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:
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:
Once you have the audio data decoded, pass it to your audio buffer source and play the sound:
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.
[plinker]