"english" Category


Why HTML5 audio/video on iOS is virtually unusable


vrijdag, november 4, 2011

Apple’s Safari on iOS is pretty cool. It has pretty good support for HTML5 audio and video. Unfortunately there’s one big quirk that makes it almost impossible to do anything useful with it. Why? They disabled autoplay. According to the docs this is because:

(…) the user may be on a cellular network and be charged per data unit, preload and autoplay are disabled. No data is loaded until the user initiates it.

In theory, this sounds great. Who doesn’t detest autoplaying advertisements on sites? Unfortunately this ‘feature’ has a few side-effects that cripple the general use of HTML5 audio/video. The autoplay property isn’t the only thing that’s disabled. Playing a HTML5 media element is not possible at all without an user action.

What does this mean in practice? Consider a piece of HTML like this:


<script>
function play() {
var a = new Audio();
a.src = 'http://example.com/audio.mp3';
a.play();
}
</script>

<button onclick="play()">play</button>

This works on iOS because the play() function is initiated from a user action (the click on the button). Now, consider something like this:


<script>
function play() {
var a = new Audio();
a.src = 'http://example.com/audio.mp3';
a.play();
}

setTimeout(play, 3000);
</script>

This doesn’t work on iOS. The play() method is called, but nothing happens because the function is not called from an user action.

Now, you might say, why would you ever want to play a video from a timeout? This example is very simplistic, but consider you’re writing a cross-browser media player that falls back on Flash on Internet Explorer, automatically plays the next track in a playlist, etcetera. You want to write clean code, so everything is modulairized, maybe using a tool like RequireJS and a MVC framework.

This means you’re getting lots of asynchronous callbacks, events, AJAX calls and dozens of functions you’re working with. Your original ‘click’ is lost and your cross-browser player doesn’t work on iOS. Bummer.

Or consider a game with sound effects. Every time you hit an enemy you want to play a sound. I suppose you don’t want to let your user click a button when she wants to hear a sound effect.

Of course, if you just want a simple video player for a blogpost you don’t run into this problem. But for virtually all advanced applications you’re going to run into the autoplay bug sooner or later.

Native iOS apps don’t have this problem, and you can actually disable the autoplay ‘feature’ by putting your web app in a native app (using UIWebView) and disabling the UIWebView.mediaPlaybackRequiresUserAction flag.

On Android this isn’t a problem at all. The code above works fine (tested on 2.3.3).

I think Apple has three possible solutions to ‘fix’ this problem:

  1. Prompt the user to enable autoplay, just like with geolocation
  2. Disable the ‘mediaPlaybackRequiresUserAction’ flag when the device is on WIFI
  3. Remove the ‘feature’ completely

If you’re having this problem as well, you might have some luck submitting a bug report.