- config/: phrases.json (mappa phrase_id->testo) e config.json (voce, output dir) - src/tts/: render.py (render incrementale) e play.py (riproduzione, no rete) - clips/ e voices/ gitignorati (artefatti generati / modelli scaricati) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
3.0 KiB
TTS-Piper — Step 1: frasario audio
Pre-renders four Italian phrases to WAV clips with Piper
and plays them back. At runtime nothing is synthesized and nothing is decided:
play.py just plays a WAV file that was rendered ahead of time.
Project layout
.
├── README.md project overview (this file)
├── requirements.txt Python dependencies
├── .gitignore excludes generated/downloaded artifacts
├── config/ data & configuration (edited by humans)
│ ├── config.json voice model path, voice config path, output directory
│ └── phrases.json map: phrase_id -> Italian text
├── src/ source code
│ └── tts/ the TTS component (one package per component)
│ ├── __init__.py
│ ├── render.py render phrases -> clips
│ └── play.py play a pre-rendered clip
├── voices/ downloaded Piper voice models (gitignored)
└── clips/ generated WAVs + .rendered.json (gitignored)
The structure is meant to grow: a new component (bus, dashboard, adapter…) gets
its own package under src/, not bolted onto tts/. Paths in config.json are
resolved relative to the project root (or absolute); nothing is hardcoded to an
absolute path, so the scripts run from any working directory.
Install
Python 3 with pip. One dependency:
python3 -m pip install -r requirements.txt
Download the Italian voice once (needs network; only at render time):
python3 -m piper.download_voices it_IT-paola-medium --download-dir voices
This writes voices/it_IT-paola-medium.onnx and voices/it_IT-paola-medium.onnx.json.
For playback you also need one audio player on the system; play.py looks for
paplay, aplay, or ffplay (in that order). On Ubuntu these come from
pulseaudio-utils / alsa-utils / ffmpeg and are usually already present.
Render the clips
python3 src/tts/render.py
Produces clips/routine_started.wav, clips/obstacle_detected.wav,
clips/object_lost.wav, clips/routine_finished.wav.
Re-runnable and incremental: edit a phrase in config/phrases.json, run
render.py again, and only that phrase's WAV is regenerated (the others are
reported as "up to date, skipped"). The clips/.rendered.json manifest records
the text each clip was rendered from. Delete a WAV (or the manifest) to force a
re-render.
Play the clips (no network)
python3 src/tts/play.py routine_started # one clip by phrase_id
python3 src/tts/play.py --all # all clips, in phrases.json order
Voice used
- Voice:
it_IT-paola-medium(Italian, female, "medium" quality, 22.05 kHz). - Source: the Piper voices collection
rhasspy/piper-voiceson Hugging Face, fetched bypython3 -m piper.download_voices.
To use a different voice: download it into voices/ and update voice_model /
voice_config in config/config.json.