55 lines
1.5 KiB
Python
55 lines
1.5 KiB
Python
"""Whisper transcription service for VoIdeaAI.
|
|
|
|
Used as fallback when browser Web Speech API fails.
|
|
Supports OpenAI Whisper API and compatible endpoints.
|
|
"""
|
|
|
|
import tempfile
|
|
from pathlib import Path
|
|
|
|
import httpx
|
|
|
|
from app.core.config import get_settings
|
|
|
|
WHISPER_URL = "https://api.openai.com/v1/audio/transcriptions"
|
|
|
|
|
|
async def transcribe(audio_data: bytes, filename: str = "audio.webm") -> str | None:
|
|
"""Transcribe audio using Whisper API.
|
|
|
|
Args:
|
|
audio_data: Raw audio bytes
|
|
filename: Original filename (determines format)
|
|
|
|
Returns:
|
|
Transcribed text or None if failed
|
|
"""
|
|
settings = get_settings()
|
|
|
|
api_key = settings.openai_api_key or settings.ai_yandex_key or ""
|
|
if not api_key:
|
|
return None
|
|
|
|
url = WHISPER_URL
|
|
|
|
with tempfile.NamedTemporaryFile(delete=False, suffix=Path(filename).suffix) as tmp:
|
|
tmp.write(audio_data)
|
|
tmp_path = tmp.name
|
|
|
|
try:
|
|
async with httpx.AsyncClient(timeout=30.0) as client:
|
|
with open(tmp_path, "rb") as f:
|
|
resp = await client.post(
|
|
url,
|
|
headers={"Authorization": f"Bearer {api_key}"},
|
|
files={"file": (filename, f, "audio/webm")},
|
|
data={"model": "whisper-1", "language": "ru"},
|
|
)
|
|
if resp.status_code == 200:
|
|
return resp.json().get("text")
|
|
return None
|
|
except Exception:
|
|
return None
|
|
finally:
|
|
Path(tmp_path).unlink(missing_ok=True)
|