Compressed Kokoro
Smaller drop-in decoders for Kokoro-82M. Kokoro's text side (ALBERT, text encoder, prosody predictor) and all 28 English voices stay exactly as they are, so pronunciation, timing and prosody are identical to Kokoro's. Only the waveform decoder, which holds 65% of Kokoro's parameters, is replaced. Each decoder was pruned from Kokoro's own and then distilled from it.
| variant | whole model | decoder speedยน | voiced artifact rateยฒ | in short |
|---|---|---|---|---|
| Kokoro-82M | 81.8M (100%) | 1.00ร | โ | reference |
H512_G512 |
59.3M (73%) | 1.03ร | 3.8% | Sounds like Kokoro: a blind listener could not tell them apart (18 of 20 pairs "same"). |
H512_G256_S128-128 |
46.8M (57%) | 1.39ร | 5.4% | Balanced: much smaller and faster. Slightly below Kokoro in a blind test. |
H512_G256 |
44.0M (54%) | 2.65ร | 18.2% | Fastest. A faint hoarse whistle on some voiced sounds. |
ยน Decoder real-time factor relative to Kokoro's decoder on the same input. Apple M4 GPU, PyTorch MPS, batch 1, median over interleaved runs. ยฒ Share of voiced frames with a narrowband 2โ3 kHz excess of more than 15 dB over Kokoro: the paired measure of the "hoarse whistle" artifact (validation set, lower is better).
Quick start
pip install kokoro==0.9.4 soundfile huggingface_hub
hf download drmhse/compressed-kokoro --local-dir compressed-kokoro --exclude "samples/*"
cd compressed-kokoro
import numpy as np, soundfile as sf
from kokoro import KPipeline
from slim import load
model = load('H512_G512') # or 'H512_G256_S128-128', 'H512_G256'
pipe = KPipeline(lang_code='a', model=model, repo_id='hexgrad/Kokoro-82M') # 'a' = US English, 'b' = UK English
audio = np.concatenate([a.numpy() for _, _, a in pipe('Hello from a smaller Kokoro.', voice='af_heart')])
sf.write('hello.wav', audio, 24000)
slim.load builds Kokoro's KModel from the official checkpoint and swaps in the slim decoder, so the rest of the kokoro package
(voices, KPipeline, speed=) works unchanged. Each variant folder holds decoder.safetensors (f32, weight norm folded into plain
weights) and config.json (widths and training steps).
Results
Each slim decoder is compared with Kokoro's own decoder on identical inputs: the same phonemes, durations, prosody and excitation.
Test set: 112 sentences from three public-domain books not used in training, 4 per voice for all 28 voices (13.9 min).
| Kokoro | H512_G512 |
H512_G256_S128-128 |
H512_G256 |
|
|---|---|---|---|---|
| Whisper small.en WER | 2.51% | 2.39% | 2.39% | 2.43% |
| log-mel L1 vs Kokoro โ | โ | 0.179 | 0.222 | 0.274 |
| waveform SNR vs Kokoro โ | โ | 8.7 dB | 7.7 dB | 6.2 dB |
| long-term spectrum cosine (mean / worst) โ | โ | 0.9983 / 0.992 | 0.9975 / 0.988 | 0.9954 / 0.982 |
| voiced artifact rate โ | โ | 4.8% | 6.7% | 20.7% |
No variant loses intelligibility. The WER differences (59โ62 errors) are within the noise of a test this size.
Blind listening test: Kokoro vs H512_G512. 22 pairs, one sentence per voice, random order, loudness-matched, including two hidden
catch pairs (Kokoro against itself), done in two sessions:
| comparison | prefers Kokoro | "same" | prefers the slim decoder |
|---|---|---|---|
Kokoro vs H512_G512 (20 pairs) |
1 | 18 | 1 |
Kokoro vs H512_G256_S128-128* (12 pairs) |
7 | 5 | 0 |
H512_G512 vs H512_G256_S128-128* (8 pairs) |
โ | 8 | โ |
* Tested at 5,000 training steps. The published weights are trained to 15,000 and are closer to Kokoro (test log-mel 0.245 โ 0.222), but the artifact rate did not change, so the result probably still holds.
The catch pairs were answered "same" every time (4 of 4). H512_G512 could not be told apart from Kokoro. H512_G256_S128-128 was never
preferred and lost 7 of 12, so it is audibly a little below Kokoro, though not distinguishable from H512_G512 in direct comparison.
Per-file reports are in results/; listen in samples/.
How it was made
Kokoro's decoder has two parts: a stack of AdaIN residual blocks (width 1024) and an iSTFTNet waveform generator (two upsampling
stages, 256 and 128 channels, then an inverse STFT). The variant names give the widths: H is the AdaIN width, G the generator input,
and S the per-stage generator widths when they differ from the default G/2, G/4.
- Pruning initialisation. Channels are ranked by weight importance and kept consistently across every tensor that reads or writes them, so each student starts from Kokoro's own strongest channels.
- Shared-excitation distillation. The generator is driven by a random sine-and-noise excitation. During training Kokoro and the student receive the same excitation draw on the same 1.6 s window, which makes Kokoro's waveform an exact, learnable target, phase included.
- Losses: multi-resolution STFT and log-mel, plus a multi-resolution complex STFT term. The shared excitation is what makes that term meaningful, and it removed a crackling artifact without any adversarial (GAN) training.
Data: 21.5 hours of Kokoro's own output: 12,000 sentences from 18 public-domain books, all 28 voices, 10% at varied speed. One
Apple M4 laptop GPU; 5,000 training steps for H512_G512, 15,000 for H512_G256_S128-128 and 30,000 for H512_G256 (each step is 25.6 s of audio). Code
and recipe are in training/.
What we learned about compressing this decoder
- The AdaIN blocks compress well. Halving them (1024 โ 512) costs nothing audible. They set the model's size but barely its speed.
- The generator's last stage decides both speed and quality. It runs at 4,800 frames per second and does most of the work. At 64 channels instead of Kokoro's 128, a voiced hoarse whistle appears that more training never removed. Restoring that single stage (+2.9M parameters) brings the artifact rate from 18.2% to 5.4%, and the speed-up from 2.65ร to 1.39ร.
- Mel distance can mislead. Between two of our models it disagreed with the listener and with every other measure; a phase-aware loss looked slightly worse by mel and sounded "better by far".
Limitations
- One listener, 20 pairs per comparison, no MUSHRA-style anchors. Treat "indistinguishable" as strong evidence, not proof.
An automatic perceptual judge (WavLM features) preferred
H512_G256_S128-128over Kokoro, while the listener preferred Kokoro. Learned judges are unreliable this close to the reference, so we rely on listening. - Speed-ups are for the decoder in PyTorch on one machine. Whole-pipeline gains are smaller because the text side is unchanged.
- English only (Kokoro's American and British voices). Quality is capped by Kokoro, including its mispronunciations.
Files
| path | contents |
|---|---|
slim.py |
Loader: Kokoro's KModel with a slim decoder. |
<variant>/decoder.safetensors, <variant>/config.json |
Decoder weights and widths. |
samples/ |
Kokoro and each variant on six test-set sentences. |
results/ |
Evaluation and speed reports (JSON) behind every number above. |
training/ |
Data preparation, teacher cache, distillation, evaluation, perceptual judge and benchmark scripts. |
License and attribution
Apache-2.0, like Kokoro-82M. The decoders are derived from Kokoro-82M by hexgrad (Apache-2.0), which builds on StyleTTS 2 and iSTFTNet. Training text is from Project Gutenberg (public domain).



