fix(audio): copy Opus frame data in OGG decoder to prevent corruption#2504
Open
jacrify wants to merge 1 commit intosipeed:mainfrom
Open
fix(audio): copy Opus frame data in OGG decoder to prevent corruption#2504jacrify wants to merge 1 commit intosipeed:mainfrom
jacrify wants to merge 1 commit intosipeed:mainfrom
Conversation
DecodeOggOpus passes a slice from bytes.Buffer.Bytes() to the onFrame callback, then calls packet.Reset(). Reset reuses the underlying array, so when the next packet is assembled the previous slice's data is overwritten. In Discord voice playback the frames are sent to a buffered channel (OpusSend, cap 16); by the time opusSender reads a frame, its backing memory has been mutated by subsequent decoder iterations. The resulting Opus frame corruption causes audible artifacts: garbled or whispery audio depending on how much of each frame is overwritten before the voice sender transmits it. Fix: allocate a dedicated copy of each frame before handing it to the callback, decoupling the consumer's data from the reusable buffer. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
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.
Description
Fix a buffer reuse bug in
DecodeOggOpusthat corrupts every Opus frame before Discord's voice sender can transmit it.packet.Bytes()returns a slice backed by thebytes.Bufferinternal array. This slice is passed to theonFramecallback, which sends it to discordgo'sOpusSendchannel (buffered, cap 16). Immediately after,packet.Reset()resets the buffer length but retains the underlying array. As subsequent packets are assembled, the previous slice's data is silently overwritten while it is still queued in the channel waiting to be read by theopusSendergoroutine.The result is that Discord receives corrupted Opus frames on every send. Depending on how much of each frame is overwritten before transmission, this manifests as garbled or whispery audio in Discord voice channels.
Root cause
Fix
Allocate a copy of the frame data before passing it to the callback:
Type of Change
🤖 AI Code Generation
🛠️ Mostly AI-generated — AI identified the bug through systematic diagnosis of Discord voice audio quality issues and wrote the fix; contributor validated and tested on hardware.
Test Environment
main@2e149f4Evidence
Before fix: Discord voice TTS consistently produced whispery/garbled audio across all TTS models and encoding approaches (direct opus passthrough, PCM+ffmpeg transcode, WAV+opusenc). The encoding pipeline was verified correct by round-trip decode testing — the issue was isolated to frame delivery.
After fix: Clear, normal-volume TTS playback in Discord voice with direct opus passthrough from OpenAI (zero transcoding, no ffmpeg dependency).
Checklist