You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 95febe0
Browse filesBrowse the repository at this point in the historyBrowse files
fix(tts): add streamFlush() API and drain Kokoro buffer on streamStop (#1197)
## Description
`Kokoro::stream` hung when the buffer held content without an
end-of-sentence character: the timer-based force-flush (after
`kStreamMaxSkippedIterations` idle iterations) tried to extract 0
characters, so the loop reset its skip counter without draining anything
and `streamStop(false)` never returned. The same threshold also fired
mid-token for LLM-style streaming, partitioning sentences before they
finished.
Replace the threshold with caller-driven flushing:
- New `streamFlush()` API. Caller signals "drain what's currently
buffered, EOS or not" — typically right before `streamStop(false)` for
normal apps that ended on un-terminated content.
- `streamStop(false)` now drains automatically (equivalent to
`streamFlush()` plus auto-stop on empty buffer), so it's guaranteed to
return even if the trailing tail has no EOS.
- LLM-style callers feeding partial tokens never call `streamFlush()` —
model punctuation drives natural EOS partitioning, and the residual tail
is drained by `streamStop(false)` when generation completes.
The skipped-iteration force-flush and its tuning constant
`kStreamMaxSkippedIterations` are removed.
### Introduces a breaking change?
- [ ] Yes
- [x] No
### Type of change
- [x] Bug fix (change which fixes an issue)
- [ ] New feature (change which adds functionality)
- [ ] Documentation update (improves or adds clarity to existing
documentation)
- [ ] Other (chores, tests, code style improvements etc.)
### Tested on
- [ ] iOS
- [x] Android
### Testing instructions
1. Build & run `apps/speech` on Android.
2. Open `Text to Speech - LLM Streaming`.
3. Tap Generate and let the story play through.
4. Tap Stop mid-stream — verify it returns promptly without hanging.
### Related issues
Fixes#1153
Copy file name to clipboardExpand all lines: docs/docs/03-hooks/01-natural-language-processing/useTextToSpeech.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -85,7 +85,7 @@ The module provides two ways to generate speech using either raw text or pre-gen
85
85
86
86
1.[**`forward({ text, speed, phonemize })`**](../../06-api-reference/interfaces/TextToSpeechType.md#forward): Generates the complete audio waveform at once. Returns a promise resolving to a `Float32Array`.
87
87
2.[**`stream({ speed, phonemize, stopAutomatically, onNext, ... })`**](../../06-api-reference/interfaces/TextToSpeechType.md#stream): An async generator-like functionality (managed via callbacks like `onNext`) that yields chunks of audio as they are computed.
88
-
This is ideal for reducing the "time to first audio" for long sentences. You can also dynamically insert text during the generation process using `streamInsert(text)`and stop it with `streamStop(instant)`.
88
+
This is ideal for reducing the "time to first audio" for long sentences. You can also dynamically insert text during the generation process using `streamInsert(text)`, force-partition trailing content without an end-of-sentence character via `streamFlush()`, and stop the stream with `streamStop(instant)`.
89
89
90
90
:::tip Recommendation
91
91
In most cases, the **`stream()`** method is recommended over `forward()`. It significantly reduces latency by allowing audio playback to begin as soon as the first chunk is synthesized, rather than waiting for the entire text to be processed.
Copy file name to clipboardExpand all lines: docs/docs/04-typescript-api/01-natural-language-processing/TextToSpeechModule.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -49,7 +49,7 @@ The module provides a way to generate speech using either raw text or pre-genera
49
49
50
50
1.[**`forward(text, speed, phonemize)`**](../../06-api-reference/classes/TextToSpeechModule.md#forward): Generates the complete audio waveform at once. Returns a promise resolving to a `Float32Array`.
51
51
-`phonemize` defaults to `true`. When set to `false`, the input is expected to be a string of IPA phonemes.
52
-
2.[**`stream({ speed, phonemize, stopAutomatically, ... })`**](../../06-api-reference/classes/TextToSpeechModule.md#stream): An async generator that yields chunks of audio as they are computed. This is ideal for reducing the "time to first audio" for long sentences. In contrast to `forward`, it enables inserting text chunks dynamically into processing buffer with [**`streamInsert(text)`**](../../06-api-reference/classes/TextToSpeechModule.md#streaminsert) and allows stopping generation early with [**`streamStop(instant)`**](../../06-api-reference/classes/TextToSpeechModule.md#streamstop).
52
+
2.[**`stream({ speed, phonemize, stopAutomatically, ... })`**](../../06-api-reference/classes/TextToSpeechModule.md#stream): An async generator that yields chunks of audio as they are computed. This is ideal for reducing the "time to first audio" for long sentences. In contrast to `forward`, it enables inserting text chunks dynamically into the processing buffer with [**`streamInsert(text)`**](../../06-api-reference/classes/TextToSpeechModule.md#streaminsert), force-partitioning trailing un-terminated content via [**`streamFlush()`**](../../06-api-reference/classes/TextToSpeechModule.md#streamflush), and stopping generation early with [**`streamStop(instant)`**](../../06-api-reference/classes/TextToSpeechModule.md#streamstop).
0 commit comments