voice_audio_multi/docs/models/qwen3_tts.md
Fabio c36510c21e
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
Initial import: audio.cpp with Orange Pi documentation
2026-11-04 19:05:22 +01:00

15 KiB

Qwen3 TTS

Qwen3 TTS includes Base voice cloning, VoiceDesign, and CustomVoice variants. For shared conversion guidance, see Qwen3 GGUF checkpoints.

Qwen3 TTS Base

Qwen3 TTS Base is the voice-clone TTS path. It requires reference audio and, by default, its transcript. To use reference audio without a transcript, pass --request-option x_vector_only_mode=true.

Field Value
Family qwen3_tts
Model directory models/Qwen3-TTS-12Hz-1.7B-Base
Tasks tts, clon
Modes offline, streaming
Voice input Reference WAV through --voice-ref
Transcript --reference-text required unless x_vector_only_mode=true
audiocpp_cli --task tts --family qwen3_tts --model models/Qwen3-TTS-12Hz-1.7B-Base --backend cuda --text "Hello from Qwen3 TTS." --voice-ref assets/resources/b.wav --reference-text "Some call me nature. Others call me Mother Nature. I've been here for over 4.5 billion years. 22,500 times longer than you." --out out.wav

tts and clon enter the same Base synthesis implementation.

Common Options (use directly)

Option Values Default Meaning
--text text required Text to synthesize.
--voice-ref WAV path required Voice clone reference audio.
--reference-text text required by default Transcript for reference audio; optional with x_vector_only_mode=true.
--language language code empty string Text language hint.
--text-chunk-size integer chars 8192 Long-form text chunk size. Each chunk is voiced separately; with the session option qwen3_tts.stitch_decode=true the talker still runs per chunk but the codes of all chunks are voiced in one decoder pass.
--max-tokens positive integer checkpoint generation config (2048 if absent) Maximum generated speech tokens per chunk.

Qwen3 TTS CustomVoice

Qwen3 CustomVoice uses speaker ids packaged with the model. Use --request-option voice_id=Vivian to select one; legacy --speaker Vivian remains accepted. Examples use Vivian and Ryan.

Field Value
Family qwen3_tts
Model directory models/Qwen3-TTS-12Hz-1.7B-CustomVoice
Task tts
Modes offline, streaming
Voice input Built-in speaker id through --speaker
Style control Optional instruction through --instruct
External voice WAV Not used by this path
audiocpp_cli --task tts --family qwen3_tts --model models/Qwen3-TTS-12Hz-1.7B-CustomVoice --backend cuda --text "Hello from a custom voice." --speaker Vivian --instruct "Very happy." --out out.wav

Common Options (use directly)

Option Values Default Meaning
--text text required Text to synthesize.
--speaker packaged speaker name required Built-in speaker id, such as Vivian or Ryan.
--instruct text empty string Style or emotion instruction.
--language language code empty string Text language hint.
--text-chunk-size integer chars 8192 Long-form text chunk size. Each chunk is voiced separately; with the session option qwen3_tts.stitch_decode=true the talker still runs per chunk but the codes of all chunks are voiced in one decoder pass.
--max-tokens positive integer checkpoint generation config (2048 if absent) Maximum generated speech tokens per chunk.

Qwen3 TTS VoiceDesign

Qwen3 VoiceDesign creates a voice from an instruction. It does not require a speaker reference WAV.

Field Value
Family qwen3_tts
Model directory models/Qwen3-TTS-12Hz-1.7B-VoiceDesign
Tasks tts, vdes
Modes offline, streaming
Voice input Instruction text through --instruct
Reference audio Not required
audiocpp_cli --task vdes --family qwen3_tts --model models/Qwen3-TTS-12Hz-1.7B-VoiceDesign --backend cuda --text "Hello from a designed voice." --instruct "A warm adult narrator" --out out.wav

tts and vdes enter the same VoiceDesign synthesis implementation.

Common Options (use directly)

Option Values Default Meaning
--text text required Text to synthesize.
--instruct text empty string Optional voice design instruction.
--language language code empty string Text language hint.
--text-chunk-size integer chars 8192 Long-form text chunk size. Each chunk is voiced separately; with the session option qwen3_tts.stitch_decode=true the talker still runs per chunk but the codes of all chunks are voiced in one decoder pass.
--max-tokens positive integer checkpoint generation config (2048 if absent) Maximum generated speech tokens per chunk.

Qwen3 TTS Streaming

