Dealing with HTML5 Video on Mobile Devices

Web video has never been a cakewalk, but at least in the days when Flash was your only option you could pretty well guarantee it’d work everywhere. This is no longer the case. We’ve gotten to the point where you can easily use H.264 as your only option (with HLS if you’re including your videos in an iOS app) but there are still loads of quirks in playback. Each browser’s implementation of HTML5 video is slightly different – mobile devices throw in additional variance. And of course IE8 and some versions of Firefox (when using H.264 at least) still require Flash for playback.

Fortunately, we’re able to use amazing open-source libraries such as Video.js to smooth out most of this for us, in particular the change in tech from HTML5 to Flash where necessary (looking at you IE8). However even with Video.js I’ve found myself having to work around a lot of variation on mobile devices. Below are some quick notes on what I’ve seen and how I have or haven’t been able to work around it.

iOS Quirks

  • iOS loves to show this incredibly attractive QuickTime logo to let you know it’s a video. It seems to do this when the video is not in a loaded state; thus, you see it on initial load. If you want to hide this bit of ugliness from the user you can push the element offscreen before it starts loading by setting in CSS its position to absolute and its left or top to something way off screen (i.e. -10000px). Once the metadata is loaded you can bring it back and on screen with no QuickTime logo. You need to push it off screen because anything to truly hide it (i.e. display: none or visibility: hidden) will cause the video to not load.
  • Another way to get the QuickTime logo is to let it run to the end of the video. To avoid seeing it after the video ends I’ve set up a listener for the timeupdate event and made the video pause when it approaches the duration. This way the user sees one of the final frames instead of the QuickTime logo when the video “ends”.
  • No autoplay unless embedded in a native app’s custom WebView.
  • On iPhone there’s no way to not go full screen unless embedded in a native app’s custom WebView.

Android 4 Quirks

  • No autoplay unless embedded in native app’s custom WebView.
  • On the default Android 4 browser (not Chrome), you need to tap on the actual video to get it to start. You can overlay another element (i.e. a giant play button) on it and have the click event for it start playback but what you see is it tries to start it and then immediately pauses it. You are able to put a poster on a video but depending on your application’s design this can be kind of confusing as it can just look like an image. There’s no indication to tap on it to start the video. Sadly, we’ve found the best solution to this to be no poster. It lets the Android equivalent of the iOS QuickTime logo show through. Not pretty but at least the user knows to tap on the video to get it started.
  • On the default Android 4 browser (not Chrome) once you’ve started a video in a tab if you leave that tab it can no longer be used again. You must refresh the page. This means if you leave the tab to another tab or leave the browser for the home screen or another app your app basically breaks. I think this is unfixable from a web developer’s perspective as even YouTube works this way. Pretty awful though.

Browser-Level Volume Control Feature Detection
iOS doesn’t allow for you to mute using the HTML5 video api’s mute function. You can call it but it won’t work. Fortunately it doesn’t work in a way that allows us to sniff it out without having to rely on user agents.

The following gist shows how you can check if volume control will work. It’s setup with Video.js in mind but it’ll work with the HTML5 video api as well.

The final key to volume control is that on Android 4 setting the volume prior to playing the video doesn’t work. If you want your volume to persist across videos on your website you’ll need to set it after the video starts playing as otherwise it’ll disregard what you had set the volume to. Thus, wait until you receive the initial ‘playing’ event from the video and then immediately set the volume.

In my experience on both desktop browsers as well as mobile browsers you never hear the volume change (even if what you’re doing it muting the volume) because the change is done so quickly after the browser starts playing the video.