SK Music: Bugs, Comments, And Feedback

SK Music now plays in the background on iOS — here is what changed

:link: https://skmusic.jacob-dcd.workers.dev

Good news for iPhone/iPad users: SK Music finally stays playing when you switch apps, lock the screen, or use the device for something else.

What the problem was

Until now the player relied on the embedded YouTube IFrame API. That worked in the browser, but iOS/Safari does not let an embedded YouTube player continue in the background. As soon as you left the app the music stopped, and sometimes tracks would skip entirely because the IFrame API would time out and the fallback stream was blocked by the PWA’s CSP.

What changed

The app now downloads the actual audio track from YouTube and plays it through the PWA’s own <audio> element, instead of embedding YouTube’s player. Because the audio file is a real media file — not an iframe — iOS treats it like any other music app and keeps it playing in the background.

How it works (technical overview)

  1. The PWA requests audio from the Cloudflare Worker at /stream?v=VIDEO_ID.
  2. The Worker first looks in a Cloudflare R2 bucket (sk-music-audio).
    • If the song is already there, it serves the cached M4A file directly, with Range/206 support for scrubbing and no delays.
    • If it is not cached, the Worker fetches a Vercel backend that runs yt-dlp to extract the audio URL, streams it, and simultaneously writes a copy to R2 in the background.
  3. Vercel uses --load-info-json so YouTube is only queried once per song, and a proxy/cookie setup to avoid the “Sign in to confirm you’re not a bot” errors.
  4. The PWA’s Content-Security-Policy was updated to allow media from the Worker/Vercel stream origins, so the fallback audio is no longer blocked.

Difference from the original Shalom-Karr/SK-Music

  • The original version depends on the YouTube IFrame API for playback. When that API is unavailable, blocked by a web filter, or restricted by iOS background rules, the song stops or skips.
  • This version removes that dependency for the actual audio: the audio is downloaded as an M4A file and served from Cloudflare R2. The YouTube video data is still used for metadata/artwork, but playback is handled natively by the PWA.

What is live now

  • Cloudflare Worker: https://skmusic.jacob-dcd.workers.dev
  • Vercel stream backend: https://ios-sk-music.vercel.app
  • The songs in the current playlist are already cached in R2.
  • New songs will cache on first play; after that they are served instantly from R2 and work in the background.

One thing to keep in mind: the very first time a new song is played it may take a few seconds to download and cache. After that it is instant and background-capable.

Let me know how it was!

Source Code

Here is the source code for all those that want!

5 Likes