Skip to content

Commit cb304fd

Browse files
authored
GLM-TTS model (0xShug0#98)
* Add GLM-TTS model * Make GLM-TTS CAMPPlus pooling opt-in * Speed up GLM-TTS memory saver
1 parent e5ca1d9 commit cb304fd

59 files changed

Lines changed: 7138 additions & 56 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CMakeLists.txt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,15 @@ add_library(engine_runtime STATIC
281281
src/models/omnivoice/assets.cpp
282282
src/models/omnivoice/tokenizer_text.cpp
283283
src/models/omnivoice/audio_tokenizer.cpp
284+
src/community_models/glm_tts/assets.cpp
285+
src/community_models/glm_tts/flow.cpp
286+
src/community_models/glm_tts/frontend.cpp
287+
src/community_models/glm_tts/loader.cpp
288+
src/community_models/glm_tts/llama.cpp
289+
src/community_models/glm_tts/session.cpp
290+
src/community_models/glm_tts/prompt.cpp
291+
src/community_models/glm_tts/speech_tokenizer.cpp
292+
src/community_models/glm_tts/tokenizer_text.cpp
284293
src/community_models/outetts/assets.cpp
285294
src/community_models/outetts/dac.cpp
286295
src/community_models/outetts/llama.cpp
@@ -770,6 +779,7 @@ if (ENGINE_BUILD_WARMBENCH)
770779
endif()
771780
endfunction()
772781
782+
add_engine_warmbench(campplus_shared_default_probe tests/glm_tts/campplus_shared_default_probe.cpp)
773783
add_engine_warmbench(chatterbox_warm_bench tests/chatterbox/chatterbox_warm_bench.cpp)
774784
add_engine_warmbench(citrinet_asr_warm_bench tests/citrinet_asr/citrinet_asr_warm_bench.cpp)
775785
add_engine_warmbench(higgs_audio_stt_warm_bench tests/higgs_audio_stt/higgs_audio_stt_warm_bench.cpp)
@@ -784,6 +794,16 @@ if (ENGINE_BUILD_WARMBENCH)
784794
add_engine_warmbench(nemotron_asr_warm_bench tests/nemotron_asr/nemotron_asr_warm_bench.cpp)
785795
add_engine_warmbench(omnivoice_warm_bench tests/omnivoice/omnivoice_warm_bench.cpp)
786796
add_engine_warmbench(outetts_warm_bench tests/outetts/outetts_warm_bench.cpp)
797+
add_engine_warmbench(glm_tts_tokenizer_probe tests/glm_tts/glm_tts_tokenizer_probe.cpp)
798+
add_engine_warmbench(glm_tts_assets_probe tests/glm_tts/glm_tts_assets_probe.cpp)
799+
add_engine_warmbench(glm_tts_prompt_probe tests/glm_tts/glm_tts_prompt_probe.cpp)
800+
add_engine_warmbench(glm_tts_speech_tokenizer_probe tests/glm_tts/glm_tts_speech_tokenizer_probe.cpp)
801+
add_engine_warmbench(glm_tts_flow_probe tests/glm_tts/glm_tts_flow_probe.cpp)
802+
add_engine_warmbench(glm_tts_flow_conditioned_probe tests/glm_tts/glm_tts_flow_conditioned_probe.cpp)
803+
add_engine_warmbench(glm_tts_frontend_probe tests/glm_tts/glm_tts_frontend_probe.cpp)
804+
add_engine_warmbench(glm_tts_campplus_probe tests/glm_tts/glm_tts_campplus_probe.cpp)
805+
add_engine_warmbench(glm_tts_llama_probe tests/glm_tts/glm_tts_llama_probe.cpp)
806+
add_engine_warmbench(glm_tts_warm_bench tests/glm_tts/glm_tts_warm_bench.cpp)
787807
add_engine_warmbench(pocket_tts_warm_bench tests/pocket_tts/pocket_tts_warm_bench.cpp)
788808
add_engine_warmbench(qwen3_asr_warm_bench tests/qwen3_asr/qwen3_asr_warm_bench.cpp)
789809
add_engine_warmbench(qwen3_forced_aligner_warm_bench tests/qwen3_forced_aligner/qwen3_forced_aligner_warm_bench.cpp)

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ Community model ports live under `community_models` to make the ownership bounda
9494

9595
| Family | Task | Lang | Runtime | Contributor | What They Added |
9696
|---|---|---|---|---|---|
97+
| **glm_tts** | TTS, Clone | zh, en | GGUF | Mirek [@mirek190](https://github.com/mirek190) | [GLM-TTS](docs/community_models/glm_tts.md) zero-shot synthesis and voice cloning support |
9798
| **moss_tts_local** | TTS, Clone, Ctrl | auto, optional language hint | GGUF | [@justinjohn0306](https://github.com/justinjohn0306) | MOSS-TTS-Local Transformer v1.5 support |
9899
| **outetts** | TTS, Clone | en, ar, zh, nl, fr, de, it, ja, ko, lt, ru, es, pt, be, bn, ka, hu, lv, fa, pl, sw, ta, uk | GGUF | Mirek [@mirek190](https://github.com/mirek190) | Llama-OuteTTS-1.0-1B TTS and voice cloning support |
99100
| **vietneu_tts** | TTS, Clone | vi, en | GGUF | Phuoc [@phuocnguyen90](https://github.com/phuocnguyen90) | [VieNeu-TTS-v3-Turbo](docs/community_models/vietneu_tts.md) TTS and voice cloning support |

docs/community_models/glm_tts.md

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
# GLM-TTS
2+
3+
GLM-TTS is a zero-shot Chinese and English speech-synthesis model. The native
4+
audio.cpp path executes its Llama speech-token generator, Whisper-VQ reference
5+
encoder, Flow/DiT mel generator, CAMPPlus speaker encoder, and HiFT vocoder.
6+
Both advertised routes are reference-conditioned: provide a clean WAV and the
7+
exact words spoken in it.
8+
9+
| Field | Value |
10+
|---|---|
11+
| Family | `glm_tts` |
12+
| Model directory | `models/GLM-TTS` |
13+
| Task | `tts`, `clon` |
14+
| Modes | `offline` |
15+
| Languages | Chinese, English |
16+
| Voice input | Required reference WAV plus its exact transcript |
17+
| Output | mono 24 kHz WAV |
18+
19+
Install and prepare the official checkpoint:
20+
21+
```bash
22+
python tools/model_manager.py install glm_tts --models-dir models
23+
```
24+
25+
The installer downloads `zai-org/GLM-TTS`, converts the official Flow and HiFT
26+
PyTorch checkpoints to safetensors, prepares the ChatGLM tokenizer resources,
27+
and installs the matching CAMPPlus safetensors weights. The latter are sourced
28+
from `mlx-community/index-tts2-mlx` because the GLM-TTS repository publishes
29+
CAMPPlus as ONNX only; the native output was checked directly against that
30+
official ONNX graph.
31+
32+
Run the prepared safetensors package:
33+
34+
```bash
35+
audiocpp_cli --task clon --family glm_tts \
36+
--model models/GLM-TTS --backend cuda \
37+
--voice-ref reference.wav \
38+
--reference-text "The exact words spoken in reference.wav." \
39+
--text "Hello from GLM-TTS." \
40+
--top-k 25 --top-p 0.8 --temperature 1.0 \
41+
--seed 0 --max-tokens 256 --out glm_tts.wav
42+
```
43+
44+
The `tts` task accepts the same reference arguments. It is an alias for the
45+
same zero-shot synthesis path rather than an unconditioned preset voice.
46+
47+
## Standalone GGUF
48+
49+
After installing the package, create a standalone mixed GGUF. The
50+
autoregressive Llama group remains F16 for speech-token quality; the speech
51+
tokenizer, Flow, HiFT, and CAMPPlus groups use Q8_0:
52+
53+
```bash
54+
audiocpp_gguf \
55+
--input llama_weights=models/GLM-TTS/llm/model.safetensors.index.json \
56+
--input speech_tokenizer_weights=models/GLM-TTS/speech_tokenizer/model.safetensors \
57+
--input flow_weights=models/GLM-TTS/flow/model.safetensors \
58+
--input hift_weights=models/GLM-TTS/hift/model.safetensors \
59+
--input campplus_weights=models/GLM-TTS/frontend/campplus.safetensors \
60+
--root models/GLM-TTS \
61+
--family glm_tts \
62+
--model-spec model_specs/glm_tts.json \
63+
--type q8_0 \
64+
--keep-type "llama_weights/*=f16" \
65+
--overwrite \
66+
--output models/GLM-TTS-Q8/GLM-TTS_Q8.gguf
67+
```
68+
69+
The resulting file embeds all five tensor groups, the package specification,
70+
configs, and tokenizer sidecars. It runs from a directory containing only the
71+
GGUF:
72+
73+
```bash
74+
audiocpp_cli --task clon --family glm_tts \
75+
--model models/GLM-TTS-Q8/GLM-TTS_Q8.gguf --backend cuda \
76+
--voice-ref reference.wav \
77+
--reference-text "The exact words spoken in reference.wav." \
78+
--text "Hello from GLM-TTS." \
79+
--seed 0 --max-tokens 256 --out glm_tts_q8.wav
80+
```
81+
82+
## Controls
83+
84+
| Option | Values | Default | Meaning |
85+
|---|---|---:|---|
86+
| `--reference-text` | text | required | Exact transcript of `--voice-ref`. |
87+
| `--max-tokens` | integer | automatic | Maximum generated speech-token count. |
88+
| `--temperature` | float | `1.0` | Speech-token sampling temperature. |
89+
| `--top-k` | integer | `25` | Speech-token top-k limit. |
90+
| `--top-p` | float | `0.8` | Speech-token nucleus threshold. |
91+
| `--seed` | integer | `0` | Seed used by token sampling, Flow noise, and HiFT. |
92+
| `--request-option flow_steps=<n>` | integer | `10` | Flow Euler integration steps. |
93+
| `--request-option cfg_rate=<float>` | float | `0.7` | Flow classifier-free guidance rate. |
94+
| `--request-option flow_noise_file=<path>` | raw F32 path | none | Optional exact initial Flow noise for parity tests. |
95+
| `--request-option hift_source_random_file=<path>` | raw F32 path | none | Optional exact HiFT phase-uniform and Gaussian values for parity tests. |
96+
| `--request-option hift_prior_noise_values=<n>` | integer | `0` | Torch RNG offset before normal HiFT source generation. |
97+
| `--session-option glm_tts.weight_type=native|f32|f16|bf16|q8_0` | enum | `native` | Requested component weight storage type. |
98+
| `--session-option glm_tts.mem_saver=true|false` | bool | `false` | Release the reference-only Whisper-VQ and CAMPPlus runtimes after caching the voice, while keeping Llama, Flow, and HiFT warm. |
99+
| `--session-option glm_tts.aggressive_mem_saver=true|false` | bool | `false` | Also release Llama, Flow, and HiFT after each stage. This minimizes VRAM but reloads the generation path on every request. |
100+
| `--session-option glm_tts.reference_cache_slots=<n>` | integer | `1` | Prepared reference-audio cache slots. Reusing a reference skips Whisper-VQ, mel, fbank, and CAMPPlus preparation; `0` disables it. |
101+
102+
Balanced mem-saver is intended for a server repeatedly using a cached
103+
reference voice. On a reference-cache miss it first releases the warm
104+
generation path, prepares and caches the new voice, then reconstructs the
105+
generation path. This prevents the reference and generation weight groups
106+
from overlapping in VRAM. Set `glm_tts.aggressive_mem_saver=true` only when
107+
the lowest possible peak VRAM is more important than request latency; it
108+
implies balanced mem-saver even when `glm_tts.mem_saver` is omitted.
109+
110+
The reference transcript must match the audio. A mismatched transcript changes
111+
both semantic and speaker conditioning and can substantially reduce quality.
112+
Q8 generation can select a slightly different speech-token sequence from the
113+
native checkpoint, so waveform identity is not expected.
114+
115+
See [GLM-TTS validation](../reports/glm_tts_validation.md) for exact component
116+
parity, path-test, timing, and output details.

docs/community_models/models.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Practical expectations:
1616

1717
| Family | Task | Supported language(s) | Contributor | What They Added |
1818
|---|---|---|---|---|
19+
| **glm_tts** | TTS, voice cloning | zh, en | Mirek [@mirek190](https://github.com/mirek190) | [GLM-TTS](glm_tts.md) zero-shot synthesis and voice cloning support |
1920
| **moss_tts_local** | TTS, voice cloning | auto, optional language hint | [@justinjohn0306](https://github.com/justinjohn0306) | [MOSS-TTS-Local Transformer v1.5](../models/moss_tts.md) support in the core model tree |
2021
| **outetts** | TTS, voice cloning | en, ar, zh, nl, fr, de, it, ja, ko, lt, ru, es, pt, be, bn, ka, hu, lv, fa, pl, sw, ta, uk | Mirek [@mirek190](https://github.com/mirek190) | [Llama-OuteTTS-1.0-1B](outetts.md) TTS and voice cloning support |
2122
| **vietneu_tts** | TTS, voice cloning | vi, en | Phuoc [@phuocnguyen90](https://github.com/phuocnguyen90) | [VieNeu-TTS-v3-Turbo](vietneu_tts.md) TTS and voice cloning support |

docs/gguf.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ Status labels:
6060
| `chatterbox` | Done | Pass | --- | Pass (ASR match, drift) | Pass (ASR match, drift) |
6161
| `citrinet_asr` | Done | Pass | --- | --- | Pass |
6262
| `fish_audio` | Done | Pass | --- | Pass | Pass |
63+
| `glm_tts` | Done | Pass (TTS + clone) | --- | --- | Pass (ASR match, drift) |
6364
| `heartmula` | Done | Pass | --- | Pass (drift) | Pass (drift) |
6465
| `higgs_audio_stt` | Done | Pass | --- | Pass | Pass |
6566
| `higgs_audio_tts` | Done | Pass | --- | Pass | Pass |

docs/model_manager.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ Packages whose loaders are not registered in the current release tree are listed
100100
| `chatterbox` | Chatterbox | **Yes** |
101101
| `citrinet_asr` | Citrinet ASR converted layout | No |
102102
| `fish_audio_s2_pro` | Fish Audio S2 Pro GGUF Q8_0 | **Yes** |
103+
| `glm_tts` | GLM-TTS with converted Flow/HiFT/tokenizer and CAMPPlus assets | No |
103104
| `heartmula` | HeartMuLa | No |
104105
| `higgs_audio_stt` | Higgs Audio STT | No |
105106
| `higgs_audio_v3_tts_4b` | Higgs Audio v3 TTS 4B GGUF Q8_0 | **Yes** |

0 commit comments

Comments
 (0)