fix(tts): repair placeholder RIFF/data sizes in streamed MiniMax WAV output - #9867
Open
kilisamemarisaaa wants to merge 2 commits into
Open
fix(tts): repair placeholder RIFF/data sizes in streamed MiniMax WAV output#9867kilisamemarisaaa wants to merge 2 commits into
kilisamemarisaaa wants to merge 2 commits into
Conversation
Co-Authored-By: EvoX <evox@evomap.ai>
Contributor
There was a problem hiding this comment.
Hey - I've found 2 issues
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="astrbot/core/provider/sources/minimax_tts_api_source.py" line_range="46-47" />
<code_context>
+ payload_start = pos + 8
+ if chunk_id == b"data":
+ if declared == WAV_SIZE_PLACEHOLDER:
+ actual = len(patched) - payload_start
+ patched[pos + 4 : pos + 8] = actual.to_bytes(4, "little")
+ data_patched = True
+ break
</code_context>
<issue_to_address>
**issue (bug_risk):** When the `data` chunk is followed by a padding byte or any later RIFF chunk, `actual = len(patched) - payload_start` includes those bytes in the `data` size. The repaired header therefore claims that padding or subsequent chunks are audio data.
**Triggers:** When a WAV has an odd-sized data payload or contains chunks after `data`.
**Suggested fix:** Determine the data payload boundary from the RIFF chunk structure, or conservatively bail out when a placeholder-sized `data` chunk is not the final chunk.
</issue_to_address>
### Comment 2
<location path="astrbot/core/provider/sources/minimax_tts_api_source.py" line_range="56-57" />
<code_context>
+ return audio
+ pos = payload_start + declared + (declared & 1)
+
+ if data_patched and riff_size == WAV_SIZE_PLACEHOLDER:
+ patched[4:8] = (len(patched) - 8).to_bytes(4, "little")
+ return bytes(patched)
+
</code_context>
<issue_to_address>
**issue (bug_risk):** A file with a placeholder RIFF size but an already-valid `data` size is returned with the invalid RIFF placeholder unchanged because the RIFF field is patched only when `data_patched` is true. This violates the stated behavior of repairing each placeholder field independently.
**Triggers:** When the RIFF size is `0xFFFFFFFF` and the `data` chunk size is already valid.
**Suggested fix:** Patch the RIFF size whenever `riff_size == WAV_SIZE_PLACEHOLDER`, independently of whether the data size was patched.
```suggestion
if riff_size == WAV_SIZE_PLACEHOLDER:
patched[4:8] = (len(patched) - 8).to_bytes(4, "little")
```
</issue_to_address>Sourcery assessment
Needs a human reviewer. 2 findings to address first, and if the chunk walk or size calculation is wrong, the generated WAV can be written with an incorrect header and fail in a strict decoder or include an incorrect data length. The affected audio file can be discarded and regenerated, so reverting the change stops further occurrences but does not repair files already produced.
Blocking findings: astrbot/core/provider/sources/minimax_tts_api_source.py:47, astrbot/core/provider/sources/minimax_tts_api_source.py:57
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
Co-Authored-By: EvoX <evox@evomap.ai>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
minimax_tts_apihardcodesstream: trueandformat: "wav", so the WAV bytes come from MiniMax's server-side ffmpeg. A streamed WAV cannot know its total length up front, so ffmpeg writes0xFFFFFFFFplaceholders into both the RIFF size field and thedatachunk size field._audio_play()only concatenates the hex-decoded SSE chunks andget_audio()writes the bytes to disk untouched, so every savedminimax_tts_api_*.wavcarries an invalid header.Browsers tolerate the placeholder sizes, which is why playback looks fine in the WebUI, but strict decoders (Android WebView / system players) reject the file — and nothing appears in AstrBot's logs. Hex dump from the issue:
Closes #9860
Fix
Add a module-level
_patch_streamed_wav_header()and call it inget_audio()on the assembled bytes right before they are written to disk:datachunk;datachunk size and the RIFF size only when the field holds the0xFFFFFFFFplaceholder, so already-valid files are returned byte-for-byte unchanged;WAVEinput, truncated input, or an un-walkable placeholder-sized chunk beforedata.Tests
tests/unit/test_minimax_tts_wav_header.py(pytest, no network):len(file) - 8/ payload sizes;datais not guessed around (conservative bail-out);data(e.g.LIST) are walked correctly;get_audio()with a mocked hex SSE stream writes a file whose repaired header decodes cleanly.ruff format/ruff checkpass; the repository's neo profile suite (scripts/pr_test_env.sh --profile neo) passes except for two pre-existing failures intests/test_computer_skill_sync.py, which fail identically on a cleanmastercheckout.Historical context
#7144 / #7795 / #7565 reported the earlier
file does not start with RIFF idfailures (MP3 payload under a.wavname), fixed by #7797 switching the default output format to WAV. That left the streamed path producing a correctly-named but header-invalid file; this PR closes that remaining gap.Summary by Sourcery
Repair streamed MiniMax WAV headers before writing audio files so strict decoders can open the generated output.
Bug Fixes:
Enhancements:
Tests: