optional tail silence to flush the decoder - #16237
Conversation
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: naymaraq <dkaramyan@nvidia.com>
|
/ok to test 4e8ff8d |
There was a problem hiding this comment.
🟡 Changes recommended
The new flush path can fail on non-CPU tensors (device mismatch) and lacks basic input validation (e.g., negative values), which can break streaming at runtime.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR introduces an opt-in streaming.flush_size_in_secs setting that appends a configurable amount of trailing silence to each streamed utterance, enabling streaming RNNT decoders to emit any “held” tail tokens when audio stops.
Changes:
- Add
flush_size_in_secsplumbing through the streaming framing stack soMonoStreamappends trailing zeros as signal. - Read
streaming.flush_size_in_secsfrom ASR streaming pipeline configs and pass it into the request generator. - Expose the new config key in the example streaming inference YAMLs (default
0.0to preserve current behavior).
File summaries
| File | Description |
|---|---|
| nemo/collections/asr/inference/streaming/framing/mono_stream.py | Appends optional trailing silence to loaded audio before framing. |
| nemo/collections/asr/inference/streaming/framing/multi_stream.py | Threads flush_size_in_secs through continuous batched stream/request generators into MonoStream. |
| nemo/collections/asr/inference/pipelines/cache_aware_rnnt_pipeline.py | Reads streaming.flush_size_in_secs from config and passes it to the request generator. |
| nemo/collections/asr/inference/pipelines/buffered_rnnt_pipeline.py | Reads streaming.flush_size_in_secs from config and passes it to the request generator. |
| examples/asr/conf/asr_streaming_inference/cache_aware_rnnt.yaml | Adds streaming.flush_size_in_secs: 0.0 to the example config. |
| examples/asr/conf/asr_streaming_inference/buffered_rnnt.yaml | Adds streaming.flush_size_in_secs: 0.0 to the example config. |
Review details
Suppressed comments (2)
nemo/collections/asr/inference/streaming/framing/mono_stream.py:70
- The flush tail is created with
torch.zeros(...)without settingdevice, which will fail ifself.samplesis on GPU (or any non-CPU device). Create the zeros tensor on the same device/dtype asself.samples.
if self.flush_size > 0: # appended as signal, not padding, so it is not trimmed downstream
self.samples = torch.cat([self.samples, torch.zeros(self.flush_size, dtype=self.samples.dtype)])
nemo/collections/asr/inference/streaming/framing/mono_stream.py:71
- New flush behavior is introduced here, but there are no tests in this PR that exercise
flush_size_in_secs>0(e.g., verifying that extra samples are appended and that frame lengths/is_lastbehave as expected). Adding a focused unit test intests/collections/asr/inference/test_framing.pywould prevent regressions.
if self.flush_size > 0: # appended as signal, not padding, so it is not trimmed downstream
self.samples = torch.cat([self.samples, torch.zeros(self.flush_size, dtype=self.samples.dtype)])
self.n_samples = len(self.samples)
- Files reviewed: 6/6 changed files
- Comments generated: 2
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Signed-off-by: Dav Karamyan <47416614+naymaraq@users.noreply.github.com>
|
/ok to test 72b9083 |
|
[🤖]: Hi @naymaraq 👋, We wanted to let you know that a CICD pipeline for this PR just finished successfully. So it might be time to merge this PR or get some approvals. |
andrusenkoau
left a comment
There was a problem hiding this comment.
Approved, thank you!
Important
The
Update branchbutton must only be pressed in very rare occassions.An outdated branch is never blocking the merge of a PR.
Please reach out to the automation team before pressing that button.
What does this PR do ?
Adds
streaming.flush_size_in_secs, an opt-in amount of silence appended to the end of every streamso a streaming decoder can emit the tokens it is still holding when the audio stops. The default is
0.0, which appends nothing and leaves current behaviour unchanged.Collection: [ASR]
Changelog
streaming/framing/mono_stream.py:MonoStreamtakesflush_size_in_secsand appends that manyseconds of zeros to the samples in
load_audio, before framing. They are appended as signal, notpadding:
n_samplescovers them, so the frames carrying them report their full length as validand nothing downstream trims them away.
streaming/framing/multi_stream.py: threads the value throughContinuousBatchedFrameStreamerandContinuousBatchedRequestStreamerto theMonoStreamit builds, so one path serves both pipelines.pipelines/cache_aware_rnnt_pipeline.py,pipelines/buffered_rnnt_pipeline.py: readcfg.streaming.get("flush_size_in_secs", 0.0)and pass it to the request generator..getkeepsexisting YAMLs working unchanged.
conf/asr_streaming_inference/cache_aware_rnnt.yaml,buffered_rnnt.yaml: the new key, default0.0.Usage
python examples/asr/asr_streaming_inference/asr_streaming_infer.py \ --config-path=../conf/asr_streaming_inference/ \ --config-name=cache_aware_rnnt.yaml \ audio_file=<manifest.json> \ output_filename=<preds.jsonl> \ streaming.flush_size_in_secs=0.48What the parameter buys when it is turned on
nemotron-speech-streaming-en-0.6b, cache-aware RNNT, WER againstflush=0.0:Results, WER
Best value per row and benchmark in bold.
att_context_size [70,13] — 1.12 s lookahead
att_context_size [70,6] — 0.56 s lookahead
att_context_size [70,1] — 0.16 s lookahead
att_context_size [70,0] — 0.08 s lookahead
GitHub Actions CI
The Jenkins CI system has been replaced by GitHub Actions self-hosted runners.
Trusted PRs run automatically through copy-pr-bot. For an untrusted PR, a maintainer can trigger CI by commenting
/ok to test <head-sha>; repeat this after a new push if the PR remains untrusted.Before your PR is "Ready for review"
Pre checks:
PR Type:
If you haven't finished some of the above items you can still open "Draft" PR.
Who can review?
Anyone in the community is free to review the PR once the checks have passed.
Contributor guidelines contains specific people who can review PRs to various areas.
Additional Information