fix(server): segment text-only OpenAI transcription responses#3292
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces fallback segment generation for non-LLM models when only text is returned. It adds helper functions to split text into OpenAI-compatible segments based on character length and audio duration, and includes unit tests for this behavior. Feedback highlights two main issues: potential data loss when the audio duration is invalid or zero (where only the first segment of a split text is returned instead of the full text), and a redundant, dead-code check for an empty word list after the text has already been stripped and validated.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| if len(parts) == 1 or duration <= 0: | ||
| return [{"start": 0.0, "end": max(float(duration), 0.0), "text": parts[0]}] |
There was a problem hiding this comment.
When duration is less than or equal to 0 (which can happen if soundfile.info fails to parse the audio duration, e.g., for unsupported formats like MP3 on some platforms), and the transcribed text is long enough to be split into multiple parts, returning parts[0] will silently discard all subsequent parts of the transcription. This leads to severe data loss in the response. Instead, the entire text.strip() should be returned as a single segment when the duration is invalid or cannot be determined.
| if len(parts) == 1 or duration <= 0: | |
| return [{"start": 0.0, "end": max(float(duration), 0.0), "text": parts[0]}] | |
| if len(parts) == 1 or duration <= 0: | |
| return [{"start": 0.0, "end": max(float(duration), 0.0), "text": text.strip()}] |
| words = text.split() | ||
| if not words: | ||
| return [text[i : i + max_chars] for i in range(0, len(text), max_chars)] |
There was a problem hiding this comment.
Since text is stripped and checked for truthiness on lines 31-33, it is guaranteed to contain at least one non-whitespace character. Therefore, text.split() will never return an empty list, making the if not words: check dead code. We can safely remove this check to simplify the function.
| words = text.split() | |
| if not words: | |
| return [text[i : i + max_chars] for i in range(0, len(text), max_chars)] | |
| words = text.split() |
Summary
Fixes the OpenAI-compatible
/v1/audio/transcriptionsfallback path for non-vLLM models such assensevoice/paraformerwhen the underlyingAutoModel.generate()result returns text but nosentence_info.Before this patch,
response_format=verbose_jsonreturnedsegments: []even whentextwas populated, which causes OpenAI-compatible clients that rely onsegmentsfor subtitles to render one large cue or lose timing entirely.This patch:
soundfile.info()sentence_infowhen availablesentence_infois missingValidation