Mira (en_US) — a Piper voice that actually laughs
A free Piper voice (VITS, medium, 22.05 kHz, LJSpeech-derived timbre) with trained non-verbal expressions: real laughs, sighs, gasps, groans, and throat-clears — produced by the vocal model itself, not spliced-in sound effects.
🔊 Listen: samples/laugh_demo.wav ·
samples/sigh_throat_demo.wav
What it does that other Piper voices don't
Standard Piper voices can only read text. This voice was fine-tuned in
phoneme_ids mode with unused phoneme IDs repurposed as non-verbal marker
tokens, then trained on an emotive corpus (distilled from ChatterBox Turbo,
MIT) in which those markers align with genuine non-verbal audio. Inject a
marker at synthesis time and the model performs it, in-voice, with natural
prosody flowing through it:
| Tag | Phoneme id | Marker char | Repeat |
|---|---|---|---|
[laugh] |
39 | æ |
5 |
[sigh] |
40 | ç |
3 |
[gasp] |
42 | ø |
2 |
[groan] |
43 | ħ |
3 |
[clear throat] |
45 | œ |
3 |
(markers.json in this repo is the canonical map.)
Usage
Plain speech works like any Piper voice:
echo "The quick brown fox jumps over the lazy dog." | \
piper -m en_US-mira-tokens2.onnx -f out.wav
Non-verbals need id-level synthesis — normal Piper phonemizes text through
espeak, which can never emit the marker characters. mira_synth.py (MIT,
included) is the reference implementation: it phonemizes the text segments,
splices the marker char (× its repeat count) where a [tag] appears, converts
to ids once, and calls phoneme_ids_to_audio:
from piper import PiperVoice
import json
from mira_synth import synth_expressive
voice = PiperVoice.load("en_US-mira-tokens2.onnx")
markers = json.load(open("markers.json"))
wav = synth_expressive(voice, markers, "Oh that's funny [laugh] tell me the rest.")
open("out.wav", "wb").write(wav)
⚠️ The phoneme-dialect trap (read this before fine-tuning or re-exporting)
This model's phoneme inventory was built with espeak voice en — NOT
en-us. The shipped config already says "voice": "en". Do not change it,
and do not phonemize inputs with en-us. Two things break if you do:
en-usemitsæfor TRAP vowels ("half", "crash", "laugh"…) — and in this voiceæis repurposed as the laugh token (id 39). Phonemize with the wrong dialect and TRAP-vowel words trigger giggles mid-word or collapse into mangled forms ("half" → "huff"-like artifacts). This is not hypothetical; we shipped that bug to ourselves once.en-usadds diphthong symbols (aɪ aʊ ɔɪ eɪ oʊ) that map to ids this model never trained — silent quality damage on any word containing them.
If you fine-tune further: pass --data.espeak_voice en to the Piper trainer,
and note that some trainer versions regenerate the exported config from the
training flag — if your flag says en-us, the exported .onnx.json will
too, and the corruption becomes the model's default. Check the exported
config's "voice" field before deploying. The extra en-us symbol entries a
bad export adds (diphthongs at ids 161–165) are the fingerprint of this
mistake.
Lineage & licensing
- Base: Piper
en_US-ljspeech-mediumcheckpoint — LJSpeech dataset is public domain. - Emotive teacher: ChatterBox Turbo (MIT) — ~520-clip distillation corpus conditioned on the LJSpeech timbre, including genuine non-verbal vocalizations aligned to the marker tokens.
- Training: Piper trainer,
phoneme_idsmode, marker tokens as above. - Weights: CC0-1.0 (public domain dedication).
mira_synth.py: MIT. - The Piper runtime is a separate install and carries its own license.
Made in a home lab as part of an embodied-companion project; shared so other Piper users can have voices that breathe. No cloud, no strings.