3.9 KiB
| name | description |
|---|---|
| speech-synthesis | Text-to-speech with Kokoro-82M (open weights, runs on CPU): synthesize WAV files with a female or male voice, choose British/American English and other languages, blend voices, set the speed, batch long texts, and play or embed the result. Use for any TTS, voice-over, audiobook, speaking assistant or "read this aloud" task. |
Speech synthesis with Kokoro
Kokoro-82M is a small, fast TTS model (Apache 2.0; ~330 MB download once).
Use the ready-made script tts.py - copy it into the project
(cp <skill-dir>/tts.py .) or import synthesize() from it.
Setup
pip install kokoro soundfile # torch comes with it; first run downloads the weights
apt install espeak-ng / brew install espeak-ng # only for non-English languages
Python 3.10-3.12 recommended. CPU is fine: ~1 s of audio per 0.1-0.3 s compute. A GPU is used automatically if torch sees one.
Female and male voice - the two calls that matter
from kokoro import KPipeline
import soundfile as sf, numpy as np
pipeline = KPipeline(lang_code='a') # 'a' American English, 'b' British English
# feminine voice
audio = np.concatenate([a for _, _, a in pipeline("Good morning! The report is ready.", voice='af_heart')])
sf.write('female.wav', audio, 24000)
# masculine voice
audio = np.concatenate([a for _, _, a in pipeline("Good morning! The report is ready.", voice='am_michael')])
sf.write('male.wav', audio, 24000)
pipeline(text, voice=..., speed=1.0) is a generator: one (graphemes, phonemes, audio) item per chunk (chunks split at newlines by default). Audio
is a float32 array at 24 kHz. Voices: af_*/am_* American female/male,
bf_*/bm_* British. Good defaults: af_heart (F), am_michael (M),
bf_emma (F, British), bm_george (M, British). python tts.py --list-voices
prints all.
Script
python tts.py "Hello there." --out hello.wav # af_heart (female)
python tts.py "Hello there." --voice am_michael --out hello_m.wav
python tts.py --file chapter.txt --voice bf_emma --lang b --speed 0.9 --out chapter.wav
python tts.py "Blend." --voice af_heart,am_michael --out blend.wav # average of two voices
synthesize(text, voice, lang, speed) -> (samples, 24000) splits at blank
lines and sentence ends, inserts 250 ms pauses and concatenates - no length limit.
Languages
Kokoro-82M v1.0: a American English, b British English, e Spanish,
f French, h Hindi, i Italian, j Japanese, p Brazilian Portuguese,
z Mandarin (pip install misaki[ja] / misaki[zh] for j/z). No German.
For German use Piper (pip install piper-tts, voice de_DE-thorsten-medium)
and say so in the summary instead of feeding German text to an English voice.
Using the audio
- Play:
pip install sounddevicethensd.play(samples, 24000); sd.wait(), orpython tts.py ... --play. - MP3/OGG: write WAV, convert with
ffmpeg -i out.wav -b:a 96k out.mp3. - Web page: serve the WAV and use
<audio controls src="out.wav">; for an in-browser TTS without Python see kokoro-js (kokoro-jsnpm, WebGPU/WASM). - Verify: check the duration (
len(samples)/24000) is plausible for the text (~2.5 words/s) and thatnp.abs(samples).max() > 0.05(not silence); for a listening check write a short sample and tell the user the file name.
Pitfalls
- First run is slow (weight download + model load); keep ONE
KPipelineper language and reuse it (tts.pycaches it). - Text with no sentence punctuation is spoken as one breathless chunk - add periods or newlines.
- Numbers, dates and abbreviations are read as written; expand them in the text ("3 km" -> "three kilometres") for clean output.
- Empty audio /
Nonein the generator: the chunk was empty or unpronounceable (only symbols). Skip it, don't crash. numpymust be < 2.0 for current kokoro releases (pip install "numpy<2"if the import fails).