Add native Voxtral realtime streaming buffer - #314
Conversation
There was a problem hiding this comment.
ℹ️ Two rough edges worth a look — one is a protocol inconsistency that affects latency metrics, the other is a fragile float tolerance in the stream config validator.
Reviewed changes — adds native Voxtral Realtime STT streaming: a VoxtralRealtimeStreamBuffer that manages audio-token interleave windows, a VoxtralRealtimeStreamSession that runs single-token greedy decode per window, an SttStreamSession adapter in voice-stt, and CLI wiring for voice listen --stream and voice realtime --stt-partials with Voxtral loaded.
VoxtralRealtimeStreamBuffer/VoxtralRealtimeStreamConfig— encodes the vLLM realtime scheduling contract: initial streaming-pad prefix, 80 ms raw-audio stride, lookback/lookahead windows, generated-token feedback queue, and right-pad onfinish()VoxtralRealtimeStreamSession— stateful per-token decode loop; accumulates full input-token prefix on each step (KV cache deferred per doc comment); routes EOS correctly;output_tokensnever includes EOS indecode_textSttStreamSession<'a>enum +VoxtralRealtimeSttStreamSession— resamples to 16 kHz onpush_audio, wrapsnext_step/drain_ready/finish;stream_session()onSttModelreturnsErrfor Whisperlisten --stream—record_until_interrupt_with_progresswith 80 ms progress interval; streams incremental audio to session; prints transcript with ANSI clear-line- Realtime live-turn native path — when
stt_partials+supports_native_streaming(), records with streaming session; falls back totranscribe_samplesonly if no stream result; native elapsed time accumulated across steps - Tests —
realtime_streamandrealtime_sessionunit tests with tiny synthetic config;voxtral_native_stream_smoke_transcribes_eval_recordingintegration test (ignored, requires model weights)
us.anthropic.claude-sonnet-4-6 | 𝕏
| "sample_rate": step.sample_rate, | ||
| "audio_ms": context.audio_ms, | ||
| "capture_elapsed_ms": context.capture_elapsed_ms, | ||
| "elapsed_ms": 0, |
There was a problem hiding this comment.
"elapsed_ms": 0 is hardcoded, whereas the non-native Whisper partial path (see maybe_emit_realtime_partial_transcription) computes and emits the real per-step inference wall time in the same conversation.item.input_audio_transcription.partial event shape. Any consumer recording latency metrics will silently get 0 for native streaming turns and a real value for Whisper turns — same field, two incompatible semantics.
The native session doesn't have a single inference-start here, but the per-step cost is already tracked in native_stream_elapsed_ms. Either propagate a per-step inference duration into NativeStreamPartialContext or emit null to make the absence explicit rather than lying with 0.
| tokenizer.audio.sampling_rate | ||
| ))); | ||
| } | ||
| if (tokenizer.audio.frame_rate - config.frame_rate()).abs() > f64::EPSILON { |
There was a problem hiding this comment.
Frame-rate equality guard uses f64::EPSILON (~2.2e-16) as tolerance. 12.5 Hz is representable exactly in IEEE 754 so this passes in practice, but the choice of machine epsilon for a physical quantity comparison is fragile — any future frame rate that isn't exactly representable (e.g. 1000.0/75.0 ≈ 13.333...) would need either exact representation or a looser guard.
Prefer a physically-meaningful epsilon like 1e-6, which covers legitimate float representations of frame rates while still catching mismatched configs (12.5 vs 25.0).

Summary
voice-voxtral.voice-sttfor Voxtral while keeping Whisper as explicit non-native-streaming.voice listen --stream, defaulting to Voxtral when no STT backend is selected.voice realtime/voice realtime-tuipartial STT through the native Voxtral stream session when Voxtral is loaded, with the finished stream used as the final transcript.eval/recordings/002.wav.Verification
cargo fmt --checkcargo test -p voice-voxtral realtime_streamcargo test -p voice-voxtral realtime_sessioncargo test -p voice-voxtralcargo test -p voice-sttcargo test -p voicecargo check -p voice-sttcargo check -p voicecargo run -q -p voice -- listen --helpcargo test -p voice-stt voxtral_native_stream_smoke_transcribes_eval_recording -- --ignored --nocaptureNotes
This is now true model-native Voxtral STT streaming through the local Rust stack. The current correctness baseline recomputes full text and audio prefix history each step; KV-cache and incremental audio encoder state are the next latency/perf slice.