TTS: Kokoro → XTTS-v2 (CPU-only, Claribel Dervla)

- Neues xtts_worker.py: Coqui XTTS-v2, HTTP-API auf Port 8085
- Router: TTS_WORKER_URL → 8085, TTS_MODEL → xtts-v2, TTS_VOICES → claribel
- deploy: mike-ai-xtts.service, install.sh + deploy.sh aktualisiert
- Tests: 54/54 bestanden (mock_tts_worker + test_local.sh auf XTTS umgestellt)
- README: TTS-Section auf XTTS-v2 aktualisiert
- Kokoro-Service gestoppt und deaktiviert (Dateien bleiben als Backup)
This commit is contained in:
Mikei386
2026-08-19 22:01:58 +02:00
parent ed471196d4
commit d399d2b4f7
9 changed files with 451 additions and 171 deletions
+2 -2
View File
@@ -9,10 +9,10 @@ SSH_KEY="${SSH_KEY:-$HOME/.ssh/lmstudio_unraid}"
STAGE="/tmp/ai-profile-router-$$"
mkdir -p "$STAGE"
cp router/ai_profile_router.py router/image_worker.py router/tts_worker.py \
cp router/ai_profile_router.py router/image_worker.py router/xtts_worker.py \
router/stt_worker.py \
deploy/install.sh deploy/mike-ai-profile-router.service \
deploy/mike-ai-kokoro.service deploy/mike-ai-whisper.service "$STAGE/"
deploy/mike-ai-xtts.service deploy/mike-ai-whisper.service "$STAGE/"
echo "== Übertrage Dateien nach ${TARGET}:/tmp/ai-profile-router/"
ssh -i "$SSH_KEY" "$TARGET" 'mkdir -p /tmp/ai-profile-router'
+56 -64
View File
@@ -1,15 +1,15 @@
#!/bin/bash
# AI Profile Router – Installation/Update auf dem Zielsystem.
# Wird als root auf dem Zielsystem ausgeführt (per SSH, vgl. deploy.sh).
# Erwartet ai_profile_router.py, image_worker.py, tts_worker.py,
# mike-ai-profile-router.service und mike-ai-kokoro.service im selben
# Erwartet ai_profile_router.py, image_worker.py, xtts_worker.py,
# mike-ai-profile-router.service und mike-ai-xtts.service im selben
# Verzeichnis wie dieses Skript.
set -euo pipefail
DIR="$(cd "$(dirname "$0")" && pwd)"
INSTALL_DIR=/opt/mike-ai/ai-profile-router
SERVICE=mike-ai-profile-router.service
KOKORO_SERVICE=mike-ai-kokoro.service
XTTS_SERVICE=mike-ai-xtts.service
WHISPER_SERVICE=mike-ai-whisper.service
OLD_SERVICE=mike-ai-local-llm-router.service
OLD_DIR=/opt/mike-ai/local-llm-router
@@ -17,8 +17,8 @@ BACKUP_DIR=/opt/mike-ai/.backup-ai-profile-router-$(date +%Y%m%d-%H%M%S)
VENV="$INSTALL_DIR/venv"
MODEL_DIR=/opt/mike-ai/models/FLUX.2-klein-base-4B
IMAGE_DIR="$INSTALL_DIR/images"
KOKORO_VENV=/opt/mike-ai/kokoro/venv
KOKORO_MODEL_DIR=/opt/mike-ai/models/kokoro
XTTS_VENV=/opt/mike-ai/xtts/venv
XTTS_CACHE=/opt/mike-ai/xtts/.cache
echo "== AI Profile Router: Installation/Update =="
@@ -40,10 +40,10 @@ fi
mkdir -p "$INSTALL_DIR" "$IMAGE_DIR"
install -m 0755 "$DIR/ai_profile_router.py" "$INSTALL_DIR/ai_profile_router.py"
install -m 0755 "$DIR/image_worker.py" "$INSTALL_DIR/image_worker.py"
install -m 0755 "$DIR/tts_worker.py" "$INSTALL_DIR/tts_worker.py"
install -m 0755 "$DIR/xtts_worker.py" "$INSTALL_DIR/xtts_worker.py"
install -m 0755 "$DIR/stt_worker.py" "$INSTALL_DIR/stt_worker.py"
install -m 0644 "$DIR/${SERVICE}" "/etc/systemd/system/${SERVICE}"
install -m 0644 "$DIR/${KOKORO_SERVICE}" "/etc/systemd/system/${KOKORO_SERVICE}"
install -m 0644 "$DIR/${XTTS_SERVICE}" "/etc/systemd/system/${XTTS_SERVICE}"
install -m 0644 "$DIR/${WHISPER_SERVICE}" "/etc/systemd/system/${WHISPER_SERVICE}"
# --- 3. Python-Venv mit Bild-Abhängigkeiten ---------------------------------
@@ -76,69 +76,61 @@ print("Modell-Download abgeschlossen")
PY
fi
# --- 5. TTS (Kokoro) ----------------------------------------------------------
# espeak-ng wird für die deutsche G2P (phonemizer) benötigt.
if ! command -v espeak-ng >/dev/null 2>&1; then
echo "-- Installiere espeak-ng"
apt-get install -y espeak-ng
fi
# Kokoro-Venv (CPU-only torch + semidark/kokoro + semidark/misaki + soundfile + lameenc)
if [ ! -x "$KOKORO_VENV/bin/python" ]; then
echo "-- Erstelle Kokoro-Venv in $KOKORO_VENV"
mkdir -p "$KOKORO_VENV"
python3 -m venv "$KOKORO_VENV"
"$KOKORO_VENV/bin/pip" install --quiet --upgrade pip
# --- 5. TTS (XTTS-v2) ----------------------------------------------------------
# XTTS-Venv (Python 3.11 via uv + CPU-only torch + Coqui TTS)
if [ ! -x "$XTTS_VENV/bin/python" ]; then
echo "-- Erstelle XTTS-Venv in $XTTS_VENV (Python 3.11 via uv)"
mkdir -p "$XTTS_VENV"
# uv installieren (falls noch nicht vorhanden)
if ! command -v uv >/dev/null 2>&1; then
curl -LsSf https://astral.sh/uv/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
fi
uv venv --python 3.11 "$XTTS_VENV"
"$XTTS_VENV/bin/pip" install --quiet --upgrade pip
echo "-- Installiere CPU-only torch"
"$KOKORO_VENV/bin/pip" install --quiet torch \
"$XTTS_VENV/bin/pip" install --quiet torch torchaudio \
--index-url https://download.pytorch.org/whl/cpu
echo "-- Installiere Kokoro-Abhängigkeiten"
"$KOKORO_VENV/bin/pip" install --quiet \
huggingface-hub loguru transformers regex num2words \
soundfile lameenc
# Offizieller Kikiri-Deutsche-Pfad:
# - semidark/misaki-Fork (0.9.4) mit [de]-Extra (phonemizer-fork + espeakng-loader)
# - semidark/kokoro-Fork (0.9.4) mit --no-deps (vermeidet misaki[en] → spacy-curated-transformers)
# - spacy + num2words für misaki.en-Import (Englisch, nicht für deutschen Pfad)
"$KOKORO_VENV/bin/pip" install --quiet "spacy<4"
"$KOKORO_VENV/bin/pip" install --quiet \
"misaki[de] @ git+https://github.com/semidark/misaki.git"
"$KOKORO_VENV/bin/pip" install --quiet \
"kokoro @ git+https://github.com/semidark/kokoro.git" --no-deps
echo "-- Installiere Coqui TTS + Abhängigkeiten"
"$XTTS_VENV/bin/pip" install --quiet \
TTS==0.22.0 transformers==4.40.2 tokenizers==0.19.1 \
huggingface-hub==0.36.2 librosa soundfile
# PyTorch 2.6+ weights_only-Patch für Coqui TTS
echo "-- Wende weights_only-Patch für Coqui TTS an"
"$XTTS_VENV/bin/python" - <<'PY'
import os
patch_file = os.path.expanduser("/opt/mike-ai/xtts/venv/lib/python3.11/site-packages/TTS/utils/io.py")
with open(patch_file, 'r') as f:
content = f.read()
if 'weights_only=False' not in content:
content = content.replace(
'return torch.load(f, map_location=map_location, **kwargs)',
'return torch.load(f, map_location=map_location, weights_only=False, **kwargs)'
)
with open(patch_file, 'w') as f:
f.write(content)
print("Patch angewendet")
else:
print("Patch bereits vorhanden")
PY
fi
# Kokoro-Modelle (kikiri-german-martin + kikiri-german-victoria, Apache 2.0)
if [ ! -f "$KOKORO_MODEL_DIR/kikiri-german-martin/kikiri_german_martin_ep10.pth" ] \
|| [ ! -f "$KOKORO_MODEL_DIR/kikiri-german-victoria/kikiri_german_victoria_ep10.pth" ]; then
echo "-- Lade Kokoro-Modelle nach $KOKORO_MODEL_DIR (kann dauern)"
"$KOKORO_VENV/bin/python" - <<'PY'
# XTTS-v2-Modell (nur wenn noch nicht vorhanden)
if [ ! -d "$XTTS_CACHE/hub/models--coqui--tts_models--multilingual--multi-dataset--xtts_v2" ]; then
echo "-- Lade XTTS-v2-Modell (kann dauern, ~1.9 GB)"
"$XTTS_VENV/bin/python" - <<'PY'
import os
from huggingface_hub import hf_hub_download
base = "/opt/mike-ai/models/kokoro"
files = [
("kikiri-tts/kikiri-german-martin", "kikiri_german_martin_ep10.pth", "kikiri-german-martin"),
("kikiri-tts/kikiri-german-martin", "voices/martin.pt", "kikiri-german-martin"),
("kikiri-tts/kikiri-german-victoria", "kikiri_german_victoria_ep10.pth", "kikiri-german-victoria"),
("kikiri-tts/kikiri-german-victoria", "voices/victoria.pt", "kikiri-german-victoria"),
("hexgrad/Kokoro-82M", "config.json", "kikiri-german-martin"),
("hexgrad/Kokoro-82M", "config.json", "kikiri-german-victoria"),
]
for repo, fname, subdir in files:
dest = os.path.join(base, subdir, fname)
if os.path.exists(dest) and os.path.getsize(dest) > 1000:
print(f"vorhanden: {subdir}/{fname}")
continue
os.makedirs(os.path.dirname(dest), exist_ok=True)
hf_hub_download(repo_id=repo, filename=fname, local_dir=os.path.join(base, subdir))
print(f"geladen: {subdir}/{fname}")
os.environ["HF_HOME"] = "/opt/mike-ai/xtts/.cache"
from TTS.api import TTS
tts = TTS("tts_models/multilingual/multi-dataset/xtts_v2")
print("Modell geladen")
PY
fi
# --- 6. Services aktivieren und starten ---------------------------------------
systemctl daemon-reload
systemctl enable "$SERVICE" "$KOKORO_SERVICE" "$WHISPER_SERVICE"
systemctl restart "$KOKORO_SERVICE"
systemctl enable "$SERVICE" "$XTTS_SERVICE" "$WHISPER_SERVICE"
systemctl restart "$XTTS_SERVICE"
systemctl restart "$WHISPER_SERVICE"
systemctl restart "$SERVICE"
@@ -150,12 +142,12 @@ if ! systemctl is-active --quiet "$SERVICE"; then
exit 1
fi
echo "-- Router-Service läuft"
if ! systemctl is-active --quiet "$KOKORO_SERVICE"; then
echo "-- FEHLER: Kokoro-Service läuft nicht" >&2
journalctl -u "$KOKORO_SERVICE" -n 20 --no-pager >&2
if ! systemctl is-active --quiet "$XTTS_SERVICE"; then
echo "-- FEHLER: XTTS-Service läuft nicht" >&2
journalctl -u "$XTTS_SERVICE" -n 20 --no-pager >&2
exit 1
fi
echo "-- Kokoro-Service läuft"
echo "-- XTTS-Service läuft"
if ! systemctl is-active --quiet "$WHISPER_SERVICE"; then
echo "-- FEHLER: Whisper-Service läuft nicht" >&2
journalctl -u "$WHISPER_SERVICE" -n 20 --no-pager >&2
+18
View File
@@ -0,0 +1,18 @@
[Unit]
Description=XTTS-v2 TTS Worker (CPU-only)
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=/opt/mike-ai/xtts
ExecStart=/opt/mike-ai/xtts/venv/bin/python /opt/mike-ai/ai-profile-router/xtts_worker.py
Restart=on-failure
RestartSec=5
Environment=PATH=/opt/mike-ai/xtts/venv/bin:/usr/local/bin:/usr/bin:/bin
Environment=HOME=/root
# CPU-only, keine GPU
Environment=CUDA_VISIBLE_DEVICES=
[Install]
WantedBy=multi-user.target