ibrahimgulbutt's picture
security: require a shared service key on /tts and /extract-resume
97e667f
Raw History Blame Contribute Delete
1.46 kB
from typing import Literal
from fastapi import APIRouter, Depends, HTTPException
from fastapi.responses import Response
from pydantic import BaseModel, Field
from services.auth import require_service_key
from services.tts_service import synthesize, is_available, backend_status
router = APIRouter(prefix="/tts", tags=["tts"])
class TtsRequest(BaseModel):
text: str = Field(..., min_length=1, max_length=1200)
voice: str | None = None
# "ogg" = Ogg/Opus (~10x smaller than WAV; not playable in Safari, so the
# client negotiates via canPlayType and asks for "wav" when needed).
format: Literal["wav", "ogg"] = "wav"
@router.get("/health")
def tts_health():
"""Reports whether Kokoro TTS is installed/usable and which backend runs it."""
return {"available": is_available(), "backend": backend_status()}
@router.post("", dependencies=[Depends(require_service_key)])
def tts(req: TtsRequest):
"""
Synthesize interviewer speech with Kokoro. Returns audio (WAV or Ogg/Opus)
on success, or 503 when TTS is unavailable so the caller falls back to
browser speech. Responses are LRU-cached per (text, voice, format).
"""
try:
audio, mime = synthesize(req.text, req.voice, req.format)
return Response(content=audio, media_type=mime)
except Exception as e: # noqa: BLE001 — TTS is optional; never hard-fail
raise HTTPException(status_code=503, detail=f"TTS unavailable: {e}")