good
This commit is contained in:
@@ -172,7 +172,7 @@ See [`.env.example`](.env.example) for a copy-paste template.
|
||||
| `FILLER_DELAY_MS` | `2500` | How long (ms) to wait for the response audio to start before playing the filler. If the reply starts earlier, the filler is dropped instead of talking over the beginning of the answer. |
|
||||
| `FILLER_GAIN_IDLE` | `1.0` | Filler gain when TTS is idle. |
|
||||
| `FILLER_GAIN_DUCK` | `0.15` | Filler gain while TTS is active (ducking). |
|
||||
| `TTS_PREBUFFER_MS` | `900` | Synthesized audio (ms) buffered on the TTS channel before the reply starts playing. Lower = the agent speaks sooner; higher = fewer drop-outs on uneven TTS chunk arrival. Only awaited at the start of a reply; mid-reply underruns resume as soon as any audio is queued again. |
|
||||
| `TTS_PREBUFFER_MS` | `450` | Synthesized audio (ms) buffered on the TTS channel before the reply starts playing. Lower = the agent speaks sooner; higher = fewer drop-outs on uneven TTS chunk arrival. Only awaited at the start of a reply; mid-reply underruns resume as soon as any audio is queued again. |
|
||||
| `TTS_PIPELINE_DEPTH` | `3` | How many TTS requests may be in flight at once. Chunks are synthesized ahead of playback and replayed in order, so each request's start-up latency hides behind the previous chunk's audio. `1` restores strictly serial synthesis. |
|
||||
| `BACKCHANNEL_ENABLED` | `true` | Master switch for during-utterance acknowledgments. |
|
||||
| `BACKCHANNEL_DIR` | `assets/backchannel` | Directory of `*.raw` backchannel PCM clips (16-bit LE mono, 44.1 kHz). |
|
||||
@@ -266,6 +266,51 @@ An unknown value panics at startup with a clear message.
|
||||
- Supports voice cloning via the `references` field.
|
||||
- Honors barge-in cancellation.
|
||||
|
||||
##### Starting the Drama 3 backend (SGLang-Omni)
|
||||
|
||||
The `fish` engine talks to an **SGLang-Omni** server running Drama 3. Start it
|
||||
with the vocoder streaming window narrowed, otherwise the vocoder emits ~3 s
|
||||
bursts and the client is forced into a large pre-buffer:
|
||||
|
||||
```bash
|
||||
sgl-omni serve \
|
||||
--model-path fishaudio/drama-3 \
|
||||
--host 0.0.0.0 --port 8000 \
|
||||
--tts_engine.gpu_memory_fraction 0.45 \
|
||||
--tts_engine.factory.max_running_requests 4 \
|
||||
--vocoder.factory.stream_followup_stride 16 \
|
||||
--vocoder.factory.stream_followup_stride_ramp "[10,12,16]"
|
||||
```
|
||||
|
||||
In this deployment the launcher is `/root/drama3/start-drama3.sh` and the server
|
||||
is kept alive by **pm2** as the process `start-drama3`:
|
||||
|
||||
```bash
|
||||
pm2 restart start-drama3 --update-env # after editing the launcher
|
||||
pm2 logs start-drama3 --lines 100 # CUDA-graph rebuild takes ~2 min at start
|
||||
```
|
||||
|
||||
The two `--vocoder.factory.*` overrides are the key part:
|
||||
|
||||
| Flag | Meaning |
|
||||
|---|---|
|
||||
| `stream_followup_stride` | Steady-state window, in codec frames (`2048` samples = `46.4 ms` each). `16` ⇒ `0.743 s` bursts; the upstream default `64` ⇒ `2.97 s`. |
|
||||
| `stream_followup_stride_ramp` | Window sizes for the first windows, as a JSON tuple. `[10,12,16]` emits a `0.464 s` then a `0.557 s` window first, so playback can start sooner. Upstream default `(10,12,32)`. |
|
||||
|
||||
Two gotchas when writing the command:
|
||||
|
||||
- The flags are **dotted keys into the pydantic config**, so they go *without* a
|
||||
`stages.` prefix — `--vocoder.factory.stream_followup_stride`, not
|
||||
`--stages.vocoder.factory.stream_followup_stride` (the latter is rejected).
|
||||
- The ramp tuple must be passed as a **JSON string** — `"[10,12,16]"` — because
|
||||
the config manager parses non-scalar paths with JSON.
|
||||
|
||||
Smaller stride = finer delivery granularity but more compute: each window
|
||||
re-decodes `stream_overlap_tokens` (default `32`) of context, so `stride 16`
|
||||
decodes 48 frames per 16 emitted. Keep the stride at or below the client's
|
||||
`TTS_PREBUFFER_MS` budget (see *Mixer & jitter buffering*) — with the defaults
|
||||
above, `TTS_PREBUFFER_MS=450` starts playback on the first window.
|
||||
|
||||
#### `kokoro` — Kokoro TTS *(stub)*
|
||||
|
||||
[`src/tts/kokoro.rs`](src/tts/kokoro.rs)
|
||||
@@ -630,6 +675,12 @@ A ready-to-use speech-to-speech example client is served at **`/mivocero`**
|
||||
(44.1 kHz, 16-bit LE mono, 20 ms frames).
|
||||
- **Chat box** — shows the user transcript (from STT) and the assistant reply
|
||||
**as it streams**, plus messages typed in the composer.
|
||||
- **Karaoke highlighting** — the assistant bubble is rendered word by word: each
|
||||
word lights up as it is *spoken*, driven by the audio playhead (the playback
|
||||
worklet reports the samples it has actually emitted). Words already spoken are
|
||||
bright, the word currently sounding is accented, and the rest stay dim. The
|
||||
rate is an estimate (`KARAOKE_CPS`, ~15 chars/s) — it only affects the visual
|
||||
highlight, never the audio.
|
||||
- **Text composer** — typing and sending a message runs a full LLM → TTS turn
|
||||
without using the microphone (`{"type":"user_text","text":…}`).
|
||||
- **Interrupt button** — flushes audio and cancels the in-flight reply
|
||||
@@ -690,13 +741,18 @@ Constants are defined in [`src/config.rs`](src/config.rs):
|
||||
`0.15`); the backchannel gain is fixed (`BACKCHANNEL_GAIN`, default `0.35`).
|
||||
Output is clamped to `i16`.
|
||||
- **Pre-buffer:** TTS playback does not start until the queue holds
|
||||
≥ `TTS_PREBUFFER_MS` (default **900 ms**) of synthesized audio. It absorbs
|
||||
≥ `TTS_PREBUFFER_MS` (default **450 ms**) of synthesized audio. It absorbs
|
||||
uneven TTS chunk arrival; lower it to start speaking sooner, raise it for fewer
|
||||
drop-outs. With pipelined synthesis (above) the pre-buffer only has to cover
|
||||
arrival jitter, not the TTS engine's per-request start-up, so it can stay
|
||||
small. Note: Drama-3 delivers ~1.08× real time in bursts every ~2.7 s, so a
|
||||
~900 ms buffer favours latency over perfect gaplessness on very long replies —
|
||||
raising it towards ~3 s is what actually removes the remaining drop-outs.
|
||||
small. Note: Drama-3 delivers ~1.04× real time, and its *granularity* is set by
|
||||
the server's vocoder window
|
||||
(`--vocoder.factory.stream_followup_stride`, in codec frames of 2048 samples =
|
||||
46.4 ms). With stride `16` and ramp `"[10,12,16]"` the first window is 10
|
||||
frames = 0.464 s, so `450 ms` starts playback on that very first window (the
|
||||
steady state then delivers a 0.743 s burst every ~0.69 s). With the upstream
|
||||
default (`64`, a 2.97 s burst every ~2.7 s) gapless playback would instead
|
||||
require a ~3 s pre-buffer.
|
||||
- **Resilient resume:** the full pre-buffer is only required at the *first*
|
||||
playback of a reply. If the queue empties mid-reply (after the 200 ms drain
|
||||
grace) playback pauses, but resumes as soon as *any* audio is queued again —
|
||||
|
||||
Reference in New Issue
Block a user