All three TTS variants accept --mode streaming. Audio is decoded and emitted while speech tokens are still being generated, rather than after the complete utterance. The first audio chunk contains one codec frame (80 milliseconds at 24 kHz). Subsequent chunks double up to the configured stream_frames_per_event maximum: with the default 12, the sequence is 1, 2, 4, 8, 12, 12, and so on. These are audio durations, not latency guarantees. Set stream_chunk_policy=fixed to use stream_frames_per_event from the first event instead; the last event may contain fewer frames. A fixed size of 1 emits one frame at a time. The default policy is grow.

Streaming retains 25 codec frames of left context and reuses a fixed-capacity decoder graph, with a separate cached graph for the first frame. The final partial chunk is flushed at end of generation. The final audio is exactly the concatenation of the emitted chunks. Streaming uses smaller codec windows than offline decoding, so waveform differences are expected; the offline decoding path is unchanged.

For the server, configure the model with "mode": "streaming" and request "stream_format": "sse" from /v1/audio/speech (streaming defaults to PCM). Audio arrives through the existing speech.audio.delta events. Base models require reference audio; the transcript can be omitted only with x_vector_only_mode=true. VoiceDesign accepts an empty instruction; CustomVoice requires a packaged speaker.

Qwen3 TTS Sampling

These sampling controls are shared by the Qwen3 TTS Base, VoiceDesign, and CustomVoice paths.

Common Options (use directly)

Option Values Default Meaning
--do-sample true, false true Enable sampling.
--temperature float 0.9 Main talker temperature; must be > 0 when --do-sample=true, ignored when false.
--top-k integer 50 Main talker top-k.
--top-p float 1.0 Main talker top-p.
--repetition-penalty float > 0 1.05 Main talker repetition penalty.
--seed integer random if omitted Sampling seed.

Request Options (use with --request-option)

Option Values Default Meaning
subtalker_do_sample bool true Enable subtalker sampling for the remaining audio codebooks.
voice_id packaged speaker name unset CustomVoice preset selection. Legacy speaker remains accepted. An explicit request option takes precedence over the structured voice's cached id.
subtalker_temperature float 0.9 Must be > 0 when subtalker_do_sample=true; ignored when false.
subtalker_top_k integer 50 Subtalker top-k.
subtalker_top_p float 1.0 Subtalker top-p.
x_vector_only_mode bool false Base voice cloning using only the reference speaker embedding, without ICL reference codec prompting.
stream_frames_per_event positive integer 12 Codec frames per fixed event, or the maximum for growing events. Smaller values reduce chunk latency but increase decoding overhead. Ignored offline.
stream_chunk_policy grow or fixed grow Grow from one frame to the configured maximum, or emit fixed-size chunks. Ignored offline.

Session Options (use with --session-option)

These options apply to Base, VoiceDesign, and CustomVoice sessions. Arena and constant-context sizes are in MiB.

cuda_perf is a preset. Explicit session options override its settings:

--session-option qwen3_tts.perf_mode=cuda_perf \
--session-option qwen3_tts.attention=eager \
--session-option qwen3_tts.packed_projections=false

In server configs, put the same keys and values in the model's session_options.

