fix: bound streaming VAD frame buffers#3236
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces support for exact score-aligned waveform spans in the streaming VAD model and the online wav frontend. Key changes include adding a DropCachedFrames method to manage memory, aligning VAD score frames with waveform samples in ComputeDecibel, and adding comprehensive unit tests to verify streaming buffer behavior and waveform alignment. The reviewer suggests using .get("waveforms") instead of direct dictionary access to avoid a potential KeyError when custom frontends are used.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
|
@yuekaizhang, this is ready for maintainer review when available. It addresses the remaining long-session degradation reported in #3101 after the WebSocket/speaker-state fix: the shared streaming VAD was retaining LFR context and consumed history, causing per-feed cost to grow over time. Current head
No further contributor-side blocker is currently visible. |
Summary
Fixes #3101.
Long-running streaming VAD appended every waveform frame exposed by
WavFrontendOnline, including LFR context, while score/decibel cleanup usedonly emitted VAD frames. A typical 60 ms call exposed 10 waveform frames but
emitted 6 score frames, so four stale frames accumulated per call and each
torch.catbecame progressively more expensive.This change:
frontend, without adding copy/concat work to other frontend consumers;
is emitted, while preserving absolute frame indexes.
Type of change
Validation
python -m compileall funasr examples testsFocused tests:
The new regression suite was run red before each fix and covers normal chunks,
160-sample and empty frontend final flushes, an initial zero-score chunk,
lfr_m=7/lfr_n=6, endpoint reset followed by more audio, no-endpoint historycompaction, opt-in frontend overhead, positional compatibility, and atomic
failure for misaligned waveform spans.
Real-model parity on H100:
segments and SHA-256
ccdcfd29a79c551620f56b5fe8e839bdc89b5d71c201fef5aa64794f9a798097.AutoModel.generate()produced the exact base seven segments andSHA-256
1ee13953dbd29cbf8326283542b90a98daccba8180ac487d06c2e377304d1bde.lfr_n=1/2/6, short initialchunks, and final chunk sizes from 0 to 960 samples.
Long-run H100 measurements:
The final mixed-audio two-hour soak completed 72,029 feed calls and 394
segments. Frontend tensor state remained at 5,441 elements, maximum RSS stayed
at 988,888 KiB, and GPU allocation stayed flat.
User impact
Realtime Fun-ASR-Nano WebSocket sessions no longer slow down as VAD context or
already-consumed silence accumulates. This directly targets the increasing RTF
and eventual disconnect reported after roughly one hour with speaker tracking
enabled.
Notes for reviewers
provide an exact waveform span, otherwise the model raises before mutating
history.
DynamicStreamingVAD.finalize()continues to use its existing 10 ms finalflush; empty-input public
AutoModel.generate()behavior is unchanged.