import base64 import httpx from app.providers.stt.base import STTProvider class OpenRouterSTTProvider(STTProvider): def __init__(self, api_key: str, model: str): self.api_key = (api_key or "").strip() self.model = (model or "").strip() async def transcribe(self, audio_bytes: bytes, fmt: str, language: str | None = None) -> str: if not self.api_key: raise ValueError("OPENROUTER_API_KEY is empty") if not self.model: raise ValueError("OPENROUTER_STT_MODEL is empty") if not audio_bytes: raise ValueError("STT input audio is empty") # OpenRouter /audio/transcriptions erwartet JSON mit base64-Audio # (NICHT multipart/form-data). Quelle: OpenRouter-Doku (STT). payload = { "model": self.model, "input_audio": { "data": base64.b64encode(audio_bytes).decode("utf-8"), "format": fmt, }, } if language: payload["language"] = language timeout = httpx.Timeout(connect=10.0, read=120.0, write=30.0, pool=10.0) async with httpx.AsyncClient(timeout=timeout) as client: try: response = await client.post( "https://openrouter.ai/api/v1/audio/transcriptions", headers={ "Authorization": f"Bearer {self.api_key}", "Content-Type": "application/json", }, json=payload, ) response.raise_for_status() except httpx.HTTPStatusError as exc: raise RuntimeError( f"OpenRouter STT error {exc.response.status_code}: {exc.response.text}" ) from exc except httpx.TimeoutException as exc: raise RuntimeError("OpenRouter STT timeout") from exc except httpx.HTTPError as exc: raise RuntimeError(f"OpenRouter STT transport error: {exc}") from exc data = response.json() return data.get("text", "") async def transcribe_detect( self, audio_bytes: bytes, fmt: str, language: str | None = None ) -> tuple[str, str | None]: if not self.api_key: raise ValueError("OPENROUTER_API_KEY is empty") if not self.model: raise ValueError("OPENROUTER_STT_MODEL is empty") if not audio_bytes: raise ValueError("STT input audio is empty") payload = { "model": self.model, "input_audio": { "data": base64.b64encode(audio_bytes).decode("utf-8"), "format": fmt, }, } if language: payload["language"] = language timeout = httpx.Timeout(connect=10.0, read=120.0, write=30.0, pool=10.0) async with httpx.AsyncClient(timeout=timeout) as client: try: response = await client.post( "https://openrouter.ai/api/v1/audio/transcriptions", headers={ "Authorization": f"Bearer {self.api_key}", "Content-Type": "application/json", }, json=payload, ) response.raise_for_status() except httpx.HTTPStatusError as exc: raise RuntimeError( f"OpenRouter STT error {exc.response.status_code}: {exc.response.text}" ) from exc except httpx.TimeoutException as exc: raise RuntimeError("OpenRouter STT timeout") from exc except httpx.HTTPError as exc: raise RuntimeError(f"OpenRouter STT transport error: {exc}") from exc data = response.json() return data.get("text", ""), data.get("language")