Duck all PulseAudio sink-inputs (Firefox, Spotify, etc.) before speech, crossfade the entry tone over the fading media, then restore volumes after the exit tone. Uses pactl subprocesses for reliable PipeWire compatibility — pulsectl-asyncio's native protocol writes are silently dropped by PipeWire's PA compat layer. New module media_duck.py with MediaDucker class. Unduck is consolidated into the consumer's finally block to guarantee restoration on all exit paths (normal, error, cancel, shutdown).
80 lines
2.4 KiB
YAML
80 lines
2.4 KiB
YAML
services:
|
|
tts-mcp:
|
|
build: .
|
|
container_name: tts-mcp
|
|
restart: unless-stopped
|
|
# Must exceed: 3s handler drain + TTS_SHUTDOWN_TIMEOUT + 5s safety margin.
|
|
# Default: 3 + 30 + 5 = 38s. Increase if TTS_SHUTDOWN_TIMEOUT > 30.
|
|
stop_grace_period: 38s
|
|
env_file: .env
|
|
environment:
|
|
# Override for Docker networking (container DNS instead of IPs)
|
|
TTS_PIPER_HOST: piper-tts
|
|
TTS_ORPHEUS_URL: http://llama-server:8081
|
|
# PipeWire client config
|
|
XDG_RUNTIME_DIR: /run/user/1000
|
|
# PulseAudio socket for media ducking (bypass XDG_RUNTIME_DIR ownership check)
|
|
PULSE_SERVER: unix:/run/user/1000/pulse/native
|
|
# Force unbuffered Python output so stderr shows up in docker logs immediately
|
|
PYTHONUNBUFFERED: "1"
|
|
volumes:
|
|
# Kokoro ONNX models (read-only)
|
|
- ./models:/app/models:ro
|
|
# HuggingFace cache for SNAC model download (lazy-loaded on first Orpheus call)
|
|
- hf-cache:/home/tts/.cache/huggingface
|
|
# Persistent data (voice assignments, etc.)
|
|
- tts-data:/data
|
|
# PipeWire socket for audio playback through host speakers
|
|
- /run/user/1000/pipewire-0:/run/user/1000/pipewire-0
|
|
# PulseAudio compat socket for media ducking (volume control)
|
|
- /run/user/1000/pulse:/run/user/1000/pulse
|
|
depends_on:
|
|
llama-server:
|
|
condition: service_healthy
|
|
networks:
|
|
- caddy
|
|
- dootie-internal
|
|
labels:
|
|
caddy: mctalkbox.l.supported.systems
|
|
caddy.reverse_proxy: "{{upstreams 8371}}"
|
|
|
|
llama-server:
|
|
build:
|
|
context: .
|
|
dockerfile: llama-server.Dockerfile
|
|
container_name: orpheus-llama-server
|
|
restart: unless-stopped
|
|
deploy:
|
|
resources:
|
|
reservations:
|
|
devices:
|
|
- driver: nvidia
|
|
count: 1
|
|
capabilities: [gpu]
|
|
volumes:
|
|
# GGUF model file (set ORPHEUS_GGUF_PATH in .env, e.g. from Ollama blob storage)
|
|
- ${ORPHEUS_GGUF_PATH}:/models/orpheus.gguf:ro
|
|
command: >-
|
|
--host 0.0.0.0 --port 8081
|
|
--model /models/orpheus.gguf
|
|
--n-gpu-layers 999 --ctx-size 4096
|
|
--flash-attn --cont-batching
|
|
networks:
|
|
- dootie-internal
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-sf", "http://127.0.0.1:8081/health"]
|
|
interval: 15s
|
|
timeout: 5s
|
|
start_period: 120s
|
|
retries: 5
|
|
|
|
volumes:
|
|
hf-cache:
|
|
tts-data:
|
|
|
|
networks:
|
|
caddy:
|
|
external: true
|
|
dootie-internal:
|
|
external: true
|