From fd834314ba1b1a583c7267a302e91fb516861005 Mon Sep 17 00:00:00 2001 From: Psychotoxical Date: Thu, 9 Apr 2026 21:42:38 +0200 Subject: [PATCH] fix(audio): VLC-style frame dropping for corrupt MP3s, silence logs in release MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the fixed DECODE_MAX_RETRIES (3) loop with a consecutive-error counter that tolerates up to 100 bad frames before giving up — matching how VLC handles files with a handful of invalid main_data offset frames. Frame-drop logs are wrapped in #[cfg(debug_assertions)] so production builds stay silent. Co-Authored-By: Claude Sonnet 4.6 --- src-tauri/src/audio.rs | 74 +++++++++++++++++++++++++++++++++--------- 1 file changed, 58 insertions(+), 16 deletions(-) diff --git a/src-tauri/src/audio.rs b/src-tauri/src/audio.rs index 6535097c..6030dbed 100644 --- a/src-tauri/src/audio.rs +++ b/src-tauri/src/audio.rs @@ -890,7 +890,13 @@ impl MediaSource for SizedCursorSource { // Implements Iterator + Source — identical interface to // rodio::Decoder, so the rest of the source chain is unchanged. +/// Max retries for IO/packet-read errors (fatal — network drop, truncated file). const DECODE_MAX_RETRIES: usize = 3; +/// Max *consecutive* DecodeErrors before giving up on a file. +/// Non-fatal errors like "invalid main_data offset" are silently dropped up to +/// this limit so a handful of corrupt MP3 frames never aborts an otherwise +/// playable track (VLC-style frame dropping). +const MAX_CONSECUTIVE_DECODE_ERRORS: usize = 100; struct SizedDecoder { decoder: Box, @@ -899,6 +905,9 @@ struct SizedDecoder { total_duration: Option