File size: 2,291 Bytes
ecb9f70
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
"""Standalone STT and TTS utility endpoints."""

from __future__ import annotations

import asyncio
import base64

from fastapi import APIRouter, Depends, File, HTTPException, UploadFile

from src.api.concurrency import STT_TIMEOUT_SEC, TTS_TIMEOUT_SEC, run_blocking
from src.api.deps import get_sarvam_key
from src.api.limits import MAX_AUDIO_BYTES, MIN_AUDIO_BYTES, enforce_max_bytes
from src.api.models import STTResponse, TTSRequest, TTSResponse

router = APIRouter(prefix="/api/audio", tags=["audio"])


@router.post("/stt", response_model=STTResponse)
async def speech_to_text(
    file: UploadFile = File(...),
    sarvam_key: str = Depends(get_sarvam_key),
):
    """Upload a WAV file and get the transcription back."""
    if not sarvam_key:
        raise HTTPException(500, "SARVAM_API_KEY not configured")

    audio_bytes = await file.read()
    enforce_max_bytes(audio_bytes, MAX_AUDIO_BYTES, "Audio")
    if not audio_bytes or len(audio_bytes) < MIN_AUDIO_BYTES:
        raise HTTPException(400, "Audio file too small or empty")

    from src.services.stt import transcribe_audio

    transcript = await run_blocking(
        transcribe_audio,
        audio_bytes, api_key=sarvam_key, model="saaras:v3", language_code="en-IN",
        timeout=STT_TIMEOUT_SEC, label="Transcription",
    )
    transcript = (transcript or "").strip()
    if not transcript:
        raise HTTPException(422, "Could not transcribe audio")

    return STTResponse(transcript=transcript)


@router.post("/tts", response_model=TTSResponse)
async def text_to_speech(
    body: TTSRequest,
    sarvam_key: str = Depends(get_sarvam_key),
):
    """Convert text to speech, return base64-encoded audio."""
    if not sarvam_key:
        raise HTTPException(500, "SARVAM_API_KEY not configured")

    if not body.text.strip():
        raise HTTPException(400, "Text cannot be empty")

    from src.services.tts import text_to_speech_bytes

    audio_bytes = await run_blocking(
        text_to_speech_bytes,
        body.text,
        api_key=sarvam_key,
        target_language_code=body.target_language_code,
        speaker=body.speaker,
        timeout=TTS_TIMEOUT_SEC, label="Speech synthesis",
    )
    audio_b64 = base64.b64encode(audio_bytes).decode()

    return TTSResponse(audio_b64=audio_b64)