Skip to content

Fix media-key next replaying same song in background - #1

Closed
Endiruslan wants to merge 1 commit into
mainfrom
fix/background-media-key-override
Closed

Fix media-key next replaying same song in background#1
Endiruslan wants to merge 1 commit into
mainfrom
fix/background-media-key-override

Conversation

@Endiruslan

Copy link
Copy Markdown
Owner

Problem

Pressing the macOS media next key while the app is in the background sometimes restarts the same song from the beginning instead of advancing to the next track in the queue.

Root cause

In nextPreviousTrack mode, Kaset overrides the WebView's navigator.mediaSession nexttrack/previoustrack handlers so media keys advance the native queue (via the REMOTE_NEXT message). YouTube Music periodically re-registers its own handlers, and Kaset re-asserts its override through a requestAnimationFrame loop on the page.

WebKit freezes requestAnimationFrame while the app is backgrounded, so the override was never re-applied. After some time backgrounded, a media-key press fell through to YouTube's own handler, which jumped to YouTube's recommended video. Queue-drift recovery (handleUnexpectedQueueDriftIfNeeded) then saw a video that wasn't in the native queue and force-reloaded the current queue song from 0 — the same song appeared to restart.

Fix

Drive the override re-assertion from a native run-loop Timer instead of relying solely on the page's requestAnimationFrame loop:

  • Starts on applicationDidResignActive.
  • Stops on applicationDidBecomeActive (where the page's rAF loop resumes ownership), plus one immediate re-assert.

Native timers keep firing in the background (active audio playback prevents App Nap), so the override stays installed and media keys continue to advance the native queue. This extends the existing override-maintenance mechanism (__kasetRefreshMediaControlStyle) rather than introducing a new path.

Verification

Confirmed at runtime with a file tracer (since removed): 5 next presses over 60+ seconds backgrounded each routed through REMOTE_NEXTnext() and advanced to the following queue track, with zero drift-recovery restarts.

🤖 Generated with Claude Code

In nextPreviousTrack mode, Kaset overrides the WebView's
navigator.mediaSession 'nexttrack'/'previoustrack' handlers so media
keys advance the native queue (via REMOTE_NEXT). YouTube Music
periodically re-registers its own handlers, and Kaset re-asserts its
override through a requestAnimationFrame loop on the page.

WebKit freezes requestAnimationFrame while the app is backgrounded, so
the override was never re-applied. After some time backgrounded a
media-key press fell through to YouTube's own handler, which jumped to
YouTube's recommended video. Queue-drift recovery then saw a video not
in the native queue and force-reloaded the current queue song from 0 —
the same song appeared to restart.

Drive the override re-assertion from a native run-loop Timer instead.
It starts on applicationDidResignActive and stops on
applicationDidBecomeActive (where the page's rAF loop resumes ownership).
Native timers keep firing in the background (active audio playback
prevents App Nap), so the override stays installed and media keys
continue to advance the native queue.

Verified at runtime: 5 next presses over 60+s backgrounded each routed
through REMOTE_NEXT -> next() and advanced to the following queue track,
with zero drift-recovery restarts.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Endiruslan

Copy link
Copy Markdown
Owner Author

Superseded by upstream PR sozercan#319.

@Endiruslan Endiruslan closed this Jun 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant