fix(transcription): drop words from srt/vtt replies when synthesis falls back

This commit is contained in:
mateo-berri 2026-08-27 13:36:31 -07:00
parent f2e64d9818
commit 5d8eb049b5
2 changed files with 50 additions and 6 deletions

View file

@ -25,7 +25,10 @@ from litellm.litellm_core_utils.agentic_loop_settings import (
validated_max_agentic_loops,
)
from litellm.litellm_core_utils.asyncify import run_async_function
from litellm.litellm_core_utils.audio_utils.subtitle_utils import synthesize_subtitle_document
from litellm.litellm_core_utils.audio_utils.subtitle_utils import (
SUBTITLE_RESPONSE_FORMATS,
synthesize_subtitle_document,
)
from litellm.litellm_core_utils.llm_request_utils import serialize_multipart_form_fields
from litellm.litellm_core_utils.realtime_errors import realtime_error_event, websocket_close_reason
from litellm.litellm_core_utils.realtime_streaming import RealTimeStreaming
@ -1303,16 +1306,16 @@ class BaseLLMHTTPHandler:
if not provider_config.supports_subtitle_synthesis:
return transformed
requested_format: Final = optional_params.get("response_format")
if not isinstance(requested_format, str):
if not isinstance(requested_format, str) or requested_format not in SUBTITLE_RESPONSE_FORMATS:
return transformed
document: Final = synthesize_subtitle_document(
words=transformed.get("words"),
response_format=requested_format,
)
if document is None:
return transformed
transformed.text = document
delattr(transformed, "words")
if document is not None:
transformed.text = document
if "words" in transformed:
delattr(transformed, "words")
return transformed
def audio_transcriptions(

View file

@ -1930,6 +1930,47 @@ def test_transform_audio_transcription_response_without_subtitle_opt_in_keeps_te
assert response["words"] == words
class _SubtitleSynthesisAudioTranscriptionConfig(_JSONBodyAudioTranscriptionConfig):
@property
def supports_subtitle_synthesis(self) -> bool:
return True
def transform_audio_transcription_response(self, raw_response):
payload = raw_response.json()
response = TranscriptionResponse(text=payload["text"])
if "words" in payload:
response["words"] = payload["words"]
return response
def _transform_subtitle_response(payload):
return BaseLLMHTTPHandler()._transform_audio_transcription_response(
provider_config=_SubtitleSynthesisAudioTranscriptionConfig(),
model="test-model",
response=httpx.Response(200, json=payload),
model_response=TranscriptionResponse(),
logging_obj=Mock(),
optional_params={"response_format": "srt"},
api_key=None,
)
def test_subtitle_synthesis_fallback_without_timings_drops_words():
response = _transform_subtitle_response(
{"text": "hello world", "words": [{"word": "hello"}, {"word": "world"}]}
)
assert response.text == "hello world"
assert "words" not in response
def test_subtitle_synthesis_without_words_keeps_plain_text():
response = _transform_subtitle_response({"text": "hello world"})
assert response.text == "hello world"
assert "words" not in response
@pytest.mark.asyncio
async def test_async_retrieve_file_content_raises_on_http_error():
"""