Taking Web Audio Offline in iOS 6 Safari

Playing cached audio for offline use on iOS Safari has long been a challenge that has proved to be mission impossible. But with the advent of the (WebKit-only) Web Audio API, it is now finally achievable — although you still need to jump through a few hoops.

The bad news is that you still can’t cache an MP3 file using Application Cache and then simply load it using an XmlHttpRequest. Safari on iOS 6 will cache the MP3 but then refuse to play it and fail silently (how useful!).

But all is not lost…

Base64 to the Rescue

Because the Web Audio API offers developers direct control over the AudioBuffer, you can now convert data formats on-the-fly and feed them directly to the Web Audio API for playback. For example, if you encode an MP3 file as a Base64 string, you can then decode it to an ArrayBuffer and convert the raw audio data.

Encoding an Audio File

You can easily convert an MP3 file to a Base64 string using OpenSSL. If you are on Mac OS X, it comes pre-installed, so just open up Terminal.app and type the following command:

openssl base64 -in [infile] -out [outfile] 

Make sure to replace [infile] with the path to your MP3 and [outfile] with your chosen destination for the encoded data.

This will output a Base64-encoded string representation of your sound file. You can then cache the string using any form of web storage you choose (e.g., Application Cache, localStorage, or webSQL).

Base64 to ArrayBuffer

In order to decode the Base64 string back into an ArrayBuffer, you’ll need to use a custom method. Check out Daniele Guerrero’s base64-binary.js as a good script that can be used exactly for this purpose. It decodes a Base64 string into a Uint8Array typed array and stores it in an ArrayBuffer.

Once this is done, you can simply decode the audio data using the Web Audio API’s decodeAudioData() method:

var buff = Base64Binary.decodeArrayBuffer(sound);  myAudioContext.decodeAudioData(buff, function(audioData) {   myBuffer = audioData; }); 

Once you have the audio data decoded, pass it to your audio buffer source and play the sound:

mySource = myAudioContext.createBufferSource(); mySource.buffer = myBuffer; mySource.connect(myAudioContext.destination); mySource.noteOn(0); 

Full Demo and Source Code

Check out the online demo and source code for a complete example of the techniques discussed in this article.

Browser Support

Currently the demo works in Safari 6, Chrome Desktop, and iOS 6 Safari. The technique has potential to work in any browser that supports Web Audio API, so hopefully Chrome Mobile can soon add support as well.

The W3C is currently pursuing the Web Audio API as a standard.

Taking Web Audio Offline in iOS 6 Safari originally appeared on HTML5 Doctor on November 27, 2012.

HTML5 Doctor

[plinker]

PHP

AudioOfflineSafariTaking

Leave a Reply

Your email address will not be published. Required fields are marked *