Repository navigation
Fix merge_vad emitting pure-silence segments - #3862
lingfengyao wants to merge 1 commit into
Conversation
LauraGPT
left a comment
There was a problem hiding this comment.
Reproduced on main 20f26b7c and checked head 8ee109bb.
- The new regression file fails on main (3 failed / 5 passed). On this head,
test_merge_vad_silence.pyplustest_merge_vad_length.pypass all 12 test methods, including the seeded randomized coverage checks. - An independent L20Z check exercised the actual
slice_padding_audio_sampleswith CUDA audio tensors and CUDA reductions in FP32 and BF16. The reported input produces three pure-silence slices on main in both dtypes. All 36 head cases (six interval layouts, three maximum lengths, two dtypes) preserve each speech sample exactly once and emit no pure-silence slices. - This is bounded synthetic segmentation/slicing validation, not a pretrained ASR/CER evaluation. I have not independently verified the AISHELL accuracy table in the PR.
Two integration gates remain: this exact head currently has no hosted workflow/check run, and the existing full-project suite gate is unresolved because its online Conformer test requires unavailable cached weights. The current workflow path filters do not cover this VAD utility/new test. I am keeping this PR open; the focused CPU/CUDA results are not a full-suite or CI pass.
Thanks for the review! Please let me know if there are any additional tests or changes you would like me to make to move this PR forward. I would be happy to help. |
Summary
With
vad_model="fsmn-vad"andmerge_vad=True(the SenseVoice demo/README default),merge_vadcan return segments that contain no speech: the pause between two VAD segments, or[0, first_speech_start]. These are sent to the ASR model, and paraformer-zh decodes them into garbage (i the the the the the,二 零 一 年 一 一 一 一 一,the alxxxxxxxxxxxxxxy YY) that ends up in the transcript.Cause: segment starts and ends are sorted into one list, and the loop checks the distance to the next point but cuts at the current one. When consecutive speech segments are each close to
max_length, it cuts atA.endand then atB.start, emitting the pause[A.end, B.start]. Becausebgstarts at 0,[0, first_start]can be emitted too.Fix: after the existing merge loop, drop spans that overlap no VAD segment (one linear pass). The signature and return format are unchanged.
Type of change
Validation
python -m compileall funasr examples testsAdded
tests/test_merge_vad_silence.py. It covers the example above, leading silence, empty input, a single segment, a single segment longer thanmax_length, and randomized inputs (no pure-silence span; every VAD segment covered exactly once). Onmain, 3 of these tests fail; with this change all pass.The existing
tests/test_merge_vad_length.pyand the othervad/auto_modeltests pass.End-to-end on long-form AISHELL-1 test: 20 speakers, 120 files of ~5 min (11.4 h) with random pauses between sentences.
AutoModel(..., vad_model="fsmn-vad")on an A100, whole-file CER, 95% CI from a paired bootstrap over speakers.For reference, VAD only without merging gives 1.96 (paraformer-zh) and 2.60 (SenseVoiceSmall).
User impact
This affects anyone using
merge_vad=Trueon long audio, which is the default in the SenseVoice demo/README. The bug shows up when speech turns are close tomerge_length_s, as in lectures, meetings and read speech. paraformer-zh users get hallucinated text inserted between sentences: 93 of the 98 silence spans above produced text, raising CER by 78%. SenseVoice mostly outputs<|nospeech|>on these spans, so it is only slightly affected, but it no longer wastes decoding on silence.Notes for reviewers
test_merge_vad_length.pyexpectations still hold.