live-wizard/services/tts/server.py
Timmy e1995bab11
Some checks failed
ci / lint (push) Has been cancelled
tts: male VCTK fallback until voice-sample.wav lands
2026-07-08 19:41:02 +00:00

42 lines
1.3 KiB
Python

"""TTS wrapper: clone mode if reference audio is present, else fallback to VCTK male."""
from pathlib import Path
from flask import Flask, request, send_file, jsonify
import os, uuid
app = Flask(__name__)
OUT_DIR = Path("/tmp/tts-out")
OUT_DIR.mkdir(parents=True, exist_ok=True)
REF = Path(os.getenv("REFERENCE_AUDIO", "/app/reference/voice-sample.wav"))
from TTS.api import TTS
tts = TTS(model_name="tts_models/en/vctk/vits", progress_bar=False, gpu=False)
def synth_to_file(text: str, out: Path):
if REF.exists():
tts.tts_to_file(text=text, speaker_wav=str(REF), file_path=str(out))
else:
# male VCTK fallback speaker
tts.tts_to_file(text=text, speaker="p267", file_path=str(out))
@app.get("/health")
def health():
return {
"status": "ok",
"mode": "clone" if REF.exists() else "fallback-male",
"reference": str(REF),
"model": "tts_models/en/vctk/vits",
}
@app.post("/synthesize")
def synthesize():
data = request.get_json(force=True)
text = data.get("text", "")
if not text:
return jsonify({"error": "text required"}), 400
out = OUT_DIR / f"{uuid.uuid4().hex}.wav"
synth_to_file(text, out)
return send_file(str(out), mimetype="audio/wav")
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5002)