thuongvv's picture
|
download
raw
13.4 kB
---
license: mit
language:
- vi
library_name: gguf
pipeline_tag: text-to-speech
tags:
- text-to-speech
- tts
- vietnamese
- gguf
- ggml
- llama-cpp
- quantized
- webassembly
- zero-shot
- speech-synthesis
- voice-cloning
- vietnamese-tts
- tieng-viet
metrics:
- wer
model-index:
- name: ZeroTTS
results:
- task:
type: text-to-speech
name: Zero-Shot Text-to-Speech
dataset:
type: zeroweight-ai/ZeroBench-TTS
name: ZeroBench-TTS
split: test
metrics:
- type: wer
value: 1.03
name: WER (%) — raw text
- type: utmos
value: 2.91
name: UTMOSv2 naturalness MOS
- type: speaker_similarity
value: 0.936
name: Speaker similarity (WavLM-SV cosine)
- type: excess_silence
value: 0.029
name: Excess silence (s)
- task:
type: text-to-speech
name: Zero-Shot TTS — monolingual Vietnamese
dataset:
type: zeroweight-ai/ZeroBench-TTS
name: ZeroBench-TTS (vietnamese)
config: vietnamese
split: test
metrics:
- type: wer
value: 0.16
name: WER (%) — raw text
- task:
type: text-to-speech
name: Zero-Shot TTS — Vietnamese/English code-switching
dataset:
type: zeroweight-ai/ZeroBench-TTS
name: ZeroBench-TTS (code_switch)
config: code_switch
split: test
metrics:
- type: wer
value: 0.97
name: WER (%) — raw text
- task:
type: text-to-speech
name: Zero-Shot TTS — cross-lingual voice prompt
dataset:
type: zeroweight-ai/ZeroBench-TTS
name: ZeroBench-TTS (cross_lingual)
config: cross_lingual
split: test
metrics:
- type: wer
value: 1.42
name: WER (%) — raw text
- task:
type: text-to-speech
name: Zero-Shot TTS — acronyms, dates, numbers
dataset:
type: zeroweight-ai/ZeroBench-TTS
name: ZeroBench-TTS (challenging)
config: challenging
split: test
metrics:
- type: wer
value: 1.75
name: WER (%) — raw text
---
<img src="banner.png" alt="ZeroTTS — Vietnamese zero-shot text-to-speech" width="100%">
# ZeroTTS — GGUF
### The ZeroTTS weights packaged as GGUF, for the [ggml](https://github.com/ggml-org/ggml) runtime instead of onnxruntime. Same model, ~4× smaller download, and it runs in the browser under WebAssembly.
This is a **repackaging**, not a different model. The weights are the same ones
in [`zeroweight-ai/ZeroTTS`](https://huggingface.co/zeroweight-ai/ZeroTTS); the
`f32` file here is verified to produce **bit-identical frame codes** to the ONNX
graphs for the same text, voice and random draws. If you want the ONNX runtime
or the `zerotts` pip package, use that repo — this one is for the ggml/WASM
runtime in [`cpp/`](https://github.com/zeroweight-ai/ZeroTTS/tree/main/cpp).
**The most accurate open Vietnamese TTS we know of — 4× fewer word errors than
the next best model**, and it runs faster than real time on a laptop CPU.
* 🎯 **Ultra-natural** — 2.91 UTMOS above every other open Vietnamese
system, with near-zero dead air (0.029 s).
* 🗣️ **Zero-shot voice cloning** — a voice is a small latent array; drop it in
and the model speaks in it, cloned from as little as 3 seconds of reference
audio (up to 30 seconds). No fine-tuning, no per-speaker training.
* ⚡ **Real-time on CPU, streaming** — ~2× faster than real time (RTF 0.5×),
first audio chunk in ~70 ms. No GPU required.
* 🇻🇳 **Built for Vietnamese** — tones, code-switched English, and
reads `31/12/2025` and `ZeroTTS` without text normalizer.
* Code, examples, browser demo: **https://github.com/zeroweight-ai/ZeroTTS**
* Benchmark dataset: **https://huggingface.co/datasets/zeroweight-ai/ZeroBench-TTS**
* Blogpost: **https://zeroweight.ai/blog/zero-tts**
## Samples
**Two-speaker conversation**
<audio controls><source src="https://huggingface.co/zeroweight-ai/ZeroTTS/resolve/main/samples/conversation.mp3" type="audio/mpeg"></audio>
**Long-form narration**
<audio controls><source src="https://huggingface.co/zeroweight-ai/ZeroTTS/resolve/main/samples/storytelling.mp3" type="audio/mpeg"></audio>
**News read, code-switched English**
<audio controls><source src="https://huggingface.co/zeroweight-ai/ZeroTTS/resolve/main/samples/news-code-switch.mp3" type="audio/mpeg"></audio>
**Cross-lingual**
Reference audio (Vietnamese)
<audio controls><source src="https://huggingface.co/zeroweight-ai/ZeroTTS/resolve/main/samples/cross-lingual-reference-vi.mp3" type="audio/mpeg"></audio>
Output (English)
<audio controls><source src="https://huggingface.co/zeroweight-ai/ZeroTTS/resolve/main/samples/cross-lingual-english.mp3" type="audio/mpeg"></audio>
## Files
| path | what it is |
|---|---|
| `gguf/zerotts-q8_0.gguf` | **the default** — 206 MB, the text encoder, global decoder and depth decoder |
| `gguf/zerotts-q4_0.gguf` | 124 MB, when the download budget is tight |
| `gguf/zerotts-f32.gguf` | 772 MB, unquantized; the reference the others are measured against |
| `onnx/codec/` | the MOSS audio-tokenizer **decoder**, still ONNX (Apache-2.0, ~45 MB) — it is not on the per-frame hot path |
| `voices/` | the voice latents; a voice is a 10×768 float32 array |
| `tokenizer.json`, `config.json`, `null_voice_emb.npy`, `silence_frame.npy` | runtime side files, identical to the ONNX repo |
You need **one** `.gguf` plus `onnx/codec/`, `voices/` and the side files.
### Which one to take
Measured in Chrome on a 14-core Apple-silicon laptop, one 3.2 s utterance,
frame generation only. "drift" is the share of sampled codes that come out
differently from `f32` when both are driven along the same code sequence — the
`<eoa>` stop decision was identical in every build.
| file | size | drift vs f32 | 1 thread | 4 threads | 8 threads |
|---|---:|---:|---:|---:|---:|
| `f32` | 772 MB | — | **2.40×** | **6.1×** | **6.2×** |
| `q8_0` | 206 MB | 4.9% | 1.06× | 3.6× | 5.3× |
| `q4_0` | 124 MB | 36.5% | 1.27× | 4.1× | 5.8× |
For reference, the ONNX graphs in
[`zeroweight-ai/ZeroTTS`](https://huggingface.co/zeroweight-ai/ZeroTTS) run at
4.2× on the same machine, at the 4 threads onnxruntime-web caps itself to.
**Quantization here buys download size, not speed.** WebAssembly's SIMD has no
integer dot-product instruction, so a `q8_0` block costs roughly 20 SIMD ops per
32 multiply-accumulates where `f32` costs 8 fused multiply-adds — on a machine
with memory bandwidth to spare the extra instructions cost more than the saved
bytes. Take `q8_0` unless you have a reason not to: it is 4× smaller than the
ONNX graphs and faster than them at the thread counts each actually uses (5.3×
on 8 threads against 4.2× on 4). Take `f32` if you want bit-exactness, the
highest speed at any thread count, or you are running on very few cores — it is
the fastest build here, just the largest. `q4_0` changes a third of the drawn
codes, which is audible as a different take rather than a broken one, but it is
the wrong trade unless 124 MB is the binding constraint.
Numbers on hardware that is genuinely short of *bandwidth* rather than compute
should look different; the benchmark page in the repo re-runs this table in one
click.
## Usage
The runtime is [`cpp/`](https://github.com/zeroweight-ai/ZeroTTS/tree/main/cpp)
in the main repository — a ggml implementation of the generation loop, building
natively and to WebAssembly.
```bash
git clone --recurse-submodules https://github.com/zeroweight-ai/ZeroTTS
cd ZeroTTS/cpp
cmake -B build -DCMAKE_BUILD_TYPE=Release . && cmake --build build -j
./build/zerotts-bench /path/to/zerotts-q8_0.gguf voice.bin text_ids.txt
```
In the browser, the demo in [`js/`](https://github.com/zeroweight-ai/ZeroTTS/tree/main/js)
uses this repo by default:
```bash
cd ZeroTTS/js && npm install && npm run dev
```
`voice.bin` is the raw little-endian float32 blob under `voices/<name>/` —
`voice.npz` is the same latents for numpy callers.
For the Python package, the ONNX graphs and `pip install zerotts`, use
[`zeroweight-ai/ZeroTTS`](https://huggingface.co/zeroweight-ai/ZeroTTS) instead.
## Benchmarks
These are the unquantized model's quality numbers, measured through the
PyTorch runtime. `f32` here is that model exactly; see the drift column above
for what the quantized files change.
Measured on **[ZeroBench-TTS](https://huggingface.co/datasets/zeroweight-ai/ZeroBench-TTS)**
Every system reads **raw text** — dates, numbers and acronyms verbatim, exactly
as they appear in the wild, with no text frontend in front of the model.
| | **ZeroTTS** | OmniVoice | XTTS-v2-vietnamse | viXTTS |
|---|:-:|:-:|:-:|:-:|
| **WER** ↓ | **1.03 %** | 4.13 % | 16.42 % | 18.40 % |
| **Naturalness** (UTMOS) ↑ | **2.91** | 2.76 | 2.43 | 2.35 |
| **Voice similarity** (SSIM) ↑ | 0.936 | **0.950** | 0.940 | 0.935 |
| **Dead air** (excess silence) ↓ | **0.029 s** | 0.340 s | 0.532 s | 0.233 s |
| **RTF, CPU** ↓ | **0.50×** | 6.12× | 0.71× | 0.73× |
| **Time to first audio, CPU** ↓ | **~70 ms** | ~34 s | ~6.1 s | ~5.1 s |
| **Parameters** ↓ | **202 M** | 775 M | 467 M | 467 M |
**4× fewer word errors than the next-best system**, and the fastest of the four
on CPU. The gap is much wider in latency than in throughput: the two XTTS
fine-tunes also beat real time (0.71×) but need seconds to emit their first
sample, while OmniVoice is 6× *slower* than real time. All three are sized and
tuned for a GPU, and it shows.
Full comparison tables, per-subset breakdowns, and CPU speed methodology:
**[docs/BENCHMARKS.md](https://github.com/zeroweight-ai/ZeroTTS/blob/main/docs/BENCHMARKS.md)**
### Speed — CPU
RTF (realtime factor, wall-clock synthesis time ÷ output audio duration — lower
is faster; below 1× is faster than real time) and time-to-first-audio, all
measured **on CPU**, single request, 8 inference threads pinned to a dedicated
core pool (no other synthesis running concurrently). Three Vietnamese samples —
short (26 chars), medium (77 chars), long (227 chars) — each run 6 times with
the first 2 (cold-cache) discarded; figures below are the mean of the
remaining 4.
| | **ZeroTTS** | OmniVoice | XTTS-v2-vietnamse | viXTTS |
|---|:-:|:-:|:-:|:-:|
| RTF — short | **0.51×** | 10.87× | 0.70× | 0.71× |
| RTF — medium | **0.47×** | 4.82× | 0.70× | 0.70× |
| RTF — long | **0.53×** | 2.67× | 0.71× | 0.78× |
| TTFA — short | **53 ms** | 21.7 s | 4.02 s | 2.45 s |
| TTFA — medium | **66 ms** | 28.9 s | 4.02 s | 3.72 s |
| TTFA — long | **89 ms** | 52.3 s | 10.3 s | 9.22 s |
ZeroTTS's time-to-first-audio comes from its real streaming path — first audio frame,
not first full utterance. The three baselines have no working CPU streaming
path, so their TTFA is the time to the complete utterance.
## Voices, and voice cloning
A voice is a small array of speaker latents, `(1, n_voice_queries, d_model)`,
shipped as a `.npz` under `voices/`. That array is the entire speaker
conditioning — no reference transcript, no audio prompt.
> **Voice cloning is not available in this release.** Those latents come from a
> voice encoder that reads a reference clip, and that encoder is not published.
> This repository ships ready-to-use voices; it cannot create new ones from
> audio.
>
> To get latents for your own speaker, see **[zeroweight.ai](https://zeroweight.ai)**
> or get in touch.
Because a voice is just an array, latents obtained that way drop into
`voices/<name>/voice.npz` and work with no code change.
## Intended use and limitations
Built for **Vietnamese**. It handles English words embedded in Vietnamese text
(`code_switch`), but it is not an English TTS system and is not evaluated as one.
Do not use it to impersonate a real person, to generate speech attributed to
someone without their consent, or to produce audio intended to deceive. The
shipped voices are for evaluation and demos.
Synthetic speech should be disclosed as synthetic wherever a listener might
reasonably assume otherwise.
## Credits
Speech codec: **MOSS-Audio-Tokenizer-Nano** by the OpenMOSS team, Apache-2.0.
Its ONNX **decoder** graphs are redistributed under `onnx/codec/` so ZeroTTS has
no external runtime dependency; the encoder is not included. See
`onnx/codec/LICENSE-Apache-2.0.txt`.
```bibtex
@misc{gong2026mossaudiotokenizerscalingaudiotokenizers,
title={MOSS-Audio-Tokenizer: Scaling Audio Tokenizers for Future Audio Foundation Models},
author={Yitian Gong and Kuangwei Chen and Zhaoye Fei and Xiaogui Yang and Ke Chen
and Yang Wang and Kexin Huang and Mingshu Chen and Ruixiao Li
and Qingyuan Cheng and Shimin Li and Xipeng Qiu},
year={2026}, eprint={2602.10934}, archivePrefix={arXiv}, primaryClass={cs.SD}
}
```
## License
ZeroTTS weights and code: **MIT**.
The ZeroBench-TTS *dataset* is CC-BY-NC-4.0 because it redistributes reference
audio from VIVOS, viVoice, phoaudiobook and Emilia. That license applies to the
benchmark dataset only — **not** to these weights.

Xet Storage Details

Size:
13.4 kB
·
Xet hash:
2aded34f039ec81314465e18809d67ea20ef64b9cc37027956d20ea33087c5fa

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.