Raise AudioException if ffmpeg encounters a demuxing error (#3035)
authorFabian Munkes <105975993+fmunkes@users.noreply.github.com>
Tue, 27 Jan 2026 19:39:45 +0000 (20:39 +0100)
committerGitHub <noreply@github.com>
Tue, 27 Jan 2026 19:39:45 +0000 (20:39 +0100)
music_assistant/helpers/ffmpeg.py

index 9ea5ea0c6e371ecdd06f60307193e33d51a89037..e2897762f4911ee1947eb04aff7c177dbc79178c 100644 (file)
@@ -59,6 +59,7 @@ class FFMpeg(AsyncProcess):
         self.input_format = input_format
         self.collect_log_history = collect_log_history
         self.log_history: deque[str] = deque(maxlen=100)
+        self.concat_error = False  # switch to True if concat demuxer fails on MultiPartFiles
         self._stdin_feeder_task: asyncio.Task[None] | None = None
         self._stderr_reader_task: asyncio.Task[None] | None = None
         self._input_codec_parsed = False
@@ -137,6 +138,11 @@ class FFMpeg(AsyncProcess):
             if decode_errors >= 50:
                 self.logger.error(line)
 
+            if "Error during demuxing" in line:
+                # this can occur if using the concat demuxer for multipart files
+                # and should raise an exception to prevent false progress logging
+                self.concat_error = True
+
             # if streamdetails contenttype is unknown, try parse it from the ffmpeg log
             if line.startswith("Stream #") and ": Audio: " in line:
                 if not self._input_codec_parsed:
@@ -223,9 +229,10 @@ async def get_ffmpeg_stream(
         iterator = ffmpeg_proc.iter_chunked(chunk_size) if chunk_size else ffmpeg_proc.iter_any()
         async for chunk in iterator:
             yield chunk
-        if ffmpeg_proc.returncode not in (None, 0):
+        if ffmpeg_proc.returncode not in (None, 0) or ffmpeg_proc.concat_error:
             # unclean exit of ffmpeg - raise error with log tail
-            log_tail = "\n" + "\n".join(list(ffmpeg_proc.log_history)[-5:])
+            log_lines = -20 if ffmpeg_proc.concat_error else -5
+            log_tail = "\n" + "\n".join(list(ffmpeg_proc.log_history)[log_lines:])
             raise AudioError(log_tail)