fix(audio): don't report a stopped playback as a decode error - #6723
Merged
Conversation
Stopping a BackgroundAudioPlayer clip logs "error decoding audio" with an av.error.InvalidDataError or EOFError raised from av.open. The stop is intentional and the audio is fine. The decode worker thread can still be probing the container when the input is torn down, and there are two windows for that. audio_frames_from_file cancels its reader task first, and the reader's finally calls decoder.end_input(), so a half-read file reaches PyAV as a complete container. aclose() then closes the StreamBuffer out from under the thread, which is a second, smaller window. _decode_loop reports both through a blanket except Exception. A cancelled read now signals an abort instead of an end of input, aclose() marks the decoder closed before tearing the input down, and _decode_loop skips the log once that flag is set. The WAV inline path already had the same guard. Genuine decode failures are unaffected: garbage input, a corrupt file read to completion, and a missing file all still report as before.
…hread The 120-iteration stop/start sweep asserted that no decode error is logged across a timing window. It passed on macOS and on Linux in a container, and failed only on the CI runners, where it also caught probe failures that the close guard is not responsible for. Assert the contract the fix establishes instead: a cancelled read must not signal an end of input. Holding the reader mid-file with a slow push makes that deterministic, and it still fails against the unpatched reader.
theomonnom
approved these changes
Aug 6, 2026
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
A stop on a
BackgroundAudioPlayerclip writeserror decoding audioto the log. PyAV raisesav.error.InvalidDataErrororEOFErrorfromav.open. The stop is intentional and the audio file is correct. A clip that loops hits this often, because_loop_audio_framesopens a new container for each iteration.When the input closes, the decode thread can still read the container header. Two paths close it.
audio_frames_from_filecancels the reader task, and thefinallyblock of the reader callsdecoder.end_input(). PyAV then reads a part of the file as a complete container.aclose()closes theStreamBufferwhile the thread reads it._decode_loopreports both windows through oneexcept Exceptionblock.Fix
A cancelled read no longer signals an end of input.
aclose()marks the decoder closed before it closes the input._decode_loopwrites no error after that flag is set. The WAV path already had this guard.Real decode errors stay visible. Garbage input, a corrupt file, and a missing file all report as before.
This change keeps #3863 open. The other reports there come from a mime and encoding mismatch. That is a real decode error, and the log keeps it.