sanoTTS

सानो — small
a tiny neural text-to-speech voice · sano (सानो) is Nepali for small

The smallest neural text-to-speech family we know of — and it plays right here, live, in your browser.

a full neural stack — duration → acoustic → decoder — quantized to int8, phonemizer and all. 28 voices, 16 languages, all spoken on this page.


Synthesize live in your browser

Type anything. The text is phonemized by espeak-ng compiled to WebAssembly (the same 275 KB port that runs on the chip; Chinese uses a 448 KB pinyin lexicon instead) and spoken by that voice's own neural stack — all client-side, no server. Pick a voice:

loading runtime…
Phonemes
Audio produced
Time (this CPU)
Speed on this machine

The speed shown is this browser on your CPU — the on-device English voice runs at 0.22× real time on an ESP32-S3. Every voice in the picker synthesizes your typed text live, right here, with no server involved. Where a language offers two sizes, the chips under its mascot switch between them. heart and heart-nano take a different route from text to sound than the other voices (a 100-band mel interface into a noise-shaping decoder), so they load their own small runtime; heart-nano runs the int8 arithmetic of the microcontroller build unchanged.


How it compares

Measured with our no-reference harness (SCOREQ / UTMOS / DNSMOS-SIG) on the same 24-sentence diverse set, run identically across every model below.

Size comparison (parameters)

Size comparison (parameters) 0 20M 40M 60M 80M parameters — linear axis, so the sliver IS the point sanoTTS (11 voices) 0.29M–2.27M params sanoTTS family: largest voice heart, 2.27M params sanoTTS family: smallest voice heart-nano, 294k params 0.29M–2.27M TinyTTS 1.62M params TinyTTS: 1.62M params, ships 3.5 MB fp16 (verified from their Hugging Face repo) 1.62M Inflect Nano 4.63M params Inflect Nano: 4.63M params 4.63M Kokoro 82M params Kokoro: 82M params, ~330 MB fp32 (widely cited public figure) 82M

Kokoro is 36× larger than our largest voice — and 279× larger than our smallest.

Shipped-file sizes: sanoTTS amy 2.8 MB fp16 and TinyTTS 3.5 MB fp16, both verified from the released files; Kokoro's ~330 MB fp32 is its widely cited public figure.

Three metrics, head to head

sanoTTS amy1.46M params sanoTTS heart2.27M params TinyTTS1.62M params Inflect Nano4.63M params
SCOREQ 4.133.483.943.81
UTMOS 4.103.383.653.65
DNSMOS-SIG 3.613.513.623.58

Same 24-sentence set, three independent no-reference metrics; best value per row in crimson. sanoTTS amy leads on SCOREQ and UTMOS; on DNSMOS-SIG TinyTTS edges us by 0.01 — no single metric tells the whole story. heart is a different voice and recipe (24 kHz, noise-shaping decoder) scored on the identical 24 sentences; heart-nano, its 294k sibling, scores 2.29 / 2.45 / 3.35 on the same three metrics.

The size-quality frontier we traced

The size-quality frontier we traced 3.6 3.8 4.0 4.2 1.09M 1.35M 1.84M 1.09M params, SCOREQ 3.70 1.19M params, SCOREQ 3.73 1.35M params, SCOREQ 4.08 1.46M params, SCOREQ 4.13 1.84M params, SCOREQ 4.16 3.70 4.16

Same voice (amy), same duration/acoustic recipe — only decoder size changes. Quality lives in the decoder: doubling it from 1.09M to 1.84M params moves SCOREQ from 3.70 to 4.16.

Every language we ship, and what we know about it

WER is Whisper word error rate over 16 held-out Tatoeba sentences per language — conversational text, deliberately a different domain from the corpus these voices were distilled on. The sample buttons synthesize that language on this page, right now, through the same runtime as the picker above. Where a language ships in two sizes, both are playable. Chinese is the one exception: written Chinese has no spaces, so word error rate means nothing there and the figure is character error rate over the same 16 Tatoeba sentences, with traditional and simplified folded together. On held-out FLORES that voice scores 0.199 against its teacher’s 0.188 — the voice it replaced scored 0.468.

LanguageWERSample
Portuguese 🇧🇷 0.038
Italian 🇮🇹 0.080
German 🇩🇪 0.099512k · 0.145
Russian 🇷🇺 0.120
Spanish 🇪🇸 0.147
French 🇫🇷 0.221
Indonesian 🇮🇩 0.256
Arabic 🇯🇴 0.274
Turkish 🇹🇷 0.303
Czech 🇨🇿 0.351
Romanian 🇷🇴 0.392
Vietnamese 🇻🇳 0.468
English 🇺🇸
Nepali 🇳🇵
Hindi 🇮🇳
Chinese 🇨🇳 0.024CER, not WER

Lower is better. Press play to judge the rest.


What these numbers are, and are not. WER is measured with Whisper over 16 held-out Tatoeba sentences per language — directional, not precise. It says the words come through; it says nothing about whether a voice sounds good. No listening test has been run on any of the ten languages added on 2026-09-08, and none of them has a SCOREQ. Czech, Romanian and French got worse on unseen text than on the corpus they were trained on, so they are the ones to press first. Indonesian and Vietnamese are the espeak arm of a paired A/B — the phoneme path this page actually runs. Everything above is reproducible from experiments/evidence/ood-tatoeba-20260908.json, idvi-espeak-free-ab-20260904.json and heart-diverse24-remeasure-20260904.json.

Open source under GPL-3.0 — builds on piper and espeak-ng. Distill your own tiny voice: github.com/Ampixa/sanoTTS.