kurdish-tts / server.py
austek
Fix the piper speaker
e520cc0 unverified
Raw
History Blame Contribute Delete
1.79 kB
import asyncio
import io
import logging
import wave
from functools import partial
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import Response
from fastapi.staticfiles import StaticFiles
from piper import PiperVoice, SynthesisConfig
from pydantic import BaseModel, Field
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
MODEL_PATH = "models/ku/ku_TR/berfin_renas/medium/ku_TR-berfin_renas-medium.onnx"
CONFIG_PATH = "models/ku/ku_TR/berfin_renas/medium/ku_TR-berfin_renas-medium.onnx.json"
app = FastAPI(title="Kurdish TTS")
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_methods=["POST"],
allow_headers=["*"],
)
logger.info("Loading voice model...")
voice = PiperVoice.load(MODEL_PATH, config_path=CONFIG_PATH, use_cuda=False)
logger.info("Model ready")
class TTSRequest(BaseModel):
text: str = Field(..., min_length=1, max_length=500)
speaker_id: int = Field(default=0, ge=0, le=1)
def _synthesize(text: str, speaker_id: int) -> bytes:
buf = io.BytesIO()
with wave.open(buf, "wb") as wav:
voice.synthesize_wav(text, wav, syn_config=SynthesisConfig(speaker_id=speaker_id))
buf.seek(0)
return buf.read()
@app.post("/api/tts")
async def tts(req: TTSRequest):
text = req.text.strip()
if not text:
raise HTTPException(status_code=400, detail="Text cannot be empty")
loop = asyncio.get_event_loop()
wav_bytes = await loop.run_in_executor(None, partial(_synthesize, text, req.speaker_id))
return Response(content=wav_bytes, media_type="audio/wav")
@app.get("/health")
def health():
return {"status": "ok"}
app.mount("/", StaticFiles(directory="static", html=True), name="static")