diff --git a/src/servers/api/stt/transcribe.ts b/src/servers/api/stt/transcribe.ts index 4b58f2a5..34e5a3a9 100644 --- a/src/servers/api/stt/transcribe.ts +++ b/src/servers/api/stt/transcribe.ts @@ -6,6 +6,16 @@ // // The detection must win when Whisper is confident. `spokenLanguages` only breaks ties on clips // Whisper is genuinely unsure about, where its low-confidence guess defaults to English. +// +// Both requests pass `timeout: false`. Bun's fetch aborts at 300s by default, and whisper.cpp runs at +// roughly 8x realtime, so anything over ~40 minutes of audio died with "The operation timed out" +// about 20 seconds short of the answer. AbortSignal.timeout() does not raise that ceiling — only +// disabling the built-in timeout does. + +// Bun's fetch accepts `timeout: false` to disable its built-in 300s ceiling. The DOM RequestInit +// type this project compiles against does not declare it, so widen it here rather than casting at +// each call site. +type BunRequestInit = RequestInit & { timeout?: boolean | number }; type TranscribeArgs = { file: File | Blob; @@ -52,7 +62,11 @@ export async function transcribeAudio({ detectForm.append('response_format', 'verbose_json'); detectForm.append('detect_language', 'true'); - const detectRes = await fetch(`${base}/inference`, { method: 'POST', body: detectForm }); + const detectRes = await fetch(`${base}/inference`, { + method: 'POST', + body: detectForm, + timeout: false, + } as BunRequestInit); if (!detectRes.ok) throw new Error(`Language detection failed (${detectRes.status})`); const detectJson = (await detectRes.json()) as { language?: string; @@ -93,7 +107,11 @@ export async function transcribeAudio({ transcribeForm.append('response_format', 'text'); transcribeForm.append('language', detectedLanguage); - const res = await fetch(`${base}/inference`, { method: 'POST', body: transcribeForm }); + const res = await fetch(`${base}/inference`, { + method: 'POST', + body: transcribeForm, + timeout: false, + } as BunRequestInit); if (!res.ok) throw new Error(`Transcription failed (${res.status})`); const text = (await res.text()).trim();