Offline text to speech generation, using the Kokoro-82M model.
Four tools:
speak.py— speak a fixed phrase once, with timing statssay.py— interactive keyboard control over SSH, with preset phrases, voice and speed controllisten.py— live speech to text from the microphone, using faster-whispertalk.py— wake word loop, listens for a command and speaks a reply
Both use CUDA when available. Pass --cpu to force CPU inference. Every script takes --help.
./speak.py
./speak.py --cpu
./say.py
./say.py --cpu./install.sh
./install.sh --listenWorks on linux and mac. Installs uv when missing, installs espeak-ng with brew or apt, plus alsa-utils on linux, then creates .venv and installs kokoro, torch, and soundfile into it.
Pass --listen to also install speech to text for listen.py and talk.py, see below.
On first run, the model and all voices download into cache/.
Speak a single block of text. Edit the TEXT constant in speak.py to change what is spoken.
Generated audio files are saved in audio/ as 001.wav, 002.wav, etc.
Interactive speech tool. Press keys to speak phrases.
Single keypresses work without Enter. Preset phrases are in phrases.json, triggered by keys 1–9.
| Key | Action |
|---|---|
t |
Type a custom phrase |
r |
Repeat last custom phrase |
c |
Cancel current speech |
x |
Clear queued speech |
+ / - |
Speed up / down |
v |
Next voice |
h |
Show help |
q |
Quit |
Default speed is 1.5x. Use + / - to adjust, v to change voice.
Generated audio files are saved in audio/.
Pass --test to speak the first two preset phrases and exit.
Live transcription from the microphone. Speak and lines print as you talk, CTRL-C to stop.
./install.sh --listen
./listen.pyOn a machine with the CUDA toolkit, --listen clones and builds CTranslate2 with CUDA for the Jetson GPU, then installs it and faster-whisper into .venv. The build takes around 30 minutes and only runs once. Everywhere else it installs the CPU wheels from PyPI, plus sox on mac.
Uses the whisper base model with voice activity detection, on GPU when available. Records with arecord from the first USB soundcard with a mic on linux, and with sox from the default input device on mac.
Say the wake word robot, then a command, and it speaks a reply. Say robot, quit or CTRL-C to stop. Needs the same install as listen.py.
./install.sh --listen
./talk.pySay it all in one breath, robot, what is the time, and it answers straight away. Say just robot and it replies Yes?, then waits for the command.
The microphone stays open the whole time. A background thread reads it into blocks, the silero voice activity detector finds where each utterance starts and ends, and only whole utterances go to whisper. Nothing is missed between turns, and silence is never transcribed. The mic is muted only while it speaks, so it does not hear itself.
Replies to a few built in commands like the time, the date, and its name, and echoes anything else back. Edit make_reply in talk.py to add more. Say quit or exit as the command and it says Goodbye! and stops.
When it nearly hears its name, a transcription with rob or rub in it but not robot, it plays the recording back and says what it heard, so you can tell why it did not wake. Near miss words are in NEAR_WAKE_WORDS.
Pass --test to run one exchange and exit. It skips the wake word, speaks What is the time? so it hears itself through the mic, then answers. When the mic cannot hear the speaker it falls back to the question text.
Three flags help check what the mic picked up, and combine with each other and with --test:
--replayplays the recording back after each utterance, saved asaudio/heard.wav--replay-robotplays back only what was said to it, the utterance with the wake word in it and any command that follows, so a busy room is not replayed back at you--repeatsays the transcribed words back after each utterance
All mute the mic while playing, so it does not hear itself.
./test.py
./test.py --freshRuns speak.py and say.py --test online, with --cpu, and offline, then talk.py --test. Pass --fresh to clear cache/ and audio/ first. Requires internet when the model is not cached.
The talk step is skipped when faster-whisper or a microphone is missing.
tools-audio.sh— route audio to any USB soundcard, disable HDMI and APE outputs. Run./tools-audio.sh --installonce, then./tools-audio.shafter plugging in a new adaptertools-power.sh— set Jetson power mode. No args shows status
./tools-power.sh # status
./tools-power.sh min # 15W, coolest/quietest, clocks scale with load
./tools-power.sh mid # 25W, balanced
./tools-power.sh max # 25W uncapped, full performance, clocks locked hightools-offline.sh— block internet for offline testing,./tools-offline.sh --fixto restore
- First
say.pylaunch downloads all voices and takes longer. Later launches are faster. min/midturn offjetson_clocksso CPU frequency can drop when idle.maxturns it back on.midandmaxare both 25W-class;maxunlocks clocks fully (MAXN_SUPER).