diff --git a/src/lib/transcription/engineImpl.native.ts b/src/lib/transcription/engineImpl.native.ts index 3caa0b3..9a9bf0b 100644 --- a/src/lib/transcription/engineImpl.native.ts +++ b/src/lib/transcription/engineImpl.native.ts @@ -196,11 +196,15 @@ export const engine: TranscriptionEngine = { // Float32Array whose `.buffer` is exactly these samples. const pcm = audio.samples.slice(); + // English-only models (".en") only do English — only pass language/translate + // for multilingual models (mirrors the web engine; keeps whisper.cpp from + // being asked to do something a .en model can't). + const multilingual = MODELS[opts.modelId].multilingual; // transcribeData returns { stop, promise }; await the promise. const { promise } = ctx.transcribeData(pcm.buffer, { // language undefined => whisper.rn auto-detects ('auto'). - language: opts.language, - translate: opts.translate ?? false, + ...(multilingual && opts.language ? { language: opts.language } : {}), + ...(multilingual ? { translate: opts.translate ?? false } : {}), }); const result = await promise; diff --git a/src/lib/transcription/engineImpl.web.ts b/src/lib/transcription/engineImpl.web.ts index 8d7bb90..e0bfb4d 100644 --- a/src/lib/transcription/engineImpl.web.ts +++ b/src/lib/transcription/engineImpl.web.ts @@ -117,13 +117,22 @@ export const engine: TranscriptionEngine = { const asr = loaded.get(opts.modelId); if (!asr) throw new Error(`Model "${opts.modelId}" is not loaded; call loadModel() first.`); - const out = await asr(audio.samples, { + // English-only Whisper models (".en") reject `language`/`task` — transformers.js + // throws "Cannot specify `task` or `language` for an English-only model" if + // either is passed. Only multilingual models accept them (translation also + // requires a multilingual model). So we add those keys ONLY when multilingual, + // and never pass an explicit `undefined` language (which trips the same check). + const genOpts: Record = { return_timestamps: true, // One window at a time; 30s matches Whisper's frame so it won't re-chunk. chunk_length_s: 30, - language: opts.language, - task: opts.translate ? 'translate' : 'transcribe', - }); + }; + if (MODELS[opts.modelId].multilingual) { + genOpts.task = opts.translate ? 'translate' : 'transcribe'; + if (opts.language) genOpts.language = opts.language; + } + + const out = await asr(audio.samples, genOpts); const segments: Segment[] = []; for (const c of out.chunks ?? []) {