Klein-TTS-X1.5-Flash
1.7M parameters | 3 languages | 0.013 real-time factor on a CPU | 4.36 UTMOS on unseen text
We introduce the Klein-TTS X1.5 family: small, fast, multilingual text-to-speech models that run faster than real time on a plain CPU. The family comes in three sizes, Flash Lite (0.4M), Flash (1.7M) and Pro (13M), and Pro also ships as a ternary (1.58-bit) + FP4 quantized version. X1.5-Flash is the 1.7M model.
X1.5-Flash is a 1.7M-parameter generator that turns phonemes into 24 kHz speech in English, French and Italian, with 5 voices. It was trained by distillation on synthetic speech, with a GAN and a WavLM feature loss. On 300 held-out web sentences it scores 4.36 UTMOS, 4.42 SCOREQ and a 2.36% word error rate (Whisper small). That is ahead of Kitten TTS Nano 0.8 (14M, 8 times larger) on every quality score, far ahead of SupraTTS 1.0 Preview (1.0M, a similar size), and ahead of Phonon 31M on the TTS Index at 1/18 of its size. The model weights take 6.8 MB in float32.
- Architecture: a StyleTTS 2 / ISTFTNet-style generator. A shared-weight text encoder predicts durations, then frame-level pitch and energy, then an AdaIN decoder with a harmonic source and an inverse-STFT output head writes the waveform.
- Training data: synthetic speech in English, French and Italian, from the 5 release voices (single voices, no blended clips) at speaking speeds of 0.9 / 1.0 / 1.1. The text is web text from FineWeb (English) and FineWeb-2 (French, Italian), in 1 to 3 sentence units.
- Training: log-mel L1, multi-resolution STFT, LSGAN with feature matching (multi-period and multi-resolution discriminators, from step 10,000), WavLM feature matching, duration, pitch and energy L1, and a silence term. AdamW, LR 2e-4 with cosine decay, bf16. During early training the decoder is fed ground-truth pitch and energy, then moved to its own predictions between steps 5,000 and 30,000.
- This checkpoint is the final step-150,000 weights of a 150,000-step run. See Benchmarks.
Model Overview
| Item | Specification |
|---|---|
| Parameters | 1.70M generator |
| Output | 24 kHz mono, 300 samples (12.5 ms) per model frame |
| Input | 178-symbol IPA phoneme vocabulary. English via misaki, French / Italian via espeak-ng |
| Languages | English (American and British), French, Italian |
| Voices | 5 voices: Sarah, Caleb, Isabella, Camille, Giulia (see Voices) |
| Speed control | A speed value divides the predicted durations. Trained on 0.9 to 1.1 |
| Text encoder | 1 shared transformer block applied 4 times (d = 128, 4 heads, FFN 288, RoPE) + 3 conv layers |
| Duration predictor | 1 style-conditioned transformer block; duration = sum of 50 sigmoid gates / speed |
| Prosody | Frame-level F0 and log-energy heads, conditioned on the voice |
| Decoder | AdaIN residual blocks (96 channels), harmonic + noise source (8 harmonics), upsampling 10x and 6x, iSTFT head |
| Checkpoint | Step 150,000 (final) |
| License | Apache-2.0 (see LICENSE) |
Quickstart
Transformers (no library needed)
The repository ships custom model code, so plain Transformers is enough:
from transformers import AutoModel
repo = "klein-ml/Klein-TTS-X1.5-Flash"
model = AutoModel.from_pretrained(repo, trust_remote_code=True).eval()
out = model.tts("Hello from Klein TTS. This is a tiny model that speaks three languages.", voice="Sarah")
model.save_wav("hello.wav", out.waveform, out.sample_rate)
print(model.voices("en-us")) # voices per language: "en-us", "en-gb", "fr", "it"
The Transformers path carries its own compact English text-to-phoneme code and dictionaries (no spaCy), so only three
small packages are needed: regex, phonemizer-fork and espeakng-loader (espeak-ng handles French and Italian, and
English words that are not in the dictionary). They install themselves the first time you give the model text; set
KLEINTTS_NO_AUTO_INSTALL=1 to get the pip command instead. On 400 English test sentences this compact front-end gives
the same phonemes as the full one in 97% of the sentences, and the rest differ by the pronunciation of a single word
(typically words like "read" or "use", whose sound depends on the part of speech). Use the kleintts package below for
the exact front-end the model was trained with.
kleintts package
pip install kleintts # uses the full misaki + spaCy text front-end, the one used for training
from kleintts import KleinTTS
tts = KleinTTS.from_pretrained("klein-ml/Klein-TTS-X1.5-Flash") # a Hugging Face repo id or a local folder
out = tts.tts("Bonjour, ceci est un court test.", voice="Camille", speed=1.0, seed=0)
tts.save_wav("bonjour.wav", out.waveform, out.sample_rate)
kleintts "Ciao, questa è una prova." --voice Giulia -o ciao.wav
kleintts --list-voices
Node.js
Flash also ships inside the Node.js package @kleinml/kleintts
(ONNX, CPU), so it works offline right after install:
npm install @kleinml/kleintts
npx kleintts "Hello from Klein TTS." -v Sarah -o hello.wav
Options
| Argument | Meaning |
|---|---|
voice |
A voice name from the table below (not case sensitive). The text is read in the language of the voice |
voice2, mix |
Blend two voices of the same language: (1 - mix) * voice + mix * voice2. This checkpoint was not trained on blends, so treat them as experimental |
speed |
Speaking speed, 1.0 is normal. Trained on 0.9 to 1.1 |
seed |
Fixes the small random noise in the vocoder, for repeatable output |
pause |
Seconds of silence between sentence chunks, default 0.12 |
phonemes |
Skip the text front-end and pass phonemes (the model's 114-symbol IPA set) directly |
Voices
| Voice | Language | Gender |
|---|---|---|
| Sarah | American English (en-us) |
female |
| Caleb | American English (en-us) |
male |
| Isabella | British English (en-gb) |
female |
| Camille | French (fr) |
female |
| Giulia | Italian (it) |
female |
model.voices() lists them, and model.voices("fr") filters by language.
Long text is split into sentence chunks (about 250 characters each) and joined. The output is 24 kHz mono. Digits are expanded by the English phonemizer; other languages and unusual formats (phone numbers, dates, long numbers) were not systematically tested.
Files
| File | Content |
|---|---|
model.safetensors |
the 1.70M-parameter generator |
config.json |
architecture, the phoneme vocabulary, the voice table and which voices are recommended |
modeling_klein_tts.py, configuration_klein_tts.py |
the Transformers remote code |
lexicon_us.json.gz, lexicon_gb.json.gz |
English pronunciation dictionaries for the Transformers path (from misaki, Apache-2.0; see NOTICE-misaki.txt) |
generate.py |
a minimal example |
onnx/ |
the generator exported to ONNX for CPU runtimes (encoder.onnx, decoder.onnx, model.json), used by the Node.js package @kleinml/kleintts |
Benchmarks
Predicted-quality scores need no reference recording: UTMOS (naturalness), DNSMOS OVRL and SCOREQ, all 1 to 5, higher is better. WER is the word error rate of Whisper small transcripts against the input text, lower is better. Every model is run with its default voice and settings, raw output. The public set is 300 English sentences from FineWeb (one per document, no digits). The private set is 97 English sentences written for this evaluation and not published, so no model can have trained on them.
| Benchmark | Klein-TTS X1.5-Flash | Klein-TTS X1.5-Pro | Kitten TTS Nano 0.8 | SupraTTS 1.0 Preview | Phonon 31M | Kokoro 82M |
|---|---|---|---|---|---|---|
| Parameters | 1.70M | 13.1M | 14.0M | 1.03M | 31.0M | 81.8M |
| UTMOS, public | 4.36 | 4.44 | 4.05 | 3.93 | 4.44 | 4.52 |
| UTMOS, private | 4.39 | 4.45 | 4.03 | 3.94 | 4.43 | 4.52 |
| DNSMOS OVRL, public | 3.41 | 3.44 | 3.39 | 3.44 | 3.35 | 3.50 |
| DNSMOS OVRL, private | 3.41 | 3.42 | 3.40 | 3.44 | 3.35 | 3.48 |
| SCOREQ, public | 4.42 | 4.70 | 4.34 | 3.98 | 4.58 | 4.87 |
| SCOREQ, private | 4.46 | 4.72 | 4.32 | 4.02 | 4.59 | 4.89 |
| WER, public | 2.36% | 2.51% | 2.11% | 2.55% | 2.59% | 2.59% |
| WER, private | 0.18% | 0.12% | 0.36% | 0.24% | 0.30% | 0.24% |
| Quality score (weighted) | 83.1 | 84.9 | 80.4 | 77.8 | 83.4 | 86.0 |
| **TTS Index (Elo)**¹ | 1144 | 1311 | 794 | 734 | 1068 | 1332 |
| RTF, GPU | 0.0018 | 0.0020 | n/a | n/a | n/a | 0.0057 |
| RTF, CPU | 0.013 | 0.022 | 0.035 | 0.0040 | 0.10 | 0.14 |
¹ From an older snapshot of the leaderboard. The Elo is fitted over every model on the leaderboard at the time, so the current leaderboard numbers differ slightly.
TTS Index (Elo). WER, UTMOS, SCOREQ and DNSMOS OVRL are each put on a 0 to 100 scale and combined with fixed weights (WER 40%, UTMOS 25%, SCOREQ 20%, DNSMOS 15%) into a quality score for every sentence. A size adjustment then rewards a model that scores above what a typical model of its size reaches and penalizes one that scores below it (1.5 points per factor of ten in size as a bonus, against a penalty of 15 for a model that is larger than its score justifies). On every sentence, every two models play a match: the higher adjusted score wins, scores within one point are a draw. The index is a Bradley-Terry fit of all those matches on the Elo scale (400 points per factor of ten in odds), anchored and frozen with Piper (lessac medium) at 1000; the private set counts 60%, the public set 40%. A gap of 200 points means the higher model wins about 76% of sentences. The quality score row is the 40/60 weighted average.
Speed. Real-time factor, lower is faster, measured on a desktop PC over 300 sentences, on this checkpoint. The Klein figures are the generator only (phonemes in, audio out). Kitten TTS Nano is measured end to end on the CPU through its own ONNX runtime, including its text front-end, Phonon through its own runtime in 8-bit, and SupraTTS is its model time on the CPU (from its own benchmark script); none of these three was run on a GPU. Kokoro 82M is measured like the Klein models (generator only, phonemes precomputed). At 0.013 on a CPU, Flash runs about 75 times faster than real time: faster than Pro (0.022), Kitten TTS Nano (0.035), Phonon 31M (0.10) and Kokoro 82M (0.14), and slower than the 1.0M SupraTTS (0.0040, model time only). Most of the time goes into the decoder, which runs at the audio rate.
Reading these numbers.
- The quality scores are predictions of listener opinion, not listener opinion. They react strongly to light noise and under-react to other flaws. Treat gaps of a few hundredths as ties.
- The private set uses clean, ordinary sentences, and almost every model transcribes it nearly perfectly (a handful of word errors each). It separates models through the quality scores, not through word accuracy.
- The private set has 97 sentences, so Elo differences of a few dozen points are within noise.
- Only English was benchmarked. French and Italian are supported but not scored here.
- Pro (13.1M), Phonon (31M) and Kokoro (81.8M) are much larger than Flash, so the table is a quality comparison, not a like-for-like one. SupraTTS (1.0M) is the closest in size.
Checkpoint choice. This release uses the final step-150,000 weights. On 150 held-out sentences, UTMOS rose to 4.34 at step 89,200 and then levelled off (4.35 at 100,000, 4.37 at 120,000 and 150,000), while SCOREQ kept improving to the end (4.35 at 89,200, 4.41 at 150,000), so the last checkpoint is the best one.
Limitations
- Expressiveness is limited. The model reproduces the speaking style of its training voices; it has no emotion or style control beyond the voice and speed.
- Five voices, three languages. There is no Spanish and no male French or Italian voice; Pro has 17 voices in four languages.
- Long inputs are split into sentence chunks automatically. Training clips were at most 30 seconds, so avoid single sentences much longer than that.
Data Attribution
- Text: FineWeb and FineWeb-2 (HuggingFaceFW), licensed under ODC-By 1.0 and subject to CommonCrawl's Terms of Use.
- English pronunciation dictionaries and the compact English text-to-phoneme code in the Transformers path are adapted from
misaki (Apache-2.0); the license text is included as
NOTICE-misaki.txt.
Citation
@techreport{klein-tts-x1.5,
title = {Klein-TTS X1.5: small multilingual text-to-speech models},
author = {Klein ML},
year = {2026},
month = {October},
url = {https://kleinml.com}
}
- Downloads last month
- 30