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.
Here’s an example of some code that will play an HLS video. Note that because we are setting the
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.
The first culprit seemed like something weird going on with the react component, so we started peeling back those layers. That didn’t help so then we went to plain ‘ol html
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.
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
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.