From 465dfd0027c7fdf5704e93da7bbc9b7ea8073e76 Mon Sep 17 00:00:00 2001 From: Marcel van der Veldt Date: Tue, 26 Mar 2024 09:13:32 +0100 Subject: [PATCH] few small optimizations --- music_assistant/server/controllers/streams.py | 23 +++++++++---------- music_assistant/server/helpers/process.py | 17 +++++++------- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/music_assistant/server/controllers/streams.py b/music_assistant/server/controllers/streams.py index d7131158..70762a12 100644 --- a/music_assistant/server/controllers/streams.py +++ b/music_assistant/server/controllers/streams.py @@ -898,7 +898,8 @@ class StreamsController(CoreController): # no crossfade enabled, just yield the buffer last part bytes_written += len(buffer) yield buffer - del buffer + # make sure the buffer gets cleaned up + del buffer # update duration details based on the actual pcm data we sent # this also accounts for crossfade and silence stripping @@ -930,13 +931,13 @@ class StreamsController(CoreController): fmt = announcement_url.rsplit(".")[-1] audio_format = AudioFormat(content_type=ContentType.try_parse(fmt)) extra_args = [] - filter_params = ["loudnorm=I=-10:LRA=7:tp=-2:offset=-0.5"] + filter_params = ["loudnorm=I=-10:LRA=11:TP=-2"] if use_pre_announce: extra_args += [ "-i", ANNOUNCE_ALERT_FILE, "-filter_complex", - "[1:a][0:a]concat=n=2:v=0:a=1,loudnorm=I=-10:LRA=7:tp=-2:offset=-0.5", + "[1:a][0:a]concat=n=2:v=0:a=1,loudnorm=I=-10:LRA=11:TP=-2", ] filter_params = [] async for chunk in get_ffmpeg_stream( @@ -1026,12 +1027,11 @@ class StreamsController(CoreController): stderr_data = "" async for line in ffmpeg_proc.iter_stderr(): line = line.decode().strip() # noqa: PLW2901 - if not line: - continue if stderr_data or "loudnorm" in line: stderr_data += line - else: + elif line: self.logger.log(VERBOSE_LOG_LEVEL, line) + del line # if we reach this point, the process is finished (finish or aborted) if ffmpeg_proc.returncode == 0: @@ -1073,6 +1073,8 @@ class StreamsController(CoreController): ) if music_prov := self.mass.get_provider(streamdetails.provider): self.mass.create_task(music_prov.on_streamed(streamdetails, seconds_streamed)) + # cleanup + del stderr_data async with AsyncProcess( ffmpeg_args, @@ -1119,8 +1121,9 @@ class StreamsController(CoreController): # collect this chunk for next round prev_chunk = chunk # if we did not receive any data, something went (terribly) wrong - # raise here to prevent an endless loop elsewhere + # raise here to prevent an (endless) loop elsewhere if state_data["bytes_sent"] == 0: + del prev_chunk raise AudioError(f"stream error on {streamdetails.uri}") # all chunks received, strip silence of last part if needed and yield remaining bytes @@ -1135,11 +1138,7 @@ class StreamsController(CoreController): else: final_chunk = prev_chunk - # yield final chunk to output (in chunk_size parts) - while len(final_chunk) > chunk_size: - yield final_chunk[:chunk_size] - final_chunk = final_chunk[chunk_size:] - state_data["bytes_sent"] += len(final_chunk) + # yield final chunk to output (as one big chunk) yield final_chunk state_data["bytes_sent"] += len(final_chunk) state_data["finished"].set() diff --git a/music_assistant/server/helpers/process.py b/music_assistant/server/helpers/process.py index 080fbe99..4f2bf61e 100644 --- a/music_assistant/server/helpers/process.py +++ b/music_assistant/server/helpers/process.py @@ -109,16 +109,16 @@ class AsyncProcess: """Yield chunks of n size from the process stdout.""" while self.returncode is None: chunk = await self.readexactly(n) - if len(chunk) == 0: - break + if chunk == b"": + raise StopAsyncIteration yield chunk async def iter_any(self, n: int = DEFAULT_CHUNKSIZE) -> AsyncGenerator[bytes, None]: """Yield chunks as they come in from process stdout.""" while self.returncode is None: chunk = await self.read(n) - if len(chunk) == 0: - break + if chunk == b"": + raise StopAsyncIteration yield chunk async def readexactly(self, n: int) -> bytes: @@ -226,12 +226,11 @@ class AsyncProcess: async def iter_stderr(self) -> AsyncGenerator[bytes, None]: """Iterate lines from the stderr stream.""" while self.returncode is None: - if self.proc.stderr.at_eof(): - break try: - yield await self.proc.stderr.readline() - if self.proc.stderr.at_eof(): - break + line = await self.proc.stderr.readline() + if line == b"": + raise StopAsyncIteration + yield line except ValueError as err: # we're waiting for a line (separator found), but the line was too big # this may happen with ffmpeg during a long (radio) stream where progress -- 2.34.1