From: Marcel van der Veldt Date: Thu, 16 Jan 2025 10:42:41 +0000 (+0100) Subject: Don't force close ffmpeg if no need X-Git-Url: https://git.kitaultman.com/?a=commitdiff_plain;h=8d053f1a9f4918f3c45712979c8a771f2f3873ce;p=music-assistant-server.git Don't force close ffmpeg if no need --- diff --git a/music_assistant/helpers/audio.py b/music_assistant/helpers/audio.py index ffe42da2..3a4aff70 100644 --- a/music_assistant/helpers/audio.py +++ b/music_assistant/helpers/audio.py @@ -383,6 +383,8 @@ async def get_media_stream( yield buffer del buffer finished = True + # wait until stderr also completed reading + await ffmpeg_proc.wait_with_timeout(5) except Exception as err: if isinstance(err, asyncio.CancelledError): # we were cancelled, just raise @@ -390,21 +392,26 @@ async def get_media_stream( logger.error("Error while streaming %s: %s", streamdetails.uri, err) streamdetails.stream_error = True finally: - logger.log(VERBOSE_LOG_LEVEL, "Closing ffmpeg...") - await ffmpeg_proc.close() + if not finished: + logger.log(VERBOSE_LOG_LEVEL, "Closing ffmpeg...") + await ffmpeg_proc.close() # try to determine how many seconds we've streamed seconds_streamed = bytes_sent / pcm_format.pcm_sample_size if bytes_sent else 0 + if ffmpeg_proc.returncode != 0: + # dump the last 25 lines of the log in case of an unclean exit + log_tail = "\n" + "\n".join(list(ffmpeg_proc.log_history)[-25:]) + logger.debug(log_tail) + else: + log_tail = "" logger.debug( - "stream %s (with code %s) for %s - seconds streamed: %s", + "stream %s (with code %s) for %s - seconds streamed: %s %s", "finished" if finished else "aborted", ffmpeg_proc.returncode, streamdetails.uri, seconds_streamed, + log_tail, ) - if ffmpeg_proc.returncode != 0: - log_tail = "\n".join(list(ffmpeg_proc.log_history)[:25]) - logger.debug(log_tail) streamdetails.seconds_streamed = seconds_streamed # store accurate duration diff --git a/music_assistant/helpers/process.py b/music_assistant/helpers/process.py index 21d0ef03..009e1c66 100644 --- a/music_assistant/helpers/process.py +++ b/music_assistant/helpers/process.py @@ -257,6 +257,10 @@ class AsyncProcess: self._returncode = await self.proc.wait() return self._returncode + async def wait_with_timeout(self, timeout: int) -> int: + """Wait for the process and return the returncode with a timeout.""" + return await asyncio.wait_for(self.wait(), timeout) + async def check_output(*args: str, env: dict[str, str] | None = None) -> tuple[int, bytes]: """Run subprocess and return returncode and output."""