Adding Kokoro TTS to a Python voice assistant
I needed text-to-speech output for Foreman's voice mode. The first step was a license check.
License check blocked Piper
The scope document warned that Piper's maintained repo might have switched to GPL. PyPI confirmed it: piper-tts 1.5.0 is GPL-3.0-or-later. I picked kokoro-onnx instead. The package is MIT and the model is Apache 2.0.
Python 3.14 compatibility
Both kokoro-onnx and the kokoro package cap their Python version below 3.14. The pip resolver fell back to kokoro-onnx 0.4.7, a pure-Python wheel with no version cap. It worked with onnxruntime 1.24.2 and numpy 2.4.0 already installed.
Implementation
I built tools/speak.py with a say() function that synthesizes via Kokoro and plays through sounddevice. It loads lazily and downloads the 196 MB model on first run into a gitignored models/ folder. Any failure prints "(speech unavailable)" and returns without raising.
I added three summarize functions to foreman.py that generate one or two sentence spoken headlines. Numbers render naturally: "755 dollars", "19 percent". The say() call only runs inside run_voice(), using the same lazy import pattern as the speech recognition stack.
I verified that typed commands stayed byte-for-byte identical and silent, and that the speech stack never loads on the typed path. Warm synthesis took 1.2 to 1.7 seconds. The live mic and speaker test passed on both git and memstack summaries.
Model choice
I picked the fp16 model over f32 and int8. It is 169 MB, loads faster than f32, and the quality margin matters when reading dollar figures.
The say() function uses a broad except block. TTS must never break the command loop.