feat(generator): add streaming generation API with chunked audio decode - #7
Open
mvanhorn wants to merge 3 commits into
Open
feat(generator): add streaming generation API with chunked audio decode#7mvanhorn wants to merge 3 commits into
mvanhorn wants to merge 3 commits into
Conversation
eoffermann
pushed a commit
to eoffermann/MisoTTS-fork
that referenced
this pull request
Jun 4, 2026
Brings in upstream PR MisoLabsAI#7 (MisoLabsAI#7): streaming generation API with chunked audio decode. Adds generate_stream() on the generator, examples/stream_demo.py, and tests/test_streaming_generation.py. README.md auto-merged: Windows command examples (ours) and the "Streaming generation" usage section (theirs) both retained. .gitignore unchanged by the PR.
Contributor
|
Great. I definitely want to include something like this in the repo. I'll have a look at this later. Thanks so much for contributing! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Audio can now be consumed while generation is still running.
generate_stream()yields ~2 second watermarked PCM chunks as frames decode, so playback can start after the first chunk instead of waiting for the full clip.generate()is unchanged, and no new dependencies are added: the chunked decode reuses Mimi's streaming mode from themoshipackage that is already pinned inpyproject.toml.Why this matters
The generation loop in
generator.pyis already frame-incremental (one 80 ms Mimi frame per step), but everything buffers until a single batch decode at the end. For a 10 second clip that means ~125 sequential frame generations before any audio exists.Demo
Simulated demo (the 8B model needs a CUDA GPU, so this recreates
examples/stream_demo.pyoutput rather than a live capture):Changes
generate()into_prepare_prompt()+_generate_frames().generate()consumes the same iterator and stays byte-identical in behavior, including RNG consumption order.generate().chunk_frames-sized chunks are decoded inside the streaming context. On CUDA, moshi wraps the streaming decoder in a CUDA graph captured at the first chunk's shape, so a shorter residual chunk would raise a shape mismatch. Residual frames flow through a batch tail decode instead, which also keeps total output length equal to a batch decode of the same codes.torch.inference_mode()but yielded outside it, so caller code between chunks runs with normal autograd semantics. Chunks are watermarked independently; if SilentCipher rejects a very short terminal fragment, that fragment is yielded unwatermarked with a code comment documenting the tradeoff.Testing
tests/test_streaming_generation.pycovers the frame-stacking and length-matching helpers (pure Python, no weights or GPU needed).Generatorthat: concatenated stream chunks match the batch decode length for partial-chunk, exact-multiple, and empty-generation cases; inference mode does not leak to the caller between yields; and only uniform-shape decodes happen inside the streaming context.examples/stream_demo.pyon a GPU box would be a useful review step.Mimi's
streaming()context manager is the same mechanism moshi's own server path uses for incremental decode; this PR reuses it rather than adding a new decode path.