Add XTTS-v2 as first TTS backend, extensible for more

Mirrors the ASR backend pattern exactly: a BACKENDS dict in
tts/router.py maps a backend name to its worker URL, so adding the
next backend is just a new worker file + venv + supervisord entry +
one dict line. XTTS-v2 runs in its own venv (--system-site-packages,
inherits base image torch/CUDA) as a new supervisord program on
port 8005.

XTTS is zero-shot voice cloning, so a reference-voice library was
added (/tts/voices CRUD, stored under /srv/tts/voices) — synthesis
requires picking a previously uploaded voice. Results and model
cache live under /srv/tts/{results,models-cache}, new quadlet
volumes, owned by the same 983:983 user as the existing /srv/asr
dirs.

Fixed two environment issues uncovered while getting XTTS to
actually run inside the container (non-root user, root-built venvs):
- coqui-tts only pins transformers>=4.57 with no ceiling, so pip
  installed an incompatible 5.x; pinned to the last 4.x release.
- HOME defaults to /app (owned by root) for the container's runtime
  user, so numba/matplotlib/torch cache writes failed; HOME is now
  forced to /tmp in all three workers (faster_whisper, qwen3, xtts)
  before any of those libraries get imported.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
du5t
2026-06-18 18:46:45 +09:00
parent ac49bfc7f9
commit acdf098c41
13 changed files with 761 additions and 24 deletions

View File

@@ -296,6 +296,20 @@ pre {
background: #0f1530;
}
/* Voice list (TTS) */
.voice-row {
display: flex;
align-items: center;
gap: 12px;
padding: 10px 14px;
margin-bottom: 8px;
background: #0f1530;
border: 1px solid #3a446d;
border-radius: 10px;
}
.voice-row .voice-name { font-weight: 600; flex-shrink: 0; min-width: 120px; }
.voice-row audio { flex: 1; height: 32px; }
@media (max-width: 720px) {
.grid2, .grid3 { grid-template-columns: 1fr; }
.mic-row { flex-direction: column; }