Step 1: frasario audio Piper (render + play) con struttura a componenti
- 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>
This commit is contained in:
commit
d3164e2e96
8 files changed
+275
No files matched your search
@@ -0,0 +1,80 @@
|
||||
# TTS-Piper — Step 1: frasario audio
|
||||
|
||||
Pre-renders four Italian phrases to WAV clips with [Piper](https://github.com/OHF-Voice/piper1-gpl)
|
||||
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:
|
||||
|
||||
```bash
|
||||
python3 -m pip install -r requirements.txt
|
||||
```
|
||||
|
||||
Download the Italian voice once (needs network; only at render time):
|
||||
|
||||
```bash
|
||||
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
|
||||
|
||||
```bash
|
||||
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)
|
||||
|
||||
```bash
|
||||
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-voices` on Hugging Face,
|
||||
fetched by `python3 -m piper.download_voices`.
|
||||
|
||||
To use a different voice: download it into `voices/` and update `voice_model` /
|
||||
`voice_config` in `config/config.json`.
|
||||
Reference in new issue
Block a user