Skip to content

feat(vad): drop silent audio windows to prevent hallucinations#109

Open
JMLX42 wants to merge 5 commits into
itsmontoya:mainfrom
lx-industries:feat/vad-gated-transcription
Open

feat(vad): drop silent audio windows to prevent hallucinations#109
JMLX42 wants to merge 5 commits into
itsmontoya:mainfrom
lx-industries:feat/vad-gated-transcription

Conversation

@JMLX42

@JMLX42 JMLX42 commented Jan 20, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Applies VAD (Voice Activity Detection) filtering in the backend stream
  • Drops silent audio windows to prevent whisper hallucinations during silence
  • Improves transcription quality by only processing audio with detected speech

Dependencies

Context

This feature is used by the Friday project.


This PR was created with the assistance of an AI assistant (Claude).

Add pass-through features for GPU backends:
- cuda: NVIDIA CUDA
- metal: Apple Metal
- hipblas: AMD ROCm
- vulkan: Cross-platform Vulkan
- coreml: Apple CoreML

This allows consumers to enable GPU acceleration by adding
the appropriate feature to their Cargo.toml, e.g.:

    scribble = { version = "0.5", features = ["cuda"] }
…cases

By default, the incremental transcriber waits for 2+ segments before
emitting, treating the last segment as potentially incomplete. This
adds latency for short utterances like voice assistant commands.

The new `emit_single_segments` option (default: false) allows emitting
single segments immediately when detected. This is useful for:
- Voice assistants
- Real-time transcription
- Any application where low latency is more important than waiting
  for natural sentence boundaries

When enabled, single segments are emitted as soon as Whisper produces
them, rather than waiting for a second segment or the 30-second
force-flush timeout.
When VAD detects no speech in an audio window, skip forwarding it to
Whisper entirely. This prevents hallucinations like "Merci" or "Thank
you for watching" that Whisper produces from silence with high
confidence.

Changes:
- process_ready_windows(): skip windows where VAD returns false
- flush(): only forward final buffer if VAD detects speech

Also fixes pre-existing test compilation (missing emit_single_segments
field) and formatting issues.
Move VAD filtering from the high-level Scribble API into the backend
stream. This ensures VAD works regardless of which API consumers use
(direct backend access or high-level Scribble::transcribe).

Changes:
- WhisperStream now optionally wraps audio with VadStream when
  enable_voice_activity_detection is true
- Remove VAD wrapping from Scribble::transcribe_with_encoder() to
  avoid double-filtering
- Export VadProcessor, VadStream, VadStreamReceiver publicly
- Make VadStream methods public for use in backend

This fixes the issue where friday-daemon's direct backend usage
bypassed VAD filtering entirely.
@sidz

sidz commented Feb 17, 2026

Copy link
Copy Markdown
Contributor

Hey @JMLX42 I did a quick check and seems like start/end seconds are broken now when vad is enabled.

@itsmontoya

Copy link
Copy Markdown
Owner

This feels like a large change. I'm not sure how I feel about it

@itsmontoya

Copy link
Copy Markdown
Owner

Can you re-sync with current main?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants