Detect the language once for auto-detect file passes on the chunked path (D-053)

Transformers.js has no Whisper language detection and silently decoded
Danish as English whenever "Skip silence" was off or unavailable.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Lucas WintherandClaude Opus 5.5 committed 2026-10-30 14:35:09 +01:00
1 parent 3583d60847
commit dd9dfc628b
6 files changed
+112 -6

No files matched your search

+36
View File
@@ -20,6 +20,7 @@ import {
import { LONG_FORM_DEFAULTS, transcribeLongForm } from "../src/worker/longform";
import { createWhisperDeps, loadSileroVad } from "../src/worker/longform/transformers";
import { decodeClip } from "./clips";
import { detectFileLanguage } from "../src/worker/language";
import { wordErrorRate } from "./dsp";
/**
@@ -500,3 +501,38 @@ describe("long-form file pipeline accuracy (real model, real recordings)", () =>
);
}
});
// ---------------------------------------------------------------------------
// "Auto" language on the default chunked file path: Transformers.js has no
// language detection and silently decodes as English, so the worker detects
// once on the first 30 s (src/worker/language.ts) and pins it.
// ---------------------------------------------------------------------------
describe("auto language on the chunked file path (real model)", () => {
for (const clip of clips) {
test.skipIf(!available)(
`${clip.base}: detected as ${clip.language}, and the transcript stays close to the reference`,
async () => {
const reference = await Bun.file(join(AUDIO_DIR, clip.transcriptFile)).text();
const audio = await decodeClip(clip.audioFile);
const asr = await loadAsr();
const language = await detectFileLanguage(asr, audio);
expect(language).toBe(clip.language);
if (audio.length / RATE > 120) return; // detection is the point; long clips are covered above
const output = await asr(audio, {
chunk_length_s: 30,
stride_length_s: 5,
return_timestamps: true,
max_new_tokens: 440,
language,
task: "transcribe",
});
const text = ((Array.isArray(output) ? output[0] : output) as { text?: string }).text ?? "";
expect(wordErrorRate(normalize(reference), normalize(text))).toBeLessThanOrEqual(
MAX_WER_BY_CLIP[clip.base] ?? MAX_WER,
);
},
DOWNLOAD_BUDGET_MS + 60 * MS_PER_AUDIO_SECOND,
);
}
});