diff --git a/app/providers/tts/piper.py b/app/providers/tts/piper.py index f19cd04..75d2d59 100644 --- a/app/providers/tts/piper.py +++ b/app/providers/tts/piper.py @@ -21,6 +21,8 @@ from pathlib import Path from app.providers.tts.base import TTSProvider +_GENDER_CODES = {"f", "m", "any"} + try: # bevorzugter Pfad: in-process, Modell bleibt geladen from piper import PiperVoice # type: ignore @@ -120,11 +122,23 @@ class PiperTTSProvider(TTSProvider): text: str, voice: str | None = None, audio_format: str = "pcm", - language: str | None = None, # ignoriert: die Piper-Stimme kodiert die Sprache + language: str | None = None, ) -> bytes: if not text or not text.strip(): raise ValueError("TTS input text is empty") + # Gender-Code (z. B. "f"/"m" aus Cartesia-Fallback) → echter Piper-Stimmname + if voice in _GENDER_CODES and language: + from app.dependencies import PIPER_VOICE_GENDERED, LANG_TO_PIPER_VOICE + lang = language.lower() + candidates = [voice, "f" if voice == "m" else "m"] if voice in ("f", "m") else ["f", "m"] + resolved = next( + (PIPER_VOICE_GENDERED.get((lang, g)) for g in candidates if PIPER_VOICE_GENDERED.get((lang, g))), + LANG_TO_PIPER_VOICE.get(lang), + ) + if resolved: + voice = resolved + voice_name, speaker_id = self._parse_speaker(voice) model, config = self._model_paths(voice_name) pcm, native_rate = await asyncio.to_thread(