Option Values Default Meaning
qwen3_tts.mem_saver bool false Release the talker cached-step graph after each request. Voice-prompt, prefill, code-predictor, and speech-decoder caches remain reusable.
qwen3_tts.lora adapter directory or checkpoint file not set Load a PEFT Talker/Subtalker adapter at session creation. Keep adapter_config.json beside its weights. A trained custom voice may also provide speaker_embedding and tts_config.json sidecars; select its name with voice_id.
qwen3_tts.lora_scale finite float 1 Strength multiplier applied after the adapter's alpha/r scaling. Speaker embedding replacements are not scaled.
qwen3_tts.perf_mode off, flash_attention, cuda_perf off Preset. off keeps normal defaults; flash_attention selects flash attention. cuda_perf also selects packing, optimized cache writes, F16 KV and convolution weights, stateful streaming decoding, and KV alignment 256. Explicit options override the preset.
qwen3_tts.attention mixed, auto, eager, flash mixed mixed uses manual prefill and contiguous-K/V flash cached decoding for the talker and code predictor, with eager speech tokenization. auto uses the shared backend policy; eager disables flash; flash uses flash with K/V views. Explicit values override the preset; cuda_perf selects flash.
qwen3_tts.packed_projections bool false; true with cuda_perf Pack QKV and gate/up projections in the talker and code predictor without changing weight dtype.
qwen3_tts.kv_cache_write standard, optimized standard; optimized with cuda_perf Optimized cache views and I64 indices allow backend fusion where supported; no CUDA-version requirement.
qwen3_tts.kv_cache_type f32, f16 f32; f16 with cuda_perf Talker and code-predictor KV storage. F16 reduces cache memory and may change numerical results. Explicit values override the preset.
qwen3_tts.talker_kv_cache_alignment int ≥ 1 1; 256 with cuda_perf Round talker KV capacity to this many rows. Alignment 1 disables padding. Explicit values override the preset. Larger alignments may use more memory and change numerical results.
qwen3_tts.stream_decoder windowed, stateful windowed; stateful with cuda_perf GGML streaming decoder. stateful carries convolution and attention history and caches graphs for exact chunk lengths. Uses more graph memory and can change audio.
qwen3_tts.stitch_decode bool false Voice the concatenated speech codes of all text chunks in one decoder pass instead of voicing each chunk separately. Per-chunk voicing voices the voice-clone reference once per chunk and zeroes the stateful vocoder cache at every chunk boundary (measured on RK3588, 300 characters, 22.5 s reference: 7 vocoder runs for 159.9 s against 1 run for 57.5 s); the stitched pass costs device memory proportional to the utterance, since one decode call builds a vocoder graph sized by its frame count.
qwen3_tts.voice_prompt_cache_slots nonnegative integer 1 Cached voice-clone prompts; 0 disables prompt caching.
qwen3_tts.weight_type native, f32, f16, bf16, q8_0 native Talker weight storage fallback.
qwen3_tts.talker_weight_type native, f32, f16, bf16, q8_0 inherits weight_type Explicit talker weight storage override.
qwen3_tts.speech_encoder_weight_type native, f32, f16, bf16, q8_0 native Reference speech encoder matmul weight storage.
qwen3_tts.speech_decoder_weight_type native, f32, f16, bf16, q8_0 native Speech decoder matmul weight storage.
qwen3_tts.conv_weight_type native, f32, f16 f32; f16 with cuda_perf Speech tokenizer and speaker encoder convolution weight storage.
qwen3_tts.talker_graph_arena_mb positive integer 32 Talker graph arena.
qwen3_tts.speech_encoder_graph_arena_mb positive integer 32 Reference speech encoder graph arena.
qwen3_tts.speech_decoder_graph_arena_mb positive integer 32 Speech decoder graph arena.
qwen3_tts.speaker_encoder_graph_arena_mb positive integer 32 Speaker encoder graph arena.
qwen3_tts.talker_constant_context_mb positive integer 4 Talker constant tensor context.
qwen3_tts.code_predictor_constant_context_mb positive integer 4 Code predictor constant tensor context.
qwen3_tts.speech_decoder_constant_context_mb positive integer 4 Speech decoder constant tensor context.
qwen3_tts.exec_plan JSON object of component plans, encoded as a string {} {"speech_decoder":{"impl":"rknn","artifacts":{"main":"/models/decoder.rknn","first":"/models/decoder-first.rknn","window":"/models/decoder-window.rknn"}}} selects the NPU decoder and skips GGML decoder weights. main is required; first optionally uses a smaller engine for the first streaming group; window optionally streams with window semantics. No decoder-specific params. See component execution plans.

Rockchip NPU decoder

The speech decoder stage can run on a Rockchip NPU through librknnrt instead of ggml. The path is opt-in at build time:

cmake -S . -B build -DENGINE_ENABLE_RKNN=ON \
  -DENGINE_RKNN_INCLUDE_DIR=/usr/local/include \
  -DENGINE_RKNN_LIBRARY=/usr/lib/librknnrt.so

The .rknn must be the stateful fp16 vocoder export for the same checkpoint and target SoC: inputs audio_codes, freqs_in, cache_valid, cache_in; outputs audio_values and cache_out; 1920 samples per token at 24 kHz, with the convolution and KV cache carried across steps in the graph I/O. The optional first-group model runs the first token group at a smaller compiled batch; the cache layout is batch-independent, so its cache feeds the main model directly. The optional window model (artifacts.window) streams with the ggml path's window semantics instead: every event runs a full decode of its whole [left context + new] window from a zeroed cache and drops the context frames' audio, so each event reproduces the CPU streaming function exactly (25 frames re-voiced per event, at one NPU step of 25 + frames_per_event tokens). Naming the same file as main aliases it: the resident engine covers the default 25 + 12 window; a dedicated export compiled at --codes-length 25 + stream_frames_per_event is cheaper per event. Offline decoding keeps using main. A .rknn is compiled per SoC and is not portable between chips. Build the file with tools/rknn/prepare_qwen3_tts_rknn_vocoder.py and see the Rockchip NPU build guide for the toolkit venv, the measured numbers, and the limits of this path. This path is opt-in and validated only on RK3588.