nano-edge-tts
A 1.75M-parameter decoder for Kokoro-82M that runs no neural network at audio rate.
Kokoro's text side (pronunciation, timing, pitch and all voices) is unchanged. Its 53.3M-parameter waveform decoder is replaced by two small networks that run 80 and 160 times a second and set per-frequency gains on a pulse train and on white noise. Two inverse STFTs turn the result into audio.
Paper: No Network at Audio Rate: A 1.75M-Parameter Harmonic-plus-Noise Decoder for Kokoro-82M (method, results, listening tests and negative results).
| Kokoro-82M | nano-edge-tts | |
|---|---|---|
| decoder parameters | 53.3M | 1.75M |
| whole model parameters | 81.8M | 30.2M |
| decoder weights on disk | 213 MB | 7.0 MB |
| decoder speed, one CPU thread (real-time factor)¹ | 0.1378 | 0.0042 (33× faster) |
| phonemes to audio, one CPU thread (real-time factor)² | 0.1411 | 0.0127 (11× faster) |
| peak memory, whole pipeline² | 1.4 to 1.7 GB | 0.75 GB |
| Whisper small.en word errors, 240 sentences | 235 (4.63%) | 238 (4.69%) |
| UTMOS, 28 validation clips | 4.383 | 4.327 |
¹ 240 validation sentences, PyTorch, Apple M4. ² Six validation sentences, 55 s of audio, same machine. Raw numbers are in
results/.
How it sounds
The same sentence through Kokoro's decoder and through this one:
| voice | Kokoro-82M | nano-edge-tts |
|---|---|---|
| af_heart | ||
| af_bella | ||
| am_michael | ||
| am_fenrir | ||
| bf_emma | ||
| bm_george |
In blind A/B tests by one listener (the author), an earlier checkpoint was heard as the same as Kokoro on 9 of 12 pairs. The released model is close to Kokoro on most sentences and not identical: on some, voiced sounds between 1 and 4 kHz are a little too pure, heard as a faint machine-like tone. The paper describes the defect and two attempts to train it away that did not work.
Quick start
pip install kokoro==0.9.4 safetensors soundfile
hf download drmhse/nano-edge-tts --local-dir nano-edge-tts --exclude "samples/*"
cd nano-edge-tts
import numpy as np, soundfile as sf
from kokoro import KPipeline
from nano_edge_tts import load
pipe = KPipeline(lang_code='a', model=load()) # 'a' American English, 'b' British English
audio = np.concatenate([r.audio.numpy() for r in pipe('The decoder that made this has under two million parameters.', voice='af_heart')])
sf.write('out.wav', audio, 24000)
load() returns Kokoro-82M with its decoder replaced, so it works anywhere a KModel does. Kokoro's own weights and voices are
downloaded from its repository on first use. load_decoder() returns the decoder alone:
decoder(asr, F0, N, style) -> waveform, the same call as Kokoro's.
Files
| file | contents |
|---|---|
nano-edge-tts.safetensors, config.json |
Mapper and renderer weights (1,749,643 parameters) and their sizes |
nano_edge_tts.py |
The whole decoder in one file: excitation, STFTs, mapper, renderer, loader. Needs only PyTorch |
paper.pdf |
The paper |
samples/, samples.py |
The pairs above and the script that renders them |
results/ |
Evaluation on 240 validation sentences, and whole-pipeline speed and memory |
How it works
- Mapper (0.96M parameters, 80 frames/s): six ConvNeXt blocks turn Kokoro's decoder inputs into a 512-channel description of the sound.
- Renderer network (0.79M parameters, 160 frames/s): four ConvNeXt blocks output, per frame, a gain and a phase rotation for each of 301 frequency bins of a pulse train, and a gain for each of 61 bins of white noise at five sub-steps.
- Synthesiser (no parameters): a pulse train at the predicted pitch carries every harmonic, noise carries breath and consonants. The pulses use a 25 ms window, which separates harmonics; the noise uses a 5 ms window, which keeps consonant attacks sharp.
Training distils Kokoro's decoder: spectral losses against Kokoro's audio, waveform discriminators, and a critic on frozen WavLM layers that has to tell Kokoro's clips from this decoder's. None of those ship with the model.
Limitations
- Trained and evaluated on Kokoro's 28 American and British English voices. Other Kokoro languages run but are untested.
- Kokoro is the target, so this model is at best as good as Kokoro, and it inherits Kokoro's pronunciation and prosody.
- Kokoro's 28.5M-parameter text side is unchanged; it is now 94% of the parameters and 69% of the CPU time.
- A faint machine-like tone on some voiced sounds, most on two or three voices (see the paper).
- Listening results come from one listener. Speed was measured in PyTorch on a laptop CPU, not on a phone.
Licence and credit
Apache-2.0, the same as Kokoro-82M, whose text side and voices this model depends on. Kokoro-82M is by hexgrad. WavLM (Microsoft) was used only as a frozen feature extractor during training.
@misc{chumba2026nanoedgetts,
title = {No Network at Audio Rate: A 1.75M-Parameter Harmonic-plus-Noise Decoder for Kokoro-82M},
author = {Mike Chumba},
year = {2026},
url = {https://huggingface.co/drmhse/nano-edge-tts}
}
- Downloads last month
- 50


