moeru-ai/airi · warning
[Whisper Worker] WebGPU not available, falling back to WASM
Error message
[Whisper Worker] WebGPU not available, falling back to WASM
What it means
Emitted by the Whisper transcription worker when getInstance() was asked for device 'webgpu' (the default) but detectWebGPUInWorker() found no navigator.gpu in the worker context. The worker silently downgrades: resolvedDevice becomes 'wasm' and inference proceeds on the WASM/CPU backend of transformers.js - functional but typically much slower than WebGPU.
Source
Thrown at packages/stage-ui/src/libs/workers/worker.ts:106
// Track which device was actually used (for reporting back to main thread)
let resolvedDevice: 'webgpu' | 'wasm' | 'cpu' = 'webgpu'
class AutomaticSpeechRecognitionPipeline {
static model_id: string | null = null
static tokenizer: Promise<PreTrainedTokenizer>
static processor: Promise<Processor>
static model: Promise<PreTrainedModel>
static async getInstance(progress_callback?: ProgressCallback, device: 'webgpu' | 'wasm' | 'cpu' = 'webgpu') {
this.model_id = MODEL_ID
// Auto-detect: if WebGPU was requested but unavailable, fall back to WASM
let actualDevice = device
if (device === 'webgpu') {
const hasWebGPU = await detectWebGPUInWorker()
if (!hasWebGPU) {
console.warn('[Whisper Worker] WebGPU not available, falling back to WASM')
actualDevice = 'wasm'
}
}
resolvedDevice = actualDevice
this.tokenizer ??= AutoTokenizer.from_pretrained(this.model_id, {
progress_callback,
})
this.processor ??= AutoProcessor.from_pretrained(this.model_id, {
progress_callback,
})
// NOTICE: fp16 encoder may fail on some devices/browsers. Fall back to fp32
// if the initial load fails. Decoder fp16 is known broken (see Issue #989).
// https://github.com/huggingface/transformers.js/issues/989
this.model ??= (async () => {
try {View on GitHub (pinned to 677329427f)
Solutions
- Check WebGPU support in the same browser profile (chrome://gpu, or 'gpu' in navigator on the main thread)
- Update the browser or enable WebGPU flags if the hardware actually supports it
- Accept the WASM fallback but pick a smaller/quantized whisper model to keep latency acceptable
- Pass device: 'wasm' explicitly to skip the probe and the warning when GPU absence is known
- In CI/VM environments, pin device 'wasm' so startup is deterministic
Example fix
// before WhisperWorker.getInstance(progressCallback) // device defaults to 'webgpu', warns + falls back // after const device = 'gpu' in navigator ? 'webgpu' : 'wasm' WhisperWorker.getInstance(progressCallback, device)
Defensive patterns
Strategy: fallback
Validate before calling
const device: 'webgpu' | 'wasm' = 'gpu' in navigator ? 'webgpu' : 'wasm' await WhisperWorker.getInstance(progressCallback, device)
Try / catch
try {
await loadModel({ device: 'webgpu' })
}
catch {
await loadModel({ device: 'wasm' })
} Prevention
- Probe navigator.gpu on the main thread and pass the device explicitly
- Keep quantized model variants available for WASM-only users
- Treat slow inference on WASM as expected, not a regression
When it happens
Trigger: Any WhisperWorker.getInstance(progress_callback) call (device defaults to 'webgpu') in a browser without WebGPU: Firefox, older Chrome/Safari, WebGPU disabled via flags or driver blocklist, headless/CI contexts, or workers where navigator.gpu is not exposed.
Common situations: Running stage-ui in Firefox; CI screenshot jobs without GPU; VMs and remote desktops with software rendering; Chrome blocklisting old GPU drivers; machines where users expect GPU speed but only WASM is available, so transcription feels slow.
Related errors
- [BG Removal Worker] WebGPU not available, falling back to WA
- [Whisper Worker] fp16 encoder failed, falling back to fp32:
- [Kokoro Worker] Failed with dtype=${attempt.dtype} device=${
- [WhisperAdapter] ${deviceLossCount} device-loss events recor
- Failed to ensure MediaPipe WASM assets: ${wasmOutputDir} is
AI-assisted analysis of moeru-ai/airi@677329427f (2026-08-18).
Data as JSON: /api/errors/3d9e8c61c6f2bd0c.
Report an issue: GitHub.