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:
@@ -9,11 +9,12 @@ from fastapi.responses import FileResponse, HTMLResponse, JSONResponse
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from starlette.middleware.sessions import SessionMiddleware
|
||||
|
||||
from asr.config import ensure_runtime_dirs
|
||||
from asr.config import ensure_runtime_dirs as ensure_asr_dirs
|
||||
from asr.router import router as asr_router
|
||||
from asr.router import ws_router as asr_ws_router
|
||||
from core.auth import SESSION_SECRET_KEY, require_login
|
||||
from core.auth import router as auth_router
|
||||
from tts.config import ensure_runtime_dirs as ensure_tts_dirs
|
||||
from tts.router import router as tts_router
|
||||
|
||||
app = FastAPI(title="Speech Gateway", docs_url="/docs", redoc_url="/redoc")
|
||||
@@ -42,7 +43,8 @@ app.include_router(tts_router, prefix="/tts", tags=["tts"], dependencies=[Depend
|
||||
|
||||
@app.on_event("startup")
|
||||
def startup() -> None:
|
||||
ensure_runtime_dirs()
|
||||
ensure_asr_dirs()
|
||||
ensure_tts_dirs()
|
||||
if UI_DIR.exists():
|
||||
app.mount("/ui", StaticFiles(directory=str(UI_DIR), html=True), name="ui")
|
||||
app.mount("/assets", StaticFiles(directory=str(UI_DIR / "assets")), name="assets")
|
||||
|
||||
Reference in New Issue
Block a user