Fix Qobuz media stream gets aborted (#456)
authorMarcel van der Veldt <m.vanderveldt@outlook.com>
Mon, 15 Aug 2022 23:26:54 +0000 (01:26 +0200)
committerGitHub <noreply@github.com>
Mon, 15 Aug 2022 23:26:54 +0000 (01:26 +0200)
music_assistant/controllers/streams.py
music_assistant/helpers/audio.py
music_assistant/mass.py
music_assistant/music_providers/qobuz/qobuz.py

index 98d7328662980692ec9fe60893bb05c9de7c46a3..8c2b4342157bf038d3d6e14bc5974d87637f88fb 100644 (file)
@@ -224,7 +224,7 @@ class StreamsController:
                 "Got stream request for unknown or finished stream: %s",
                 stream_id,
             )
-            return web.FileResponse(SILENCE_FILE)
+            return web.Response(status=404)
 
         # handle a second connection for the same player
         # this probably means a client which does multiple GET requests (e.g. Kodi, Vlc)
@@ -631,12 +631,10 @@ class QueueStream:
                 and prev_track.media_type == MediaType.TRACK
                 and queue_track.media_type == MediaType.TRACK
             ):
-                prev_item = await self.mass.music.get_item_by_uri(prev_track.uri)
-                new_item = await self.mass.music.get_item_by_uri(queue_track.uri)
                 if (
-                    prev_item.album is not None
-                    and new_item.album is not None
-                    and prev_item.album == new_item.album
+                    prev_track.media_item.album is not None
+                    and queue_track.media_item.album is not None
+                    and prev_track.media_item.album == queue_track.media_item.album
                 ):
                     self.logger.debug("Skipping crossfade: Tracks are from same album")
                     use_crossfade = False
@@ -644,7 +642,7 @@ class QueueStream:
 
             self.logger.info(
                 "Start Streaming queue track: %s (%s) for queue %s - crossfade: %s",
-                queue_track.uri,
+                streamdetails.uri,
                 queue_track.name,
                 self.queue.player.name,
                 use_crossfade,
@@ -731,7 +729,7 @@ class QueueStream:
 
             if bytes_written == 0:
                 # stream error: got empy first chunk ?!
-                self.logger.warning("Stream error on %s", queue_track.uri)
+                self.logger.warning("Stream error on %s", streamdetails.uri)
                 queue_track.streamdetails.seconds_streamed = 0
                 continue
 
@@ -744,11 +742,13 @@ class QueueStream:
             # log warning if received seconds are a lot less than expected
             if (stream_duration - chunk_num) > 20:
                 self.logger.warning(
-                    "Unexpected number of chunks received for track %s: %s/%s - process_time: %s",
-                    queue_track.uri,
+                    "Unexpected number of chunks received for track %s: %s/%s - "
+                    "process_time: %s - player_buffered: %s",
+                    streamdetails.uri,
                     chunk_num,
                     stream_duration,
                     process_time,
+                    player_buffered,
                 )
             self.logger.debug(
                 "end of track reached - chunk_num: %s - crossfade_buffer: %s - "
@@ -791,7 +791,7 @@ class QueueStream:
             )
             self.logger.debug(
                 "Finished Streaming queue track: %s (%s) on queue %s",
-                queue_track.uri,
+                queue_track.streamdetails.uri,
                 queue_track.name,
                 self.queue.player.name,
             )
index f33547fde331981e047e355a66d89adf6d842b0e..ac244237eab826f7c63e3803dcb8361c8aa49bef 100644 (file)
@@ -230,7 +230,7 @@ async def get_stream_details(
         param queue_id: Optionally provide the queue_id which will play this stream.
     """
     streamdetails = None
-    if queue_item.streamdetails and (time() < queue_item.streamdetails.expires):
+    if queue_item.streamdetails and (time() < (queue_item.streamdetails.expires - 60)):
         # we already have fresh streamdetails, use these
         queue_item.streamdetails.seconds_skipped = None
         queue_item.streamdetails.seconds_streamed = None
@@ -697,6 +697,18 @@ async def _get_ffmpeg_args(
     ]
     if streamdetails.direct:
         # ffmpeg can access the inputfile (or url) directly
+        input_args += [
+            "-reconnect",
+            "1",
+            "-reconnect_streamed",
+            "1",
+            "-reconnect_on_network_error",
+            "1",
+            "-reconnect_on_http_error",
+            "5xx",
+            "-reconnect_delay_max",
+            "10",
+        ]
         if seek_position:
             input_args += ["-ss", str(seek_position)]
         input_args += ["-i", streamdetails.direct]
index 66a386e194d1707bd7640d154a41288e9ff001c9..a0807b67a4d92b71540ac8e17bc202bbf27625f9 100644 (file)
@@ -157,7 +157,9 @@ class MusicAssistant:
         job = BackgroundJob(str(uuid4()), name=name, coro=coro)
         self._jobs.append(job)
         self._jobs_event.set()
-        self.signal_event(MassEvent(EventType.BACKGROUND_JOB_UPDATED, data=job))
+        self.signal_event(
+            MassEvent(EventType.BACKGROUND_JOB_UPDATED, job.name, data=job)
+        )
         return job
 
     def create_task(
index 099a748b51da5bc0993d926d1a756e181b0c9bee..a62f977e303b85676dc3cfbc1942eb53db990979 100644 (file)
@@ -361,7 +361,7 @@ class QobuzProvider(MusicProvider):
             sample_rate=int(streamdata["sampling_rate"] * 1000),
             bit_depth=streamdata["bit_depth"],
             data=streamdata,  # we need these details for reporting playback
-            expires=time.time() + 600,  # not sure about the real allowed value
+            expires=time.time() + 3600,  # not sure about the real allowed value
             direct=streamdata["url"],
             callback=self._report_playback_stopped,
         )