Add banner, marketing intro, restructured result tables (normalized headline + both WER tables)
#3
by zeroweightai - opened
- .gitattributes +1 -0
- README.md +110 -46
- banner.png +3 -0
.gitattributes
CHANGED
|
@@ -4,3 +4,4 @@
|
|
| 4 |
*.npz filter=lfs diff=lfs merge=lfs -text
|
| 5 |
*.bin filter=lfs diff=lfs merge=lfs -text
|
| 6 |
*.wav filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
| 4 |
*.npz filter=lfs diff=lfs merge=lfs -text
|
| 5 |
*.bin filter=lfs diff=lfs merge=lfs -text
|
| 6 |
*.wav filter=lfs diff=lfs merge=lfs -text
|
| 7 |
+
banner.png filter=lfs diff=lfs merge=lfs -text
|
README.md
CHANGED
|
@@ -15,8 +15,12 @@ tags:
|
|
| 15 |
- voice-cloning
|
| 16 |
- vietnamese-tts
|
| 17 |
- tieng-viet
|
| 18 |
-
datasets:
|
| 19 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 20 |
metrics:
|
| 21 |
- wer
|
| 22 |
model-index:
|
|
@@ -31,8 +35,8 @@ model-index:
|
|
| 31 |
split: test
|
| 32 |
metrics:
|
| 33 |
- type: wer
|
| 34 |
-
value:
|
| 35 |
-
name: WER (%)
|
| 36 |
- type: utmos
|
| 37 |
value: 2.91
|
| 38 |
name: UTMOSv2 naturalness MOS
|
|
@@ -52,8 +56,8 @@ model-index:
|
|
| 52 |
split: test
|
| 53 |
metrics:
|
| 54 |
- type: wer
|
| 55 |
-
value: 0.
|
| 56 |
-
name: WER (%)
|
| 57 |
- task:
|
| 58 |
type: text-to-speech
|
| 59 |
name: Zero-Shot TTS — Vietnamese/English code-switching
|
|
@@ -64,8 +68,8 @@ model-index:
|
|
| 64 |
split: test
|
| 65 |
metrics:
|
| 66 |
- type: wer
|
| 67 |
-
value: 0.
|
| 68 |
-
name: WER (%)
|
| 69 |
- task:
|
| 70 |
type: text-to-speech
|
| 71 |
name: Zero-Shot TTS — cross-lingual voice prompt
|
|
@@ -76,8 +80,8 @@ model-index:
|
|
| 76 |
split: test
|
| 77 |
metrics:
|
| 78 |
- type: wer
|
| 79 |
-
value:
|
| 80 |
-
name: WER (%)
|
| 81 |
- task:
|
| 82 |
type: text-to-speech
|
| 83 |
name: Zero-Shot TTS — acronyms, dates, numbers
|
|
@@ -88,14 +92,30 @@ model-index:
|
|
| 88 |
split: test
|
| 89 |
metrics:
|
| 90 |
- type: wer
|
| 91 |
-
value:
|
| 92 |
-
name: WER (%)
|
| 93 |
---
|
| 94 |
|
|
|
|
|
|
|
| 95 |
# ZeroTTS
|
| 96 |
|
| 97 |
-
|
| 98 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 99 |
|
| 100 |
* Code, examples, browser demo: **https://github.com/zeroweight-ai/ZeroTTS**
|
| 101 |
* Benchmark dataset: **https://huggingface.co/datasets/zeroweight-ai/ZeroBench-TTS**
|
|
@@ -121,51 +141,98 @@ for chunk in tts.synthesize_stream("Một đoạn văn bản dài hơn…", voic
|
|
| 121 |
|
| 122 |
## Benchmarks
|
| 123 |
|
| 124 |
-
Measured on **[ZeroBench-TTS](https://huggingface.co/datasets/zeroweight-ai/ZeroBench-TTS)**
|
| 125 |
-
|
| 126 |
Vietnamese XTTS-v2 finetunes. 137/137 scored, 0 empty generations.
|
| 127 |
|
| 128 |
-
Scored by the benchmark
|
| 129 |
-
|
| 130 |
-
|
| 131 |
-
|
| 132 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 133 |
|
| 134 |
| | **ZeroTTS** | XTTS-v2-vietnamse | viXTTS |
|
| 135 |
|---|:-:|:-:|:-:|
|
| 136 |
-
| **WER** ↓ | **
|
| 137 |
| **Naturalness** (UTMOS) ↑ | **2.91** | 2.43 | 2.35 |
|
| 138 |
| **Voice similarity** (SSIM) ↑ | 0.936 | **0.940** | 0.935 |
|
| 139 |
| **Dead air** (excess silence) ↓ | **0.029 s** | 0.532 s | 0.233 s |
|
| 140 |
|
| 141 |
-
**
|
| 142 |
-
dead air. Median WER is **0.00%** on all four subsets
|
|
|
|
| 143 |
|
| 144 |
-
WER
|
|
|
|
|
|
|
|
|
|
| 145 |
|
| 146 |
| Subset | what it tests | **ZeroTTS** | XTTS-v2-vietnamse | viXTTS |
|
| 147 |
|---|---|:-:|:-:|:-:|
|
| 148 |
-
| `vietnamese` |
|
| 149 |
-
| `code_switch` | Vietnamese + embedded English | **0.
|
| 150 |
-
| `cross_lingual` | foreign voice prompt → Vietnamese | **
|
| 151 |
-
| `challenging` | acronyms, dates, %, currency | **
|
|
|
|
|
|
|
|
|
|
| 152 |
|
| 153 |
-
|
|
|
|
|
|
|
| 154 |
|
| 155 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 156 |
noise. On `cross_lingual` ZeroTTS is genuinely behind (0.911 vs ~0.935): it
|
| 157 |
-
carries a foreign speaker's timbre into Vietnamese less faithfully
|
| 158 |
-
|
| 159 |
-
* **
|
| 160 |
-
|
| 161 |
-
|
| 162 |
-
|
| 163 |
-
|
| 164 |
-
|
| 165 |
-
|
| 166 |
-
`W`/`H` acronym letter names.
|
| 167 |
-
|
| 168 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 169 |
|
| 170 |
```bash
|
| 171 |
huggingface-cli download zeroweight-ai/ZeroBench-TTS --repo-type dataset --local-dir ZeroBench-TTS
|
|
@@ -174,9 +241,6 @@ python -m zerobench_eval manifest --out manifest.jsonl # what to synthesize
|
|
| 174 |
python -m zerobench_eval score --wav_dir my_wavs/ --name MyModel
|
| 175 |
```
|
| 176 |
|
| 177 |
-
Full tables and reproduction commands:
|
| 178 |
-
[evaluation/RESULTS.md](https://github.com/zeroweight-ai/ZeroTTS/blob/main/evaluation/RESULTS.md).
|
| 179 |
-
|
| 180 |
## Voices, and voice cloning
|
| 181 |
|
| 182 |
A voice is a small array of speaker latents, `(1, n_voice_queries, d_model)`,
|
|
|
|
| 15 |
- voice-cloning
|
| 16 |
- vietnamese-tts
|
| 17 |
- tieng-viet
|
| 18 |
+
# NOTE deliberately NO `datasets:` field. It is the only thing that populates
|
| 19 |
+
# the Hub's cross-link, but the Hub renders it as "Models trained or fine-tuned
|
| 20 |
+
# on <dataset>" — which for our own held-out benchmark reads as train/test
|
| 21 |
+
# contamination. ZeroBench-TTS is EVALUATION data; every voice in it is held
|
| 22 |
+
# out of training. The `model-index` block below states that correctly, and the
|
| 23 |
+
# body links the benchmark in prose.
|
| 24 |
metrics:
|
| 25 |
- wer
|
| 26 |
model-index:
|
|
|
|
| 35 |
split: test
|
| 36 |
metrics:
|
| 37 |
- type: wer
|
| 38 |
+
value: 0.56
|
| 39 |
+
name: WER (%) — normalized text
|
| 40 |
- type: utmos
|
| 41 |
value: 2.91
|
| 42 |
name: UTMOSv2 naturalness MOS
|
|
|
|
| 56 |
split: test
|
| 57 |
metrics:
|
| 58 |
- type: wer
|
| 59 |
+
value: 0.21
|
| 60 |
+
name: WER (%) — normalized text
|
| 61 |
- task:
|
| 62 |
type: text-to-speech
|
| 63 |
name: Zero-Shot TTS — Vietnamese/English code-switching
|
|
|
|
| 68 |
split: test
|
| 69 |
metrics:
|
| 70 |
- type: wer
|
| 71 |
+
value: 0.95
|
| 72 |
+
name: WER (%) — normalized text
|
| 73 |
- task:
|
| 74 |
type: text-to-speech
|
| 75 |
name: Zero-Shot TTS — cross-lingual voice prompt
|
|
|
|
| 80 |
split: test
|
| 81 |
metrics:
|
| 82 |
- type: wer
|
| 83 |
+
value: 0.38
|
| 84 |
+
name: WER (%) — normalized text
|
| 85 |
- task:
|
| 86 |
type: text-to-speech
|
| 87 |
name: Zero-Shot TTS — acronyms, dates, numbers
|
|
|
|
| 92 |
split: test
|
| 93 |
metrics:
|
| 94 |
- type: wer
|
| 95 |
+
value: 0.61
|
| 96 |
+
name: WER (%) — normalized text
|
| 97 |
---
|
| 98 |
|
| 99 |
+
<img src="banner.png" alt="ZeroTTS — Vietnamese zero-shot text-to-speech" width="100%">
|
| 100 |
+
|
| 101 |
# ZeroTTS
|
| 102 |
|
| 103 |
+
### Ultra-natural Vietnamese speech, cloned from seconds of audio — streaming, real-time on a CPU
|
| 104 |
+
|
| 105 |
+
**The most accurate open Vietnamese TTS we know of — 13× fewer word errors than
|
| 106 |
+
the next open model**, and it runs faster than real time on a laptop CPU.
|
| 107 |
+
|
| 108 |
+
* 🎯 **Ultra-natural** — 2.91 UTMOS, ~0.5 MOS above every other open Vietnamese
|
| 109 |
+
system, with near-zero dead air (0.029 s vs 0.23–0.53 s).
|
| 110 |
+
* 🗣️ **Zero-shot voice cloning** — a voice is a small latent array; drop it in
|
| 111 |
+
and the model speaks in it. No fine-tuning, no per-speaker training.
|
| 112 |
+
* ⚡ **Real-time on CPU, streaming** — first audio chunk in ~100 ms, then chunks
|
| 113 |
+
ramp up. No GPU required.
|
| 114 |
+
* 🇻🇳 **Built for Vietnamese** — tones, code-switched English, and a built-in
|
| 115 |
+
normalizer that reads `31/12/2025` and `1.250 tỷ` the way a person would.
|
| 116 |
+
* 📊 **Measured, not asserted** — every number below comes from
|
| 117 |
+
[ZeroBench-TTS](https://huggingface.co/datasets/zeroweight-ai/ZeroBench-TTS)'s
|
| 118 |
+
own public scorer, on 59 held-out voices.
|
| 119 |
|
| 120 |
* Code, examples, browser demo: **https://github.com/zeroweight-ai/ZeroTTS**
|
| 121 |
* Benchmark dataset: **https://huggingface.co/datasets/zeroweight-ai/ZeroBench-TTS**
|
|
|
|
| 141 |
|
| 142 |
## Benchmarks
|
| 143 |
|
| 144 |
+
Measured on **[ZeroBench-TTS](https://huggingface.co/datasets/zeroweight-ai/ZeroBench-TTS)** —
|
| 145 |
+
137 items, 59 held-out reference voices × 4 subsets — against the two public
|
| 146 |
Vietnamese XTTS-v2 finetunes. 137/137 scored, 0 empty generations.
|
| 147 |
|
| 148 |
+
**Scored by the benchmark, not by us.** ZeroTTS synthesizes the clips and hands
|
| 149 |
+
them to `zerobench_eval`, the official scorer published inside the benchmark
|
| 150 |
+
dataset repo. Nothing in this repo computes a metric.
|
| 151 |
+
|
| 152 |
+
### Headline
|
| 153 |
+
|
| 154 |
+
Every system reads **normalized text** — dates, numbers and acronyms already
|
| 155 |
+
spoken out, from the benchmark's own curated reading. Every system gets exactly
|
| 156 |
+
the same input, so the comparison is like-for-like.
|
| 157 |
+
|
| 158 |
+
This is the condition a Vietnamese TTS system meets in production, where a text
|
| 159 |
+
frontend runs ahead of the model. ZeroTTS ships one — `normalize_vi_text`,
|
| 160 |
+
applied by default (see the [GitHub README](https://github.com/zeroweight-ai/ZeroTTS#usage)) — which reaches the benchmark's reading
|
| 161 |
+
on 27 of the 35 items that need normalization; the remaining gaps are date
|
| 162 |
+
separators and alphanumeric codes. Neither baseline ships a Vietnamese frontend
|
| 163 |
+
at all, which is why the raw-text table below is so much harsher on them.
|
| 164 |
|
| 165 |
| | **ZeroTTS** | XTTS-v2-vietnamse | viXTTS |
|
| 166 |
|---|:-:|:-:|:-:|
|
| 167 |
+
| **WER** ↓ | **0.56 %** | 7.27 % | 8.61 % |
|
| 168 |
| **Naturalness** (UTMOS) ↑ | **2.91** | 2.43 | 2.35 |
|
| 169 |
| **Voice similarity** (SSIM) ↑ | 0.936 | **0.940** | 0.935 |
|
| 170 |
| **Dead air** (excess silence) ↓ | **0.029 s** | 0.532 s | 0.233 s |
|
| 171 |
|
| 172 |
+
**13× fewer word errors**, ~0.5 MOS more natural, an order of magnitude less
|
| 173 |
+
dead air. Median WER is **0.00 %** on all four subsets — the typical generation
|
| 174 |
+
is transcribed exactly.
|
| 175 |
|
| 176 |
+
### WER — normalized text
|
| 177 |
+
|
| 178 |
+
The headline condition: numbers and dates already spoken out, as the shipped
|
| 179 |
+
normalizer produces.
|
| 180 |
|
| 181 |
| Subset | what it tests | **ZeroTTS** | XTTS-v2-vietnamse | viXTTS |
|
| 182 |
|---|---|:-:|:-:|:-:|
|
| 183 |
+
| `vietnamese` | monolingual Vietnamese | **0.21 %** | 7.21 % | 7.54 % |
|
| 184 |
+
| `code_switch` | Vietnamese + embedded English | **0.95 %** | 10.14 % | 5.86 % |
|
| 185 |
+
| `cross_lingual` | foreign voice prompt → Vietnamese | **0.38 %** | 4.94 % | 6.61 % |
|
| 186 |
+
| `challenging` | acronyms, dates, %, currency | **0.61 %** | 5.63 % | 13.44 % |
|
| 187 |
+
| **overall** | | **0.56 %** | **7.27 %** | **8.61 %** |
|
| 188 |
+
|
| 189 |
+
### WER — raw text
|
| 190 |
|
| 191 |
+
The harder condition: the model is handed `31/12/2025` and `ChatGPT` verbatim
|
| 192 |
+
and has to read them itself, with no normalizer in front. This is what a system
|
| 193 |
+
with no Vietnamese text frontend faces.
|
| 194 |
|
| 195 |
+
| Subset | what it tests | **ZeroTTS** | XTTS-v2-vietnamse | viXTTS |
|
| 196 |
+
|---|---|:-:|:-:|:-:|
|
| 197 |
+
| `vietnamese` | monolingual Vietnamese | **0.16 %** | 7.92 % | 9.56 % |
|
| 198 |
+
| `code_switch` | Vietnamese + embedded English | **0.97 %** | 10.94 % | 9.25 % |
|
| 199 |
+
| `cross_lingual` | foreign voice prompt → Vietnamese | **1.42 %** | 21.37 % | 27.27 % |
|
| 200 |
+
| `challenging` | acronyms, dates, %, currency | **1.75 %** | 27.86 % | 31.85 % |
|
| 201 |
+
| **overall** | | **1.03 %** | **16.42 %** | **18.40 %** |
|
| 202 |
+
|
| 203 |
+
**Reading these fairly:**
|
| 204 |
+
|
| 205 |
+
* **Normalization is where the baselines gain most, and we still win.** Their
|
| 206 |
+
tokenizers genuinely have no Vietnamese number expansion, so raw text punishes
|
| 207 |
+
them hard (`challenging` 27.86 %) and the normalized column is the fairest
|
| 208 |
+
comparison available — it improves XTTS 2.3× and viXTTS 2.1×, against 1.8× for
|
| 209 |
+
us. The gap narrows from 16× to 13× and stops there, because what remains is
|
| 210 |
+
the acoustic model.
|
| 211 |
+
* **`vietnamese` barely moves for anyone** (0.16 % → 0.21 % for ZeroTTS). It has
|
| 212 |
+
no digits or acronyms, so there is nothing to normalize — which is the control
|
| 213 |
+
showing the other subsets' gains are real and not a scoring artifact.
|
| 214 |
+
* **Voice similarity is a tie, not a win.** 0.936 / 0.940 / 0.935 is within
|
| 215 |
noise. On `cross_lingual` ZeroTTS is genuinely behind (0.911 vs ~0.935): it
|
| 216 |
+
carries a foreign speaker's timbre into Vietnamese slightly less faithfully,
|
| 217 |
+
while winning that subset's WER by 15×.
|
| 218 |
+
* **The WER definition matters more than the WER.** ZeroBench scores every clip
|
| 219 |
+
with **two ASRs** (`whisper-large-v3` + `PhoWhisper-large`, min taken — neither
|
| 220 |
+
can judge Vietnamese code-switch TTS alone) against **every acceptable
|
| 221 |
+
reading** of the target text. Its test suite pins the policy in both
|
| 222 |
+
directions: format artifacts must score 0, real defects must still cost.
|
| 223 |
+
* **Our remaining errors are published, not hidden.** Every item scoring above
|
| 224 |
+
0.00 is audited in [docs/BENCHMARKS.md](https://github.com/zeroweight-ai/ZeroTTS/blob/main/docs/BENCHMARKS.md) — mostly voiced
|
| 225 |
+
leading zeros in dates and `W`/`H` acronym letter names.
|
| 226 |
+
|
| 227 |
+
Reproduce, or score your own system:
|
| 228 |
+
|
| 229 |
+
```bash
|
| 230 |
+
pip install "zerotts[eval]"
|
| 231 |
+
SYNTH_FROM=text_normalized OUT_DIR=./eval/norm ./evaluation/run_benchmark.sh
|
| 232 |
+
./evaluation/run_benchmark.sh # raw text
|
| 233 |
+
```
|
| 234 |
+
|
| 235 |
+
Not using ZeroTTS? The scorer stands alone — bring wavs from any system:
|
| 236 |
|
| 237 |
```bash
|
| 238 |
huggingface-cli download zeroweight-ai/ZeroBench-TTS --repo-type dataset --local-dir ZeroBench-TTS
|
|
|
|
| 241 |
python -m zerobench_eval score --wav_dir my_wavs/ --name MyModel
|
| 242 |
```
|
| 243 |
|
|
|
|
|
|
|
|
|
|
| 244 |
## Voices, and voice cloning
|
| 245 |
|
| 246 |
A voice is a small array of speaker latents, `(1, n_voice_queries, d_model)`,
|
banner.png
ADDED
|
Git LFS Details
|