pipecrab-vad 0.3.0

The voice-activity-detection interface for pipecrab: the VoiceActivityDetector trait that gates a pipeline on speech.
Documentation

pipecrab-vad: the voice-activity-detection interface, in two tiers.

Voice activity has two natural shapes, and this crate names both:

  • [VoiceActivityDetector] — the stage-facing capability: audio in, speech edges out ([VadEvent::SpeechStarted] / [VadEvent::SpeechStopped]). Segmenter-class engines that already speak in segments — sherpa's VAD, platform VADs — implement this directly. It is what [VadStage] drives.
  • [SpeechScorer] — the raw-model tier: a per-window speech probability. This is what a bare silero build (native ort, browser onnxruntime-web) exposes. A scorer becomes a detector through the [Debounced] adapter, which owns the windowing, threshold, and hangover.

Probabilities used to live on the one VAD trait; they moved down to [SpeechScorer]. A segmenter never has a probability to hand back, and anything downstream that wants confidence (a turn manager, prosody) composes its own [SpeechScorer] rather than leaning on the VAD to surface one.

The edge contract

Across the lifetime of a [VoiceActivityDetector], events alternate, starting with SpeechStarted: started, stopped, started, stopped, … This is a documented invariant that [VadStage] and everything downstream of it trust.

[VadStage] turns those edges into a gate: it owns a pre-roll ring and emits speech-only audio, bracketed by the edges. Note the contract this inverts — downstream of the gate, SpeechStarted precedes an utterance's audio (pre-roll included) and SpeechStopped follows its last chunk. (The older lane-discipline design emitted the edge after the chunk that triggered it; that wording is gone.) See [VadStage] for the full gate algorithm.

No runtime format detection

Both traits take an Arc<[f32]>, which carries no sample rate. Samples are interpreted as input_format(); no runtime detection is possible. The stage enforces the format fatally before any audio reaches an engine, so an engine never sees nonconforming samples through the pipeline — which is why [VadError] carries no format-mismatch variant.

Platform-neutral and wasm32-checkable: the concrete engines live elsewhere, each behind these traits, so the interface itself carries no backend dependency and compiles for the host and wasm32-unknown-unknown.