fix(transcription): drop whisper-hallucinated segments on silent windows

This commit is contained in:
iamdoubz committed 2026-07-10 18:51:08 -05:00
1 parent ec864c24f0
commit 469df7524f
1 file changed
+31
+31
View File
@@ -87,6 +87,17 @@ fn resolve_language(requested: Option<&str>, multilingual: bool) -> Option<Strin
}
}
/// Segments whisper.cpp itself flags as more likely silence than speech are
/// dropped rather than emitted (see `run_full`) — whisper.cpp's CLI ships
/// this same 0.6 default for `--no-speech-thold`.
#[cfg(feature = "cpu-transcription")]
const NO_SPEECH_THRESHOLD: f32 = 0.6;
#[cfg(feature = "cpu-transcription")]
fn is_likely_speech(no_speech_probability: f32) -> bool {
no_speech_probability <= NO_SPEECH_THRESHOLD
}
/// whisper.cpp-backed transcriber (CPU baseline; GPU via Cargo features).
#[cfg(feature = "cpu-transcription")]
pub struct WhisperTranscriber {
@@ -185,6 +196,15 @@ impl WhisperTranscriber {
if text.is_empty() {
continue;
}
// whisper.cpp's own `no_speech_thold` gate is a no-op (unimplemented
// upstream as of whisper-rs 0.16 / whisper.cpp v1.3.0+), so silent/
// near-silent windows still decode — and greedy short-window decode
// reliably hallucinates a short filler word ("you", "Thank you.")
// instead of emitting nothing. Drop those ourselves: matches
// whisper.cpp's own CLI default threshold for "this was silence".
if !is_likely_speech(seg.no_speech_probability()) {
continue;
}
// Whisper timestamps are centiseconds (10ms units).
let start_ms = offset_ms + seg.start_timestamp().max(0) as u64 * 10;
let end_ms = if single_segment {
@@ -383,6 +403,17 @@ mod tests {
assert_eq!(audio_ctx_for_window(60 * 16_000), 1500); // 60s window
}
#[test]
fn is_likely_speech_drops_high_no_speech_probability_windows() {
// Silence/near-silence: whisper.cpp's own greedy hallucination case
// ("you", "Thank you.") on an otherwise-quiet window.
assert!(!is_likely_speech(0.9));
assert!(!is_likely_speech(NO_SPEECH_THRESHOLD + 0.01));
// Confident speech kept, including right at the threshold.
assert!(is_likely_speech(0.0));
assert!(is_likely_speech(NO_SPEECH_THRESHOLD));
}
/// GPU spike (opt-in): times whisper.cpp on a chosen backend against a real
/// model + wav. With `--features vulkan` and `WA_BACKEND=intel` (or nvidia/amd)
/// whisper.cpp offloads to the GPU; `WA_BACKEND=cpu` is the baseline. Run: