From 01b011235fcd269e703b18950187d81f70d91f67 Mon Sep 17 00:00:00 2001 From: Till-JS <101404291+Till-JS@users.noreply.github.com> Date: Sat, 14 Feb 2026 12:08:17 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=A9=B9=20fix(mana-tts):=20add=20Piper/Ger?= =?UTF-8?q?man=20voice=20support=20to=20/synthesize/auto=20endpoint?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The auto endpoint now properly routes German voices (de_thorsten, de_katja, etc.) to Piper TTS instead of falling back to English Kokoro voices. Co-Authored-By: Claude Opus 4.5 --- services/mana-tts/app/main.py | 40 +++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/services/mana-tts/app/main.py b/services/mana-tts/app/main.py index 4c393495f..f6ad6b961 100644 --- a/services/mana-tts/app/main.py +++ b/services/mana-tts/app/main.py @@ -37,6 +37,11 @@ from .f5_service import ( DEFAULT_F5_MODEL, ) from .voice_manager import get_voice_manager, CustomVoice +from .piper_service import ( + synthesize_piper, + PIPER_VOICES, + is_piper_loaded, +) # Configure logging logging.basicConfig( @@ -563,6 +568,41 @@ async def synthesize_auto( ) return await synthesize_with_kokoro(kokoro_request) + # Check if it's a Piper/German voice + if voice in PIPER_VOICES: + try: + # Convert speed to length_scale (inverse relationship) + # speed > 1 means faster, so length_scale < 1 + length_scale = 1.0 / request.speed + + result = await synthesize_piper( + text=request.text, + voice=voice, + length_scale=length_scale, + ) + + # Convert to requested format + output_format = request.output_format.lower() + audio_bytes, content_type = convert_audio( + result.audio, + result.sample_rate, + output_format, + ) + + return Response( + content=audio_bytes, + media_type=content_type, + headers={ + "X-Model": "piper", + "X-Voice": voice, + "X-Duration": str(result.duration), + "X-Sample-Rate": str(result.sample_rate), + }, + ) + except Exception as e: + logger.error(f"Piper synthesis error: {e}") + raise HTTPException(status_code=500, detail=f"German voice synthesis failed: {e}") + # Check if it's a registered custom voice voice_manager = get_voice_manager() if voice_manager.voice_exists(voice):