Piper text-to-speech (synaplan-tts)

Module id: piper_tts · Kind: sidecar · Configured by: SYNAPLAN_TTS_URL · Capability: text_to_speech · Provider: piper

Spoken answers without a cloud: synaplan-tts is a small HTTP service around Piper with five voices baked into the image — English, German, Spanish, French, Turkish. The UI language picks the voice; the audio never leaves your infrastructure. Off by default.

The companion page Text-to-Speech covers voices, the image and adding your own models. This page is the module view.


What it adds

  • The speaker control on chat answers, using a local voice.
  • The text_to_speech capability the assistant can use in multi-task plans ("read this back to me").
  • A voice per UI language — German UI → Thorsten, Spanish → davefx, and so on — with no separate picker to configure.

Without it

The speaker control does not appear and the capability inventory reports text-to-speech as unavailable — unless you use a cloud voice instead: ELEVENLABS_API_KEY, or a catalog TTS model from Gemini, Mistral Voxtral or xAI. Those live inside the main app and do not need this module. Speech input (Whisper transcription) ships with the core and is unaffected either way.


How to enable

Option A — Compose profile (recommended)

docker compose --profile tts up -d                                   # dev / evaluation stack
docker compose -f docker-compose-minimal.yml --profile tts up -d     # minimal stack

This pulls ghcr.io/metadist/synaplan-tts and binds it to 127.0.0.1:10200. Both Compose files default SYNAPLAN_TTS_URL to http://host.docker.internal:10200, so the backend finds it without further configuration.

Option B — standalone container, same or another host

docker run -d --name synaplan-tts \
  -p 127.0.0.1:10200:10200 \
  ghcr.io/metadist/synaplan-tts:latest

Then point the backend at it and restart backend + worker:

SYNAPLAN_TTS_URL=http://host.docker.internal:10200    # same host
SYNAPLAN_TTS_URL=http://10.0.0.7:10200                # a LAN box or GPU host serving several Synaplan nodes

Production deploy/compose.yaml does not include the service; use Option B and set the variable in deploy/.env.


Check it works

  • Operate → Feature StatusPiper text-to-speech shows Available / Synaplan TTS is running. The probe is GET /health on the service. Synaplan TTS is not reachable means the URL is set but nothing answered; SYNAPLAN_TTS_URL is unset means the module is off.
  • Send a chat message and click the speaker icon on the answer.
  • Directly:
curl -s http://127.0.0.1:10200/health

Configuration reference

Variable Default Meaning
SYNAPLAN_TTS_URL empty (Compose: http://host.docker.internal:10200) Base URL of synaplan-tts. Empty = module off.

Extra voices: mount .onnx + .onnx.json Piper models into the service's extra-voices volume — see the synaplan-tts README. Cloud alternatives (ELEVENLABS_API_KEY, catalog TTS models) are provider settings, not part of this module.


Troubleshooting

  • not reachable although curl on the host works. The backend resolves the URL from inside its container. localhost there is the backend; use host.docker.internal (Compose adds the mapping) or the host's LAN address.
  • No speaker icon. The control only renders when the service answers; check Feature Status first, then the browser console for the /api/v1/tts/stream call.
  • Wrong voice. The backend sends the frontend locale; if it detects a different reply language, that language's voice wins. There is no manual voice picker by design.

Related