CPU MeloTTS serialised under concurrent load (whisper STT + bot) and blew voice-reply TTS to 7-8s. Install the Blackwell-verified cu128 torch in the melo venv, select the GPU via MELO_DEVICE=cuda, and do a throwaway synth at worker startup so the one-off CUDA kernel-init (~5s) doesn't land on the user's first reply. Measured: ~0.3s/sentence on GPU vs ~1.2-2.6s on CPU. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
81 lines
4.0 KiB
Bash
Executable File
81 lines
4.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# ============================================================================
|
|
# Install a dedicated MeloTTS (Korean voice) venv at /opt/melo.
|
|
#
|
|
# Why a SEPARATE venv (not the brain-bridge /opt/venv):
|
|
# - MeloTTS pins old deps (transformers 4.27.4 / tokenizers 0.13.3 / fugashi)
|
|
# whose binary wheels exist only for cp311, so we use python3.11 here even
|
|
# though the image's default interpreter is 3.12.
|
|
# - It isolates the heavy torch/transformers stack from the slim bridge env,
|
|
# which pins numpy<2 for faster-whisper.
|
|
#
|
|
# torch is the CUDA (cu128) build so MeloTTS runs on the GPU alongside Ollama +
|
|
# Whisper. CPU synth serialised under concurrent load (whisper STT + bot) and
|
|
# blew TTS up to 7-8s per reply; on the GPU a sentence synthesises in ~0.3s.
|
|
# cu128 is the Blackwell (sm_120) wheel verified on this host's RTX 5050.
|
|
# The worker selects the device via MELO_DEVICE=cuda (compose).
|
|
# ============================================================================
|
|
set -euxo pipefail
|
|
|
|
export DEBIAN_FRONTEND=noninteractive
|
|
|
|
apt-get update
|
|
# Build deps for fugashi / mecab-python3 + a system MeCab dict, plus python3.11.
|
|
apt-get install -y --no-install-recommends \
|
|
software-properties-common build-essential pkg-config swig \
|
|
libmecab-dev mecab mecab-ipadic-utf8
|
|
add-apt-repository -y ppa:deadsnakes/ppa
|
|
apt-get update
|
|
apt-get install -y --no-install-recommends python3.11 python3.11-venv python3.11-dev
|
|
rm -rf /var/lib/apt/lists/*
|
|
|
|
python3.11 -m venv /opt/melo
|
|
/opt/melo/bin/pip install --no-cache-dir --upgrade pip wheel setuptools
|
|
|
|
# CUDA (cu128) torch first, so MeloTTS's unpinned `torch` dep is already
|
|
# satisfied with the GPU build. Pinned to the Blackwell-verified versions
|
|
# (2.11.0+cu128) for reproducible rebuilds.
|
|
/opt/melo/bin/pip install --no-cache-dir torch==2.11.0+cu128 torchaudio==2.11.0+cu128 \
|
|
--index-url https://download.pytorch.org/whl/cu128
|
|
|
|
# MeloTTS from GitHub. The PyPI sdist is broken (its setup.py reads a
|
|
# requirements.txt that is not shipped in the sdist), so install from the repo.
|
|
# Pinned to a commit (not refs/heads/main) so rebuilds are reproducible.
|
|
/opt/melo/bin/pip install --no-cache-dir \
|
|
"https://github.com/myshell-ai/MeloTTS/archive/209145371cff8fc3bd60d7be902ea69cbdb7965a.tar.gz"
|
|
|
|
# Korean g2p backend. MeloTTS otherwise tries to pip-install this on the first
|
|
# Korean request, which fails in a network-isolated container at runtime.
|
|
/opt/melo/bin/pip install --no-cache-dir python-mecab-ko python-mecab-ko-dic
|
|
|
|
# Remove the full `unidic` package (its dictionary is never downloaded, only a
|
|
# stub) so mecab-python3 falls back to the bundled `unidic_lite` dict. Without
|
|
# this, importing melo's Japanese module fails with a missing-mecabrc error.
|
|
/opt/melo/bin/pip uninstall -y unidic || true
|
|
|
|
# Pre-cache every model asset MeloTTS pulls at runtime, so the worker starts
|
|
# offline and the first Discord turn pays no download cost. Importing melo.api
|
|
# fetches the Japanese (tohoku-nlp/bert-base-japanese-v3) and Korean
|
|
# (kykim/bert-kor-base) BERT tokenizers plus nltk g2p data; loading the KR voice
|
|
# downloads the OpenVoice KR config+checkpoint, and a real synth pulls the
|
|
# Korean BERT weights. All of these go through huggingface_hub.
|
|
#
|
|
# CRITICAL: at runtime docker-compose mounts the `whisper_cache` named volume
|
|
# over /root/.cache/huggingface (for faster-whisper). That volume would SHADOW
|
|
# anything baked into the default HF cache, so we pin the melo worker to a
|
|
# DEDICATED, non-volume cache dir (/opt/melo-cache) here AND in supervisord, and
|
|
# warm it once. nltk_data (/root/nltk_data) is not volume-mounted so it stays.
|
|
export HF_HOME=/opt/melo-cache
|
|
mkdir -p "$HF_HOME"
|
|
MELO_LANGUAGE=KR HF_HOME=/opt/melo-cache /opt/melo/bin/python - <<'PY'
|
|
import tempfile
|
|
from melo.api import TTS
|
|
|
|
model = TTS(language="KR", device="cpu")
|
|
out = tempfile.mktemp(suffix=".wav")
|
|
model.tts_to_file("초기화 워밍업입니다.", model.hps.data.spk2id["KR"], out, speed=1.5)
|
|
print("[setup-melo] warm-up KR synth OK ->", out)
|
|
PY
|
|
|
|
echo "[setup-melo] MeloTTS venv ready at /opt/melo"
|