// ============================================================ // WHISPER WORKER — runs @xenova/transformers in a Web Worker // Audio never leaves the device. Model cached in IndexedDB. // ============================================================ importScripts('https://cdn.jsdelivr.net/npm/@xenova/transformers@2.17.2'); var T = self.transformers || transformers; T.env.allowLocalModels = false; T.env.useBrowserCache = true; var _pipe = null; var _loadedModel = null; async function load(modelName) { if (_pipe && _loadedModel === modelName) { console.log('[WhisperWorker] Model already loaded:', modelName); return; } console.log('[WhisperWorker] Loading model:', modelName); self.postMessage({ type: 'loading', model: modelName }); try { _pipe = await T.pipeline('automatic-speech-recognition', modelName, { progress_callback: function(p) { console.log('[WhisperWorker] Progress:', p.status, p.file, p.progress); if (p.status === 'downloading' || p.status === 'progress') { self.postMessage({ type: 'progress', file: p.file || '', progress: Math.round(p.progress || 0) }); } if (p.status === 'done' || p.status === 'ready') { self.postMessage({ type: 'progress', file: p.file || '', progress: 100 }); } } }); _loadedModel = modelName; console.log('[WhisperWorker] Model loaded successfully'); self.postMessage({ type: 'ready', model: modelName }); } catch (err) { console.error('[WhisperWorker] Load error:', err); self.postMessage({ type: 'error', message: 'Model load failed: ' + err.message }); } } self.addEventListener('message', async function(e) { var d = e.data; console.log('[WhisperWorker] Message received:', d.type); if (d.type === 'load') { try { await load(d.model || 'Xenova/whisper-tiny.en'); } catch(err) { console.error('[WhisperWorker] Load error:', err); self.postMessage({ type: 'error', message: 'Load failed: ' + err.message }); } return; } if (d.type === 'transcribe') { try { await load(d.model || 'Xenova/whisper-tiny.en'); console.log('[WhisperWorker] Starting transcription...'); var result = await _pipe(d.audio, { language: 'english', task: 'transcribe', chunk_length_s: 30, stride_length_s: 5, return_timestamps: false }); console.log('[WhisperWorker] Transcription complete'); self.postMessage({ type: 'result', text: result.text.trim() }); } catch(err) { console.error('[WhisperWorker] Transcribe error:', err); self.postMessage({ type: 'error', message: 'Transcription failed: ' + err.message }); } } }); // Log worker startup console.log('[WhisperWorker] Worker initialized');