stacks/index-tts: own FastAPI wrapper for IndexTTS-2 + deploy playbook
Adds a third TTS to the irv-ml1 fleet. IndexTTS-2 is Bilibili's
emotion-controllable zero-shot TTS (paper 2506.21619). Distinguishing
capability vs the existing two: timbre and emotion are disentangled —
clone a voice's timbre from one reference and the emotion from a
different reference, OR set emotion via 8-vector, OR derive it from a
text description. Neither CosyVoice 3 nor Qwen3-TTS-1.7B-Base does
this cleanly in English.
Wrapper is owned end-to-end (~150 lines in app.py) — the only existing
FastAPI fork (csllpr/index-tts-fastapi) targets v1 and is a dormant
single-commit repo. Upstream IndexTTS-2 ships only a Gradio webui.
Layout follows the qwen3-tts pattern:
stacks/index-tts/
Dockerfile — CUDA 12.8 base, IndexTTS pinned to a SHA
app.py — FastAPI: POST /v1/audio/speech + /v1/voices
entrypoint.sh — one-time HF snapshot_download of the weights
compose.yaml — env-driven, GPU pinning support, bind mounts
.env.example — port 8192, fp16, paths
README.md — API examples + comparison vs the other TTS
playbooks/deploy-index-tts.yaml — elway playbook for irv-ml1
Voice and emotion libraries are flat host dirs of WAVs, bind-mounted.
Drop a new <name>.wav and /v1/voices picks it up immediately.
License caveat: IndexTTS-2 weights ship under a custom Bilibili
license (free at our scale, not OSI-open). README documents it.
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
# syntax=docker/dockerfile:1.6
|
||||
#
|
||||
# IndexTTS-2 served behind our own thin FastAPI wrapper (~150 lines in
|
||||
# app.py). Upstream ships only a Gradio webui; the existing csllpr
|
||||
# FastAPI fork is for v1 and dormant. We own the wrapper end-to-end.
|
||||
|
||||
ARG CUDA_BASE=nvidia/cuda:12.8.0-cudnn-runtime-ubuntu22.04
|
||||
FROM ${CUDA_BASE}
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive \
|
||||
PIP_ROOT_USER_ACTION=ignore \
|
||||
PYTHONUNBUFFERED=1 \
|
||||
PATH="/opt/venv/bin:${PATH}"
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
python3.10 python3.10-venv python3-pip \
|
||||
git ffmpeg libsndfile1 \
|
||||
ca-certificates wget \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& python3.10 -m venv /opt/venv
|
||||
|
||||
# Pinned IndexTTS-2 SHA — bump in stack .env (INDEX_TTS_SHA build arg)
|
||||
# when you want upstream updates.
|
||||
ARG INDEX_TTS_SHA=830f6f8f94a51fea23ab1d639027a86200075a4e
|
||||
RUN git clone https://github.com/index-tts/index-tts.git /opt/index-tts \
|
||||
&& cd /opt/index-tts && git checkout ${INDEX_TTS_SHA}
|
||||
|
||||
# CUDA 12.8 torch wheels (per IndexTTS pyproject.toml's tool.uv.index
|
||||
# pin — same versions, same source).
|
||||
RUN pip install --no-cache-dir \
|
||||
torch==2.8.0 torchaudio==2.8.0 \
|
||||
--index-url https://download.pytorch.org/whl/cu128
|
||||
|
||||
# IndexTTS package + its long pinned-deps tail (numpy 1.26.2, transformers
|
||||
# 4.52.1, sentencepiece, librosa, descript-audiotools, jieba/g2p-en/cn2an,
|
||||
# WeTextProcessing, modelscope, accelerate, safetensors, etc.).
|
||||
# BigVGAN is vendored under indextts/ so it resolves without a pip dep.
|
||||
RUN cd /opt/index-tts && pip install --no-cache-dir -e .
|
||||
|
||||
# Wrapper deps (FastAPI stack + soundfile for in-memory WAV encoding).
|
||||
RUN pip install --no-cache-dir \
|
||||
fastapi 'uvicorn[standard]' python-multipart soundfile
|
||||
|
||||
WORKDIR /app
|
||||
COPY app.py /app/app.py
|
||||
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
|
||||
RUN chmod +x /usr/local/bin/entrypoint.sh
|
||||
|
||||
EXPOSE 8000
|
||||
|
||||
# wget is in the base image (added above); curl is not.
|
||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=600s --retries=3 \
|
||||
CMD wget -q -O /dev/null http://127.0.0.1:8000/healthz || exit 1
|
||||
|
||||
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
|
||||
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000"]
|
||||
Reference in New Issue
Block a user