feat(tts): default to offline GPU MeloTTS with brain-role worker

Switch the default TTS engine from online Edge TTS to offline GPU
MeloTTS (privacy-first: reply text never leaves the host). Adds a
supervisord melo-worker program that runs in full/bot/brain roles and
synthesises Korean on the GPU (MELO_DEVICE=cuda, MELO_SPEED=1.5), a
baked /opt/melo py3.11 venv layer in the Dockerfile, and compose/env
defaults. Edge TTS stays available as an opt-in online fallback via
TTS_ENGINE=edge.

Verified on the RTX 5050 (Blackwell sm_120): melo-worker logs
"ready (lang=KR speed=1.5 device=cuda)", /health returns ok, and a
/synth round-trip returns a 177KB WAV.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
javis-bot
2026-07-22 20:39:54 +09:00
parent 8562548571
commit bb60c4db3b
5 changed files with 65 additions and 20 deletions

View File

@@ -65,10 +65,19 @@ RUN ls -d /opt/venv/lib/python*/site-packages/nvidia/cublas/lib \
> /etc/ld.so.conf.d/nvidia-cu12.conf 2>/dev/null \
&& /sbin/ldconfig || true
# --- Korean voice: Microsoft Edge TTS (online neural). No model is baked — the
# `edge-tts` pip package (in requirements-bridge.txt) calls the MS service at
# runtime and the bridge transcodes the MP3 to PCM16 with ffmpeg. No heavy
# TTS build layer is needed. ---
# --- Korean voice: GPU MeloTTS (offline, privacy-first) in a separate /opt/melo
# py3.11 venv; see docker/setup-melo.sh. Heavy layer (torch cu128 GPU +
# transformers + MeCab + baked KR model), placed before the app COPY so it
# stays cached across source-only changes. Runtime device is MELO_DEVICE=cuda
# (compose), so TTS synthesises on the GPU next to Ollama + Whisper. Started
# only in full/bot/brain roles (see docker/supervisord.conf). The offline
# Edge TTS (`edge-tts`, in requirements-bridge.txt) remains available as an
# opt-in fallback via TTS_ENGINE=edge, but it is ONLINE (text leaves the
# host), so MeloTTS is the default. ---
COPY docker/setup-melo.sh /app/docker/setup-melo.sh
# Strip CR first: a Windows (autocrlf) checkout yields CRLF, which makes bash
# read `set -euxo pipefail\r` and abort. Idempotent on an LF tree.
RUN sed -i 's/\r$//' /app/docker/setup-melo.sh && bash /app/docker/setup-melo.sh
# --- Human input + window management for the on-screen Chrome control tool.
# xdotool injects real X pointer/keyboard events (visible cursor,