From: Marcel van der Veldt Date: Mon, 30 Sep 2024 22:40:07 +0000 (+0200) Subject: Fix some playback issues (#1689) X-Git-Url: https://git.kitaultman.com/?a=commitdiff_plain;h=9c800b0cd9a801c672ffad71b48e5283a33fc9e5;p=music-assistant-server.git Fix some playback issues (#1689) --- diff --git a/music_assistant/server/controllers/player_queues.py b/music_assistant/server/controllers/player_queues.py index a4a6f96f..6267eb35 100644 --- a/music_assistant/server/controllers/player_queues.py +++ b/music_assistant/server/controllers/player_queues.py @@ -290,7 +290,7 @@ class PlayerQueuesController(CoreController): # we need to restart playback self.mass.create_task(self.resume(queue_id)) else: - self.mass.create_task(self._enqueue_next(queue, queue.current_index)) + self.mass.call_later(5, self._enqueue_next(queue, queue.current_index)) @api_command("player_queues/play_media") async def play_media( diff --git a/music_assistant/server/helpers/audio.py b/music_assistant/server/helpers/audio.py index 559b13fd..b871ae30 100644 --- a/music_assistant/server/helpers/audio.py +++ b/music_assistant/server/helpers/audio.py @@ -46,7 +46,7 @@ from .playlists import HLS_CONTENT_TYPES, IsHLSPlaylist, PlaylistItem, fetch_pla from .process import AsyncProcess, check_output, communicate from .tags import parse_tags from .throttle_retry import BYPASS_THROTTLER -from .util import create_tempfile +from .util import TimedAsyncGenerator, create_tempfile if TYPE_CHECKING: from music_assistant.common.models.player_queue import QueueItem @@ -296,7 +296,9 @@ async def get_media_stream( ) try: await ffmpeg_proc.start() - async for chunk in ffmpeg_proc.iter_chunked(pcm_format.pcm_sample_size): + async for chunk in TimedAsyncGenerator( + ffmpeg_proc.iter_chunked(pcm_format.pcm_sample_size), 60 + ): # for radio streams we just yield all chunks directly if streamdetails.media_type == MediaType.RADIO: yield chunk diff --git a/music_assistant/server/helpers/ffmpeg.py b/music_assistant/server/helpers/ffmpeg.py index 0aaa9dcf..392f2cee 100644 --- a/music_assistant/server/helpers/ffmpeg.py +++ b/music_assistant/server/helpers/ffmpeg.py @@ -14,7 +14,7 @@ from music_assistant.common.models.media_items import AudioFormat, ContentType from music_assistant.constants import VERBOSE_LOG_LEVEL from .process import AsyncProcess -from .util import close_async_generator +from .util import TimedAsyncGenerator, close_async_generator LOGGER = logging.getLogger("ffmpeg") @@ -122,7 +122,7 @@ class FFMpeg(AsyncProcess): generator_exhausted = False audio_received = False try: - async for chunk in self.audio_input: + async for chunk in TimedAsyncGenerator(self.audio_input, 30): audio_received = True await self.write(chunk) generator_exhausted = True @@ -169,7 +169,7 @@ async def get_ffmpeg_stream( ) as ffmpeg_proc: # read final chunks from stdout iterator = ffmpeg_proc.iter_chunked(chunk_size) if chunk_size else ffmpeg_proc.iter_any() - async for chunk in iterator: + async for chunk in TimedAsyncGenerator(iterator, 60): yield chunk diff --git a/music_assistant/server/helpers/util.py b/music_assistant/server/helpers/util.py index 55c8439e..95896f6d 100644 --- a/music_assistant/server/helpers/util.py +++ b/music_assistant/server/helpers/util.py @@ -249,3 +249,36 @@ def lock( return await func(*args, **kwargs) return wrapper + + +class TimedAsyncGenerator: + """ + Async iterable that times out after a given time. + + Source: https://medium.com/@dmitry8912/implementing-timeouts-in-pythons-asynchronous-generators-f7cbaa6dc1e9 + """ + + def __init__(self, iterable, timeout=0): + """ + Initialize the AsyncTimedIterable. + + Args: + iterable: The async iterable to wrap. + timeout: The timeout in seconds for each iteration. + """ + + class AsyncTimedIterator: + def __init__(self): + self._iterator = iterable.__aiter__() + + async def __anext__(self): + result = await asyncio.wait_for(self._iterator.__anext__(), int(timeout)) + if not result: + raise StopAsyncIteration + return result + + self._factory = AsyncTimedIterator + + def __aiter__(self): + """Return the async iterator.""" + return self._factory() diff --git a/music_assistant/server/providers/spotify/__init__.py b/music_assistant/server/providers/spotify/__init__.py index 7bd49696..52b238a2 100644 --- a/music_assistant/server/providers/spotify/__init__.py +++ b/music_assistant/server/providers/spotify/__init__.py @@ -576,7 +576,7 @@ class SpotifyProvider(MusicProvider): "pipe", "--single-track", spotify_uri, - "--token", + "--access-token", auth_info["access_token"], ] if seek_position: diff --git a/music_assistant/server/providers/spotify/bin/librespot-linux-aarch64 b/music_assistant/server/providers/spotify/bin/librespot-linux-aarch64 index 8ce08d22..24c26e2f 100755 Binary files a/music_assistant/server/providers/spotify/bin/librespot-linux-aarch64 and b/music_assistant/server/providers/spotify/bin/librespot-linux-aarch64 differ diff --git a/music_assistant/server/providers/spotify/bin/librespot-linux-x86_64 b/music_assistant/server/providers/spotify/bin/librespot-linux-x86_64 index b780aba4..fefd8061 100755 Binary files a/music_assistant/server/providers/spotify/bin/librespot-linux-x86_64 and b/music_assistant/server/providers/spotify/bin/librespot-linux-x86_64 differ diff --git a/music_assistant/server/providers/spotify/bin/librespot-macos-arm64 b/music_assistant/server/providers/spotify/bin/librespot-macos-arm64 index 60722e85..4222d547 100755 Binary files a/music_assistant/server/providers/spotify/bin/librespot-macos-arm64 and b/music_assistant/server/providers/spotify/bin/librespot-macos-arm64 differ