From b8fceecca4412c12c3ef82d94c3ac03f5ac66e95 Mon Sep 17 00:00:00 2001 From: Andy Kelk Date: Sun, 22 Feb 2026 10:30:26 +1100 Subject: [PATCH] Add API to handle playback speed (#3198) --- music_assistant/controllers/player_queues.py | 18 ++++++++++++++++++ music_assistant/helpers/audio.py | 6 ++++++ 2 files changed, 24 insertions(+) diff --git a/music_assistant/controllers/player_queues.py b/music_assistant/controllers/player_queues.py index 99795cca..a589a6f2 100644 --- a/music_assistant/controllers/player_queues.py +++ b/music_assistant/controllers/player_queues.py @@ -389,6 +389,24 @@ class PlayerQueuesController(CoreController): if next_item := self.get_next_item(queue_id, queue.index_in_buffer): self._enqueue_next_item(queue_id, next_item) + @api_command("player_queues/set_playback_speed") + async def set_playback_speed(self, queue_id: str, speed: float) -> None: + """Set the playback speed for the given queue. + + :param queue_id: queue_id of the queue to configure. + :param speed: playback speed multiplier (0.5 to 2.0). 1.0 = normal speed. + """ + if not (0.5 <= speed <= 2.0): + raise InvalidDataError(f"Playback speed must be between 0.5 and 2.0, got {speed}") + queue = self._queues[queue_id] + current_speed = float(queue.extra_attributes.get("playback_speed") or 1.0) + if abs(current_speed - speed) < 0.001: + return # no change + queue.extra_attributes["playback_speed"] = speed + self.signal_update(queue_id) + if queue.state == PlaybackState.PLAYING: + await self.resume(queue_id) + @api_command("player_queues/play_media") async def play_media( self, diff --git a/music_assistant/helpers/audio.py b/music_assistant/helpers/audio.py index 2dd60995..e44f1d02 100644 --- a/music_assistant/helpers/audio.py +++ b/music_assistant/helpers/audio.py @@ -1465,6 +1465,12 @@ def get_player_filter_params( elif conf_channels == "right": filter_params.append("pan=mono|c0=FR") + # Apply playback speed via atempo filter if a non-default speed is set on the queue. + if _speed_queue := mass.player_queues.get_active_queue(player_id): + speed = float(_speed_queue.extra_attributes.get("playback_speed") or 1.0) + if speed != 1.0: + filter_params.append(f"atempo={speed:.4f}") + # Add safety limiter at the end if limiter_enabled: filter_params.append("alimiter=limit=-2dB:level=false:asc=true") -- 2.34.1