June 7, 2021 (about 2 years ago)
This is a fun one. There appears to be a bug in Mobile Safari’s default HLS implementation when it comes to looping short-form videos.
We’re using the loop attribute so that the video loops (when it reaches the end, it sets back to the beginning and plays again).
Should be easy enough, right? Not quite. We’re seeing a bug at the start of the 3rd loop, the player stutters like this:
This was first reported by Justin Greer on our team when he noticed it on a looping video on the Mux blog, and that’s where this journey began.
As of now (April 2021), if you’re on an iPhone 12+ with iOS 14.3+ you should experience the bug when playing any of the videos. Hit play, let it loop. At the beginning of the 3rd loop you’ll see a visual stutter.
This seems to only happen under these conditions:
Alright, so the problem seems to be with the `loop` attribute specifically. What if we do the looping ourselves by listening for the video end and calling play() programmatically with a 10ms timeout?
Not so easy, unfortunately, that didn’t fix the bug. Nice try though.
Hls.js works great, can we use that instead of relying on Safari’s native HLS support? Unfortunately, we cannot. Hls.js relies on Media Source Extensions, which iOS Safari does not support:
As long as your video is short, the only reasonable solution if you want to get looping working in iOS Safari is to use an mp4 version of the video. You will forgo the advantages of HLS (adaptive bitrate streaming, being able to deliver a quality level that suits your viewer) but at least Mux mp4s are streamable, so the player is able to start playback without downloading the entire file.
MP4 support can be added to Mux Assets at no additional cost. You can then use the low.mp4 or medium.mp4 or high.mp4 file and drop that into the <video> element. The tradeoff you’re making here is that if the user is on a low bandwidth connection they will see a slower startup time compared to if they played one of the lower renditions from the HLS version.
For short videos that are less than a couple of minutes, the fallback to mp4 doesn’t hurt as bad, so this seems like the best option. The tradeoff is that users on low bandwidth connections will have a slower time starting playback, so make sure to use a poster= image on the video element so that the user doesn’t see an empty player while the beginning of the video is downloading.
If you have run into this and found another workaround, we’d love to hear from you. Or if you have dug deeper to understand more of what’s going on please reach out. Right now we’re tracking this in Safari’s bug tracker: https://bugs.webkit.org/show_bug.cgi?id=225136, stay tuned for updates as we learn more.
No credit card to start. $20 in free credits when you're ready.
Vercel's Edge Config can come in handy in many different ways. See how we used it to cut down on the amount of spam we were dealing with from our forms.
By Justin Sanford
With lazy-loading and a blurhash placeholder, we make the loading experience of Mux Player feel great in our Next.js app
By Darius Cepulis
While hunting for a pesky live streaming bug, we discovered that virtual load balancers don’t always simulate their physical counterparts the way you might expect.
By Dmitry Ilyevsky