Web audio offline in Safari for iOS 6

Original author: Alex Gibson
  • Transfer
  • Tutorial

Playing cached audio offline in Safari under iOS has long been a real challenge, which was considered an unattainable goal . But with the advent of the web audio API (only in WebKit engines), it finally became possible, despite the fact that you still have to take a few steps.

The bad news is that you still won’t be able to cache mp3 files using the application cache and just download them using XmlHttpRequest. Safari for iOS 6 will cache mp3 files, but then silently refuse to play them (very useful!)

Base64 goes to the rescue


Due to the fact that the web audio API provides developers with direct access to the audio buffer , you can change the data format on the fly and transfer them directly to the web audio API for playback. For example, if you encode an mp3 file into a base64 string, then you can then decode it into ArrayBuffer and convert raw audio data.

Audio file encoding


You can easily convert mp3 file to base64 string using OpenSSL . If you are running Mac OS X, where it is preinstalled, just open Terminal.app and enter the following command:

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

Replace [infile] with the path to your mp3 file, and [outfile] with the path to save the encoded data.
The command will save the base64 encoded string representation of the audio file. Then you can cache this line using any web storage of your choice (for example, application cache , local storage or webSQL )

Base64 in ArrayBuffer


To convert base64 to ArrayBuffer, you need to use your solution. Check out Daniele Guerrero's base64-binary.js solution . This is a good script that was created specifically for this purpose. It converts base64 string to Uint8Array and saves it to ArrayBuffer.
After that, you can simply decode the audio data using the honey decodeAudioData()from the web audio API.

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

After transcoding the audio data, transfer it to the audio buffer and play the sound:

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


Demo and source code


Check out the online demo and source code for additional examples of using the technique from this article.

Browser support


Presented demos work under Safari 6, Chrome Desktop and Safari under iOS6. The technique could potentially work in any browser that supports the web audio API, so hopefully Chrome Mobile will soon add support for it.
At the moment, W3C is promoting the web audio API as a standard .

Also popular now: