Skip to content

Add playback_speed for variable-speed elapsed-time tracking#213

Open
OzGav wants to merge 2 commits intomainfrom
adjust-playback-speed
Open

Add playback_speed for variable-speed elapsed-time tracking#213
OzGav wants to merge 2 commits intomainfrom
adjust-playback-speed

Conversation

@OzGav
Copy link
Copy Markdown
Contributor

@OzGav OzGav commented Apr 27, 2026

Looking to satisfy https://github.com/orgs/music-assistant/discussions/3790

Music Assistant already supports variable playback speed by applying ffmpeg's atempo filter to speed up the audio before it reaches the player. However, this will break elapsed-time accounting because the player only knows how long it has been playing the (sped-up) audio — it has no idea how much of the original content the listener has heard.

Without knowing the speed, the queue and the progress bar can't tell those two values apart, which causes:

  1. The progress bar to drift from the listener's actual position between server updates, because the realtime tick advances using real-world seconds instead of audiobook seconds; and

  2. Flow mode (where MA stitches multiple tracks into one continuous stream for players that can't gap-lessly switch tracks) to pick the wrong track boundary when the speed varies across items in the stream.

This PR adds two new fields, both defaulting to 1.0, so the speed travels alongside the timing data:

  • PlayerQueue.playback_speed: the speed in effect at the moment of the last elapsed_time update. The corrected_elapsed_time property is updated to multiply its between-update delta by this value, so the progress bar ticks in audiobook/podcast playback seconds rather than real-world seconds.

  • PlayLogEntry.playback_speed: the speed at which each flow-mode segment was streamed. The MA controller uses this to figure out which track is currently playing when the speed has varied across segments in a single stream.

The new fields default to 1.0 which means the current callers get exactly the same behaviour.

The corresponding server PR uses these fields to record elapsed_time in audiobook/podcast playback seconds and to step through the flow-mode playlog with the correct speed for each segment.

@OzGav OzGav added the enhancement Enhancement of an existing feature/functionality label Apr 27, 2026
@MarvinSchenkel
Copy link
Copy Markdown
Contributor

I don't think we need this on the PlayLog right? If I remember correctly, the streamscontroller writes the duration based on the bytes that were streamed to the player rather than 'elapsed time'.

@marcelveldt ?

@OzGav
Copy link
Copy Markdown
Contributor Author

OzGav commented Apr 28, 2026

I think you're right that seconds_streamed is calculated from bytes so it's already in "real seconds" and doesn't need the speed for the boundary check.

But I think we still use the speed in one spot — when working out how far into the current track the listener actually is, we multiply the player's elapsed seconds by the speed to convert it back into audiobook seconds (so the progress bar shows the right position).

I think we could probably just read that speed off queue.current_item instead of storing it on the PlayLogEntry, since the entry we break on is always the current item. The reason I put it on the PlayLogEntry is that when a user changes the speed, the queue item's speed updates straight away but the stream takes a moment to restart — so for that brief window the audio actually playing was generated at the old speed. Storing it on the entry pins it to "what the audio was streamed at" rather than "what the queue setting currently says".

Happy to drop it if you don't think that window matters in practice.

@marcelveldt
Copy link
Copy Markdown
Member

marcelveldt commented Apr 28, 2026

You don't need this on the PlayLogEntry

Comment thread music_assistant_models/player_queue.py
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement Enhancement of an existing feature/functionality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants