"""FluentGerman.ai — Voice service (API provider + browser fallback).""" import io import logging import openai from app.config import get_settings async def transcribe(audio_bytes: bytes, filename: str = "audio.webm") -> str: """Transcribe audio to text using OpenAI Whisper API.""" settings = get_settings() # Use dedicated OpenAI key if available, otherwise fallback to LLM key api_key = settings.openai_api_key or settings.llm_api_key key_type = "OPENAI_API_KEY" if settings.openai_api_key else "LLM_API_KEY" masked = f"{api_key[:4]}...{api_key[-4:]}" if api_key and len(api_key) > 8 else "EMPTY" logging.getLogger("fluentgerman.voice").info(f"Transcribing with {key_type}: {masked}") client = openai.AsyncOpenAI(api_key=api_key) audio_file = io.BytesIO(audio_bytes) audio_file.name = filename transcript = await client.audio.transcriptions.create( model=settings.stt_model, file=audio_file, prompt="FluentGerman.ai — German language tutor. Deutsch, Grammatik, Übung, Aussprache.", ) return transcript.text async def synthesize(text: str) -> bytes: """Synthesize text to speech using OpenAI TTS API.""" settings = get_settings() # Use dedicated OpenAI key if available, otherwise fallback to LLM key api_key = settings.openai_api_key or settings.llm_api_key key_type = "OPENAI_API_KEY" if settings.openai_api_key else "LLM_API_KEY" masked = f"{api_key[:4]}...{api_key[-4:]}" if api_key and len(api_key) > 8 else "EMPTY" logging.getLogger("fluentgerman.voice").info(f"Synthesizing with {key_type}: {masked}") client = openai.AsyncOpenAI(api_key=api_key) response = await client.audio.speech.create( model=settings.tts_model, voice=settings.tts_voice, input=text, response_format="mp3", ) return response.content