speakeo-TTS / app.py
AthanasiusRG's picture
Update app.py
367741c verified
Raw
History Blame Contribute Delete
1.64 kB
import io
from fastapi import FastAPI, HTTPException, Query
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import StreamingResponse
from kokoro_onnx import Kokoro
import soundfile as sf
MODEL_PATH = "kokoro-v1.0.onnx"
VOICES_PATH = "voices-v1.0.bin"
VOICES = {
"en": ["af_heart", "am_puck"],
"fr": ["ff_siwis"],
}
LANG_CODES = {"en": "en-us", "fr": "fr-fr"}
app = FastAPI(title="Speakeo TTS", description="API Kokoro TTS (EN/FR)")
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # à restreindre au domaine de Speakeo plus tard
allow_methods=["*"],
allow_headers=["*"],
)
_kokoro: Kokoro | None = None
def get_kokoro() -> Kokoro:
global _kokoro
if _kokoro is None:
_kokoro = Kokoro(MODEL_PATH, VOICES_PATH)
return _kokoro
@app.get("/")
def root():
return {"status": "ok", "service": "speakeo-tts", "languages": list(VOICES)}
@app.get("/voices")
def voices():
return VOICES
@app.get("/tts")
def tts(
text: str = Query(..., min_length=1, max_length=2000),
lang: str = Query("en", pattern="^(en|fr)$"),
voice: str | None = None,
speed: float = Query(1.0, ge=0.5, le=2.0),
):
if voice is None:
voice = VOICES[lang][0]
elif voice not in VOICES[lang]:
raise HTTPException(400, f"Voix invalide pour '{lang}'. Options : {VOICES[lang]}")
samples, sample_rate = get_kokoro().create(
text, voice=voice, speed=speed, lang=LANG_CODES[lang]
)
buf = io.BytesIO()
sf.write(buf, samples, sample_rate, format="WAV")
buf.seek(0)
return StreamingResponse(buf, media_type="audio/wav")