Stand up a second deploy target on apex-simulation dedicated to "simulation"-style supplier capabilities, starting with CPU-only PiperTTS served via openedai-speech-min behind Traefik on :80. - deploy/simulation/docker-compose.traefik.yml: Traefik latest with introspection API, settles on Docker daemon 29.x API negotiation - deploy/simulation/docker-compose.tts-piper.yml: openedai-speech-min with curl-based healthcheck (image lacks wget, which Docker would have marked unhealthy and Traefik would filter from the docker provider) - deploy/simulation/deploy.sh: rsync-based deploy mirroring the apex-dashboard pattern; selective --traefik-only / --tts-only flags - deploy/simulation/install-voice-extras.sh + voice-mappings.py: idempotent post-deploy step that downloads en_US-lessac-high voice files into the bind-mount and registers a "lessac" alias in voice_to_speaker.yaml; survives a host wipe without manual steps - deploy/simulation/README.md: full host runbook - .gitignore: exclude data/ recursively, *.log, .vitest-cache, .DS_Store, __pycache__/, *.pyc, docs/*.zip
81 lines
3.5 KiB
YAML
81 lines
3.5 KiB
YAML
# deploy/simulation/docker-compose.tts-piper.yml — PiperTTS as OpenAI-compatible /v1/audio/speech
|
||
#
|
||
# Wraps rhasspy/piper (CPU neural TTS) behind matatonic/openedai-speech,
|
||
# which exposes the OpenAI Audio API (`POST /v1/audio/speech`). Once
|
||
# online behind Traefik on `apex-simulation`, this becomes a viable
|
||
# capability for a future `audio.synthesize.v1` supplier in the
|
||
# marketplace — same OpenAI-shaped HTTP surface as Ollama for chat.
|
||
#
|
||
# `*-min` image is the CPU/Piper-only variant (the full image pulls
|
||
# parler-tts + xtts which want a GPU). Default model is `en_US-amy-low`
|
||
# — small (~10 MB) and fast on CPU. Add `PRELOAD_MODEL=...` env to
|
||
# pre-warm a different voice on boot.
|
||
#
|
||
# Bring up:
|
||
# docker compose -f deploy/simulation/docker-compose.tts-piper.yml up -d
|
||
#
|
||
# Quick test (from any host that resolves the Traefik route):
|
||
# curl -s -X POST https://tts-piper.vector.testnet.apexfusion.org/v1/audio/speech \
|
||
# -H "Content-Type: application/json" \
|
||
# -d '{"model":"tts-1","input":"Hello from the marketplace.","voice":"alloy","response_format":"wav"}' \
|
||
# -o /tmp/out.wav && aplay /tmp/out.wav # or `mpv` / `ffplay`
|
||
|
||
name: marketplace-tts-piper
|
||
|
||
services:
|
||
tts-piper:
|
||
image: ghcr.io/matatonic/openedai-speech-min:latest
|
||
container_name: marketplace-tts-piper
|
||
restart: unless-stopped
|
||
environment:
|
||
# Pre-load Piper's highest-quality American-English voice so first
|
||
# /v1/audio/speech doesn't pay the model-download tax. `-high`
|
||
# variants are 60–70 MB and noticeably more natural than `-low`/
|
||
# `-medium` on CPU. Browse alternatives at
|
||
# https://huggingface.co/rhasspy/piper-voices/tree/main
|
||
# en_US-lessac-high — clean female, very natural (default)
|
||
# en_GB-alan-high — British male
|
||
# en_US-ryan-high — American male
|
||
# en_US-libritts_r-medium — multi-speaker (904 voices)
|
||
PRELOAD_MODEL: en_US-lessac-high
|
||
# Expose port — matches the loadbalancer label below.
|
||
PORT: "8000"
|
||
volumes:
|
||
# Host bind mounts (not Docker named volumes) so the deploy user can
|
||
# `ls`/`du`/back-up the downloaded Piper voices directly without
|
||
# `docker volume inspect`. Paths are relative to THIS compose file,
|
||
# i.e. `deploy/simulation/data/tts-piper/{voices,config}` from the
|
||
# repo root. Create the dirs once before `compose up` (see README).
|
||
- ./data/tts-piper/voices:/app/voices
|
||
- ./data/tts-piper/config:/app/config
|
||
healthcheck:
|
||
# /v1/models is the OpenAI-shape model list; a 200 here proves the
|
||
# server is up and at least one voice is loaded. Image ships with
|
||
# curl (and python3) but NOT wget — using wget here marks the
|
||
# container unhealthy on every probe, and Traefik then filters it
|
||
# out of the docker provider ("Filtering unhealthy or starting
|
||
# container"), which means no router ever registers.
|
||
test: ["CMD-SHELL", "curl -fsS http://localhost:8000/v1/models >/dev/null || exit 1"]
|
||
interval: 30s
|
||
timeout: 5s
|
||
retries: 3
|
||
start_period: 90s
|
||
networks:
|
||
- traefik-net
|
||
labels:
|
||
- "traefik.enable=true"
|
||
- "traefik.docker.network=traefik-net"
|
||
- "traefik.http.routers.tts-piper.entrypoints=web"
|
||
- "traefik.http.routers.tts-piper.rule=Host(`tts-piper.vector.testnet.apexfusion.org`)"
|
||
- "traefik.http.services.tts-piper.loadbalancer.server.port=8000"
|
||
logging:
|
||
driver: json-file
|
||
options:
|
||
max-size: "10m"
|
||
max-file: "3"
|
||
|
||
networks:
|
||
traefik-net:
|
||
external: true
|
||
name: traefik-net
|