A 15M-parameter Piper (VITS) voice that I taught three emotions by distilling them from a 3B expressive
speech model. Write emotion tags inline and the voice changes mid-paragraph. Nothing leaves your device: the model
runs here with ONNX Runtime Web.
~15M params · 77 MBneutral · happy · sadruns offline after first loadWASM or WebGPU
Insert tag:Text before the first tag uses the default emotion. Devanagari works best; English words written in Devanagari (ऑर्डर, कन्फर्म) are fine.
The voice downloads on the first click (77 MB model + 18 MB Hindi phoneme data), then your browser caches it.
audio
–
synthesis
–
real-time factor
–
backend
–
Try one
How it was made
Teacher: Rumik-oss-1 (a 3B speech LM that follows emotion descriptions) generated the same Hindi
sentences as neutral, happy and sad in one voice. A speech-emotion classifier, a speaker-similarity check and a
forced aligner filtered and trimmed the clips.
Student: Piper's VITS "medium" model, fine-tuned on Kaggle's free 2×T4 from the Hindi rohan
checkpoint, with emotion as the speaker ID. Round 2 started happy from an extrapolated embedding (×3 away from
neutral); round 3 adds 162 stronger happy clips selected by pitch.
In the browser: espeak-ng (WebAssembly) turns text into phonemes, ONNX Runtime Web runs the voice,
and each tagged span is synthesized with its own emotion ID and joined with a short pause.
Honest limits: sad is clearly different (slower, softer); happy is lighter and higher but still
subtle. Emotion is per span, not per word, and Roman-script Hinglish is read poorly.
Self-check: does the browser phonemizer match training?
Compares the phoneme IDs produced here with the IDs Python Piper produced for 43 test sentences.
Any mismatch would mean the browser voice reads text differently from how it was trained.