New crates/transcription/src/streaming/ module with:
- VadChunker trait: Send-bound, object-safe, push/flush/reset/
next_sample_index. Same surface a future Silero backend will
present, so live.rs wiring does not change when Silero drops in.
- VadChunk type: (start_sample: u64, samples: Vec<f32>) for
commit-policy sample-offset bookkeeping in #24.
- RmsVadChunker: fallback backend the plan permits while the
ort 2.0.0-rc.10 vs rc.12 ecosystem conflict blocks silero-vad-rust
/ voice_activity_detector. Tuned to match the existing
evaluate_speech_gate behaviour (enter 0.003, exit 0.0014, 3-frame
onset, 500 ms silence close, 2 s max chunk).
Key behavioural properties, each backed by a test:
- pure silence emits nothing
- samples between exit and enter thresholds never trigger onset
- a single loud frame does not start a chunk (sustained speech only)
- sustained speech followed by silence emits exactly one chunk
- hysteresis: a dip between enter and exit does not split a chunk
- max_chunk_samples caps continuous speech (Whisper never fed > 2 s)
- flush surfaces in-flight speech
- flush on an idle chunker emits nothing
- reset restores a clean state
- emitted chunk start_sample includes the onset buffer (Whisper sees
the speech attack, not post-onset audio)
Open items tracked as follow-ups:
1. Silero backend via direct ort rc.12 bridge (Handy-style). Blocked
on either ecosystem ort alignment or dedicated bridge session.
2. Integration into src-tauri/src/commands/live.rs. Deferred so
threshold tuning can be validated against real microphone
captures rather than synthetic constant-signal fixtures.