From 7999dd6b596ee1d831e74067e7f671f05f83eddf Mon Sep 17 00:00:00 2001 From: MarvinFS Date: Tue, 2 Jun 2026 13:20:02 +0300 Subject: [PATCH] fix(tts): honor wav/flac output in OpenAI TTS provider instead of forcing mp3 _generate_openai_tts derived the OpenAI response_format solely from a .ogg check, mapping every other extension - including .wav and .flac - to mp3. This ignored the configured output_format, which Hermes already validates against COMMAND_TTS_OUTPUT_FORMATS = {mp3, wav, ogg, flac} and uses to set the output file extension. Impact: - Configured wav/flac output was re-encoded to mp3 (or written as mp3 bytes under a .wav name) even when the backend produced the requested format natively. - On OpenAI-compatible backends without server-side mp3 encoding - e.g. devnen/Chatterbox-TTS-Server, which returns native 24 kHz WAV - the forced mp3 request failed with "500: Failed to encode audio", breaking TTS entirely when wav would have worked. Mirror the sibling Mistral provider and map .wav -> wav and .flac -> flac. Both are documented OpenAI audio.speech response_format values, so this stays within the API contract and adds no new config surface. --- tools/tts_tool.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tools/tts_tool.py b/tools/tts_tool.py index cab2cc584ab0a..e128f210923bc 100644 --- a/tools/tts_tool.py +++ b/tools/tts_tool.py @@ -997,9 +997,17 @@ def _generate_openai_tts(text: str, output_path: str, tts_config: Dict[str, Any] base_url = oai_config.get("base_url", base_url) speed = float(oai_config.get("speed", tts_config.get("speed", 1.0))) - # Determine response format from extension + # Determine response format from extension. Mirror the Mistral provider so a + # configured wav/flac output_format is honored instead of always forcing mp3. + # wav/flac are valid OpenAI audio.speech response_format values, and some + # OpenAI-compatible backends only implement native WAV (e.g. Chatterbox-TTS-Server), + # where forcing mp3 yields a hard "500: Failed to encode audio". if output_path.endswith(".ogg"): response_format = "opus" + elif output_path.endswith(".wav"): + response_format = "wav" + elif output_path.endswith(".flac"): + response_format = "flac" else: response_format = "mp3"