my_voice_assistant_v2/app/api/speak.py

60 lines
1.7 KiB
Python
Raw Normal View History

from io import BytesIO
from fastapi import APIRouter, HTTPException, Query
from fastapi.responses import StreamingResponse
from app.config import settings
from app.errors import RoutingError
from app.dependencies import (
resolve_route,
build_orchestrator,
resolve_output_endpoint,
)
from app.schemas import SpeakRequest
router = APIRouter()
@router.post("/speak")
async def speak(
payload: SpeakRequest,
session_id: str | None = Query(
default=None,
description="Optional session id to apply a stored route",
),
):
overrides = {
"output_endpoint": payload.output_endpoint,
"language": payload.language,
"tts_provider": payload.tts_provider,
}
route = resolve_route(session_id, overrides)
voice = payload.voice or settings.openrouter_tts_voice
try:
orchestrator = build_orchestrator(route)
output = await resolve_output_endpoint(route)
except RoutingError as exc:
raise HTTPException(status_code=422, detail=str(exc))
try:
audio = await orchestrator.speak_only(
payload.text,
voice=voice,
language=route.language,
output=output,
)
headers = {
"Content-Language": route.language,
"X-Audio-Format": "pcm",
"X-Audio-Sample-Rate": "24000",
"X-Audio-Channels": "1",
"X-Audio-Sample-Width": "16",
"X-Output-Endpoint": route.output_endpoint,
"X-TTS-Provider": route.tts_provider,
}
return StreamingResponse(BytesIO(audio), media_type="audio/pcm", headers=headers)
except Exception as exc:
raise HTTPException(status_code=502, detail=str(exc))