tap download
innertube requests song and gets returned a scrambled link (depending on client used)
my cipher deobfuscates it (if needed)
app downloads with a normal web request
Really? I made a shortcut to the home screen on my iPhone, so that it looks like an app, but is running a webview orientation. Would it still cut playback if I left the SK Music screen, or shut my phone just because itâs pulling from YouTube in th background?
Yup, this is what I experienced. I tried adding some workarounds like playsinline=1 and Page Visibility API but that didnât help much it only made that it fires immediately, auto-resuming the music right where I left off.
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)
The PWA requests audio from the Cloudflare Worker at /stream?v=VIDEO_ID.
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.
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.
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.
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.
@Shalom_Karr i added to the iOS - skmusic version that by tapping the sections title like âlatest releasesâ should create a queue of all the songs and albums in that section,
Thought itâs a great feature to add to the official sk music.
Think about what actually happens: someone taps âLatest Releasesâ because they want to see the releases. Instead their queue gets wiped and a random song starts blasting. Nobody expects a title to do that. No app does that. Titles are for opening the list, thatâs it. And you underlined it, so now it looks even more like a normal link people should click. Great.
Also I read the code. Youâre regexing my rendered HTML out of the markup to figure out whatâs in the section. I change those all the time. The first time I touch one this just stops working, quietly. And on album rails youâre fetching every albumâs tracklist because someone tapped a heading.
If âplay the whole sectionâ is worth doing it gets an actual play button on the header, reading from real data. Not this.
Besides⌠@ars18 is putting out Zemer Radio soon which I am going to hopefully implement when I have time which will change some structures