Skip to main content

Crate voxora_vad

Crate voxora_vad 

Source
Expand description

Energy-based voice activity detection (VAD) for the voxora workspace.

voxora-vad ships a tiny, deterministic, CPU-only VAD implementation that downstream crates (batch ASR front-ends, live-transcription UIs, future speaker-diarization pre-filters) can pull in without taking on a heavyweight ML dependency. The detector slides a window over a stream of mono PCM samples, computes the RMS energy in each frame, and emits VadSegments whenever the speech/silence state machine transitions past the configured debounce windows.

§When to use this crate

Use caseNotes
Trimming silence before a batch ASR passPass the audio through EnergyVad first, then send only the speech runs to the engine. Caveat: trimming changes sample alignment, so re-stamp timestamps against the trimmed audio before showing UI timings.
Live-transcription UIsPoll VadSegmenter::next_segment on each chunk of microphone PCM and only wake the decoder when is_speech == true. The ML-based Silero VAD via onnxruntime is a planned follow-up but is not part of this crate.
Pre-filtering before diarizationSpeaker diarization (“who spoke when”) composes on top of VAD — the diarizer only sees the speech runs, not the gaps. Diarization itself is tracked separately (see docs/ROADMAP.md Phase 7).

The fixtures module ships the canonical 16 kHz mono PCM fixtures (SILENCE_1S, sine_440hz_500ms) used by the example and the integration tests. They are kept byte-identical to voxora_testkit::audio::* so a downstream consumer can swap the source trivially; the local copy is here because voxora-testkit is publish = false and cargo publish cannot resolve workspace-only crates as dev-dependencies.

Integration with voxora_traits::StreamingAsrEngine is intentionally not included in this crate: streaming engines are still gated upstream on whisper-rs / candle incremental-decoding APIs (issues #50/#51). When the first streaming engine lands, a future patch will add a StreamingVadSegmenter extension that drives the decoder incrementally.

§Example

use voxora_vad::{EnergyVad, VadSegmenter, VadSegment};

let mut vad = EnergyVad::new();

// Feed a chunk of PCM. Returns a segment iff this call
// closed a speech/silence run; `None` while the detector is
// still inside an open run.
let samples: Vec<f32> = vec![0.0; 16_000];
let seg: Option<VadSegment> = vad.next_segment(&samples);
assert!(seg.is_none()); // pure silence → no transition

// At end-of-stream, drain any trailing open run.
let trailing: Option<VadSegment> = vad.flush();

§Crate conventions

  • Zero non-workspace runtime deps — the detector is pure f32 arithmetic over a sliding window, so the crate stays hermetic on a fresh cargo build. Matches the “tiny pure-Rust” stance of voxora-config.
  • Deterministic, no #[ignore] tests — the crate has no model/audio fixtures, so every test runs unconditionally and the CI test job stays fast.
  • ASR-specific — not a generic signal-processing library. VAD here is a building block for the voxora speech-recognition stack only.

Modules§

fixtures
Inline audio fixtures used by the example and the integration tests.

Structs§

EnergyVad
Energy-based voice activity detector.
EnergyVadBuilder
Builder for EnergyVad with a fluent API.
EnergyVadConfig
Tuning knobs for EnergyVad.
VadSegment
One run of speech or silence inside a stream of PCM samples.

Enums§

VadConfigError
All errors that may occur while building an energy-based voice-activity detector.

Traits§

VadSegmenter
Voice-activity detector.