Files
petal/deploy
prosolis 2363ef2d37 Make Piper's synthesis path configurable (TTS_PATH)
piper-tts 1.6.0 moved synthesis from POST / to POST /synthesize, with an
identical request body; the VPS sidecars run 1.6.0 and returned 405 to
every read-aloud request, while millenia's older server still expects /.
Rather than pinning both deployments to one Piper release, the path is
configuration -- default "/" keeps millenia working untouched, and the
compose stack sets /synthesize. The container healthcheck moves with it,
since it was probing the old route too.
2026-07-26 23:15:01 -07:00
..

Deploying read-aloud (Piper TTS) to millenia

Petal's read-aloud generates audio with a local Piper neural-TTS server and transcodes it to mp3 with ffmpeg. Both run on millenia (192.168.1.212); nothing leaves the box. If Piper is down or TTS_ENDPOINT is unset, the frontend falls back to the browser's Web Speech API automatically.

1. Piper as a systemd service (one-time)

# from this repo, on your workstation:
scp deploy/piper.service deploy/setup-piper.sh 192.168.1.212:/tmp/
ssh 192.168.1.212 'cd /tmp && sudo ./setup-piper.sh'

setup-piper.sh creates ~/piper/venv, installs piper-tts[http], downloads the en_US-amy-medium voice into ~/piper/voices, installs+enables piper.service (loopback :5005), and smoke-tests it. Idempotent.

Check it any time: systemctl status piper, journalctl -u piper -f.

2. Point petal at Piper + redeploy the binary

Add to petal's environment (its .env or launch env):

TTS_ENDPOINT=http://127.0.0.1:5005
TTS_VOICE_EN=en_US-amy-medium
TTS_AUDIO_FORMAT=mp3

Then ship the rebuilt binary (go build -o petal ./cmd/server already done) and restart the petal :8088 session. Confirm the log line: read-aloud enabled (TTS endpoint=http://127.0.0.1:5005).

3. Verify

# on millenia — end-to-end through petal, including ffmpeg transcode:
curl -sf -X POST localhost:8088/api/tts \
  -H 'Content-Type: application/json' \
  -d '{"text":"hello there","lang":"en-US"}' -o /tmp/petal-tts.mp3 \
  && file /tmp/petal-tts.mp3   # expect: Audio file ... MPEG ... layer III
  • Second identical call is served from the cache (~/petal/.../data/tts/*.mp3).
  • A language with no configured instance returns 404 → client uses Web Speech.
  • Browser check via the uitest harness (~/petal/uitest): tap a word in the WordCard / select a sentence and hit speak — expect the natural Piper voice.

Chinese voice (live)

Each Piper HTTP server loads ONE model, so Chinese runs as a second instance: piper-zh.service on :5006 with zh_CN-huayan-medium. Deployed via:

scp deploy/piper-zh.service 192.168.1.212:~/.config/systemd/user/
ssh 192.168.1.212 'export XDG_RUNTIME_DIR=/run/user/$(id -u)
  ~/piper/venv/bin/python -m piper.download_voices zh_CN-huayan-medium --data-dir ~/piper/voices
  systemctl --user daemon-reload && systemctl --user enable --now piper-zh.service'

Then in petal's start.sh: TTS_ENDPOINT_ZH=http://127.0.0.1:5006 and TTS_VOICE_ZH=zh_CN-huayan-medium. The handler maps language → instance from config, so adding more languages is just another instance + env pair (no code change).