Some checks failed
Linux Build / Linux cpu (push) Has been cancelled
Linux Build / Linux cpu-clang (push) Has been cancelled
Linux Build / Linux vulkan (push) Has been cancelled
mac-build / macOS CPU (push) Has been cancelled
Nix Build / Nix (cpu) (push) Has been cancelled
Nix Build / Nix (vulkan) (push) Has been cancelled
windows-build / Windows CPU (push) Has been cancelled
223 lines
11 KiB
Markdown
223 lines
11 KiB
Markdown
# BreezeTTS 2
|
|
|
|
BreezeTTS 2 is a GGUF TTS family for instruction-conditioned speech and
|
|
prompt-audio voice cloning. The default package is Q8_0.
|
|
|
|
## Quick Start
|
|
|
|
Download the default Q8_0 package:
|
|
|
|
```bash
|
|
python3 tools/model_manager_v2.py install breeze_tts_2_q8_0 --models-root models
|
|
```
|
|
|
|
Voice cloning:
|
|
|
|
```bash
|
|
audiocpp_cli \
|
|
--task clon \
|
|
--family breeze_tts \
|
|
--model models/Breeze-TTS-2-GGUF/breeze-tts-2-q8_0.gguf \
|
|
--backend cuda \
|
|
--text "Please read this line in a clear and natural voice." \
|
|
--voice-ref assets/resources/b.wav \
|
|
--reference-text "Some call me nature. Others call me Mother Nature. I have been here for over four and a half billion years." \
|
|
--request-option instruct="Speak clearly and naturally." \
|
|
--out breeze_tts_clone.wav
|
|
```
|
|
|
|
Voice design:
|
|
|
|
```bash
|
|
audiocpp_cli \
|
|
--task tts \
|
|
--family breeze_tts \
|
|
--model models/Breeze-TTS-2-GGUF/breeze-tts-2-q8_0.gguf \
|
|
--backend cuda \
|
|
--text "Welcome to the local voice demo." \
|
|
--request-option instruct="A warm female narrator with calm pacing and studio clarity." \
|
|
--out breeze_tts_design.wav
|
|
```
|
|
|
|
Streaming:
|
|
|
|
```bash
|
|
audiocpp_cli \
|
|
--task tts \
|
|
--mode streaming \
|
|
--family breeze_tts \
|
|
--model models/Breeze-TTS-2-GGUF/breeze-tts-2-q8_0.gguf \
|
|
--backend cuda \
|
|
--text "Welcome to the BreezeTTS 2 streaming demo." \
|
|
--request-option instruct="A confident product demo narrator with steady pacing." \
|
|
--request-option stream_frames_per_event=16 \
|
|
--out breeze_tts_stream.wav \
|
|
--out-dir breeze_tts_stream_chunks
|
|
```
|
|
|
|
## Model
|
|
|
|
| Field | Value |
|
|
|---|---|
|
|
| Family | `breeze_tts` |
|
|
| Default GGUF | `models/Breeze-TTS-2-GGUF/breeze-tts-2-q8_0.gguf` |
|
|
| Tasks | `tts`, `clon`, `vdes` |
|
|
| Modes | `offline`, `streaming` |
|
|
| Languages | `zh`, `en` |
|
|
| Voice input | Optional for `tts` and `clon`; supplied reference audio requires its transcript |
|
|
|
|
## Common Options (use directly)
|
|
|
|
| Option | Values | Default | Meaning |
|
|
|---|---|---:|---|
|
|
| `--voice-ref` | WAV path | optional | Supplied audio selects reference conditioning for `tts` or `clon`; `clon` does not enforce its presence. |
|
|
| `--reference-text` | text | required with reference codes | Transcript for prompt audio. |
|
|
|
|
## Request Options (use with `--request-option`)
|
|
|
|
| Option | Values | Default | Meaning |
|
|
|---|---|---:|---|
|
|
| `reference_text` | text | required with reference codes | Request-option alias for the prompt-audio transcript. |
|
|
| `instruct` | text | `Speak clearly and naturally.` | Voice or style instruction. Legacy `instruction` remains accepted. |
|
|
| `text_chunk_size` | integer > 0 | `600` | Long-form text chunk size. |
|
|
| `text_chunk_mode` | `default`, `tag_aware`, `japanese`, `endline` | `default` | Framework text chunk mode. |
|
|
| `max_tokens` | integer > 0 | `1500` | Maximum generated acoustic frames. |
|
|
| `guidance_scale` | float >= 0 | `1.0` | Classifier-free guidance scale. |
|
|
| `temperature` | float > 0 | `0.9` | Backbone sampling temperature. |
|
|
| `depth_temperature` | float > 0 | `0.9` | Depth decoder sampling temperature. |
|
|
| `top_k` | integer | `50` | Top-k sampling limit; nonpositive values disable top-k filtering. |
|
|
| `top_p` | float > 0 | `1.0` | Positive nucleus sampling cutoff; values >=1 disable nucleus filtering. |
|
|
| `seed` | integer >= 0 | `0` | Generation seed. |
|
|
| `stream_frames_per_event` | integer > 0 | `16` | Maximum codec frames per audio event, or fixed event size with `stream_chunk_policy=fixed`. |
|
|
| `stream_chunk_policy` | `grow`, `fixed` | `grow` | Emit 1, 2, 4, ... frames up to the configured maximum, or use the fixed size from the first event. |
|
|
| `stream_lookahead_margin` | integer >= 0 | `0` | Additional trailing frames buffered before emission. The decoder is causal; zero minimizes latency. |
|
|
|
|
## Session Options (use with `--session-option`)
|
|
|
|
| Option | Values | Default | Meaning |
|
|
|---|---|---:|---|
|
|
| `breeze_tts.reference_cache_slots` | integer >= 0 | `1` | Prepared reference-audio cache slots. |
|
|
| `breeze_tts.attention` | `auto`, `flash`, `eager` | `auto` | Attention kernel. `auto` uses flash except on Volta/Turing GPUs (e.g. V100), where it falls back to eager to avoid missing MMA kernels. |
|
|
| `breeze_tts.bf16_activations` | `auto`, `on`, `off` | `auto` | Reference bf16 activation rounding (and, on Metal, the bf16 KV cache). `auto` is on for CUDA/HIP/Vulkan and off on Metal; see [Metal and the reference bf16 path](#metal-and-the-reference-bf16-path). |
|
|
| `weight_type` | `native`, `f32`, `f16`, `bf16`, `q8_0`, `q4_0`, `q4_k` | `native` | Weight storage type; quantized types convert at load time from the BF16 package. |
|
|
| `breeze_tts.perf_mode` | `off`, `cuda_perf` | `off` | Decode preset; see [performance controls](#performance-controls). |
|
|
| `breeze_tts.fused_depth` | `true`, `false` | `true` | One backend graph per frame for the depth codebooks, with graph sampling. |
|
|
| `breeze_tts.direct_prefill` | `true`, `false` | `true` | Offline prefill writes straight into the decode cache. |
|
|
| `breeze_tts.skip_cache_round` | `true`, `false` | `true` | Skips the identity bf16 re-rounding of the F16 KV cache. |
|
|
| `breeze_tts.round_bf16_fusion` | `true`, `false` | `false` | On CUDA, fold the bf16 activation rounding into the RMS-norm, add and SwiGLU kernels that produce it. Output is bit-identical; it only saves kernel launches. Other models are unaffected. |
|
|
| `breeze_tts.batched_cfg` | `true`, `false` | `false` | Decode both CFG backbone branches as one batch-2 step on CUDA. |
|
|
|
|
For long-form generation without reference audio, the first text chunk's generated
|
|
audio codes and text serve as a fixed voice reference for subsequent chunks. This
|
|
applies to offline and streaming generation, preserves the instruction, and avoids
|
|
independently selecting a voice at every text boundary. Single-chunk requests and
|
|
requests with supplied reference audio are unchanged. The reference lasts only for
|
|
the current request; later chunks have additional reference-prefill work.
|
|
|
|
BreezeTTS streaming is incremental by default. It emits audio events from the
|
|
generated codec-frame stream instead of waiting for a whole text chunk. For the
|
|
OpenAI-compatible speech endpoint, pass streaming options inside the request
|
|
`options` object:
|
|
|
|
```json
|
|
{
|
|
"model": "breeze-stream",
|
|
"input": "Welcome to the BreezeTTS 2 streaming demo.",
|
|
"stream": true,
|
|
"stream_format": "sse",
|
|
"response_format": "pcm",
|
|
"options": {
|
|
"instruct": "A confident product demo narrator with steady pacing.",
|
|
"stream_frames_per_event": "16",
|
|
"stream_chunk_policy": "grow",
|
|
"stream_lookahead_margin": "0"
|
|
}
|
|
}
|
|
```
|
|
|
|
> **Streaming playback:** The default `grow` policy with zero lookahead lowers
|
|
> time to first audio, but small early chunks may cause playback underruns or
|
|
> audible clicks on slow devices. If this occurs, try `stream_chunk_policy=fixed`
|
|
> with `stream_frames_per_event=16` and `stream_lookahead_margin=12`, at the cost
|
|
> of higher initial latency. Offline generation is unaffected.
|
|
|
|
Quantized weight storage is the largest measured speedup and applies to CUDA
|
|
and HIP alike: `q8_0` cut the fixed 100-token regression case from RTF ~1.5 to
|
|
~0.95 on gfx1151 and from ~0.77 to ~0.56 on an RTX 2080 Ti, and `q4_k` reached
|
|
~0.84 / ~0.49 respectively, with no audible quality regression in the Chinese
|
|
voice-design regression cases. Counter to intuition, fp32 is the one
|
|
configuration known to be *worse* for this model (mispronunciations and
|
|
runaway repetition), because the model is trained and tuned in bf16.
|
|
|
|
## Performance controls
|
|
|
|
`breeze_tts.perf_mode` defaults to `off`, which uses the normal defaults
|
|
below. The opt-in `cuda_perf` preset additionally enables CUDA batched CFG.
|
|
Explicit session options override either preset. These three defaults apply on
|
|
CUDA, Vulkan and Metal; other backends keep their original paths. Cache-round
|
|
skipping also requires an eligible bf16-rounded F16 cache and flash attention.
|
|
Batched CFG and rounding fusion remain CUDA-only.
|
|
|
|
| Session option | `off` | `cuda_perf` | Effect |
|
|
|---|---|---|---|
|
|
| `breeze_tts.fused_depth` | `true` | `true` | Decodes the 15 residual codebooks of a frame in one backend graph. CFG mixing, temperature, top-k/top-p and sampling run on the device, and only the sampled tokens return to the host. |
|
|
| `breeze_tts.direct_prefill` | `true` | `true` | Offline generation prefills the backbone straight into the decode cache, as streaming does, instead of exporting the KV state to host floats and importing it back. |
|
|
| `breeze_tts.skip_cache_round` | `true` | `true` | With the bf16 reference path, an F16 KV cache and flash attention, skips re-rounding the whole cache to bf16 after each update. The K/V rows are already bf16-rounded when written, so the pass is an identity. |
|
|
| `breeze_tts.batched_cfg` | `false` | `true` | With `guidance_scale` other than 1, decodes the conditional and unconditional backbone branches as one batch-2 step, so the backbone weights are read once per frame. |
|
|
|
|
On CUDA, the fused depth graph uses the per-codebook path's torch random draws,
|
|
so for the same seed it normally reproduces `fused_depth=false` token for token. Its
|
|
temperature scaling and f32 ranking round differently, which can change a sample only when
|
|
two candidates are tied to within float precision. It replaces the
|
|
per-codebook depth runtimes rather than adding to them, so peak VRAM stays
|
|
close to the per-codebook path, with a small VRAM increase possible.
|
|
`direct_prefill` removes the KV host round trip. `skip_cache_round` preserves
|
|
the stored cache values, but changing attention input types can change backend
|
|
rounding. `batched_cfg` changes matmul accumulation order,
|
|
so CFG output is not bit-identical to the two-runtime path. Vulkan/Metal fused
|
|
depth uses a different random-draw mapping and can change seeded output.
|
|
|
|
```text
|
|
--session-option breeze_tts.perf_mode=cuda_perf
|
|
```
|
|
|
|
To use the per-codebook depth and host KV-transfer paths, disable the three defaults:
|
|
|
|
```text
|
|
--session-option breeze_tts.fused_depth=false \
|
|
--session-option breeze_tts.direct_prefill=false \
|
|
--session-option breeze_tts.skip_cache_round=false
|
|
```
|
|
|
|
## Metal and the reference bf16 path
|
|
|
|
The official BreezeTTS 2 inference rounds activations to bf16 at every decoder
|
|
stage and keeps a bf16 KV cache. CUDA, HIP and Vulkan match that by default; the
|
|
casts are cheap enough there. On Metal the same rounding costs a visible share
|
|
of the AR loop — even after adding the fused round-to-bf16 unary op for Metal
|
|
(which removes the f32 -> bf16 -> f32 cast pair at every rounding point) the
|
|
reference path measured roughly **20% slower on the AR component** on a Mac
|
|
mini M4, and about the same on an M4 MacBook Air — so on Metal it is **opt-in**:
|
|
|
|
```bash
|
|
# Reference bf16 parity on Metal (slower, matches the official implementation)
|
|
audiocpp_cli --task tts --family breeze_tts \
|
|
--model models/Breeze-TTS-2-GGUF/breeze-tts-2-q8_0.gguf \
|
|
--backend metal \
|
|
--text "Welcome to the local voice demo." \
|
|
--session-option breeze_tts.bf16_activations=on \
|
|
--out breeze_tts_bf16.wav
|
|
```
|
|
|
|
| Value | Behavior |
|
|
|---|---|
|
|
| `auto` (default) | on for CUDA/HIP/Vulkan, off on Metal |
|
|
| `on` | bf16 activation rounding on every GPU backend; on Metal it also switches the KV cache to bf16 |
|
|
| `off` | f32 activations; Metal/CUDA/Vulkan keep an f16 KV cache (HIP keeps bf16) |
|
|
|
|
The trade-off is real in both directions: the Metal default (`auto` -> off) is
|
|
the faster path but is the same f32 configuration this page warns about above,
|
|
so if a prompt mispronounces or collapses into repetition, re-run it with
|
|
`bf16_activations=on` before changing anything else. On non-Metal GPUs the
|
|
default already matches the reference, and `off` is only useful for A/B
|
|
measurements.
|