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

  1. Check WebGPU support in the same browser profile (chrome://gpu, or 'gpu' in navigator on the main thread)
  2. Update the browser or enable WebGPU flags if the hardware actually supports it
  3. Accept the WASM fallback but pick a smaller/quantized whisper model to keep latency acceptable
  4. Pass device: 'wasm' explicitly to skip the probe and the warning when GPU absence is known
  5. 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

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


AI-assisted analysis of moeru-ai/airi@677329427f (2026-08-18). Data as JSON: /api/errors/3d9e8c61c6f2bd0c. Report an issue: GitHub.