I am currently developing an audio editing application for firefox OS (github). That uses, for playback, Howler JS (link).
On Firefox OS, I can easily play audio files which are within the application folder (does not matter where) only by passing an URL to Howler, but, if I want to create new audio files (recording audio), I then need to save them somewhere on the internal memory.
The problem is : Howler js does not support playback of blob files (even when I try to get the URL - window.URL.createObjectURL(blob)).
Is there a way to save the files the app creates directly withing the application folder? (So I will be able to reference them using an url?)
If not, what's a good way to go?
Any file that is packaged in the app can be accessed using a relative url. Which means you don't have to get a blob or anything.
It won't be possible to save assets (at runtime) in the app folder as far as I can tell. The only way to access the app folder requires you to have the webapp-manage
permission and that your application has to be certified.
It's unlikely that Howler.js
doesn't work with blob urls as they are not much different from any other url. There might be a bug in FirefoxOS though.
From the documentation, it is said that you should use the "format" property to set the file format of the url if it isn't possible to get it from the url
var sound = new Howl({
urls: [URL.createObjectUrl(blob)],
format: 'mp3',
....
})
As a side note, I have to say that for each use of URL.createObjectUrl(blob)
, you should also call URL.revokeObjectUrl(url)
. I haven't read much about it but as I understand, the browser will keep the blob in memory as long as the url isn't revoked. Each call to the createObjectUrl
method will create a new URL that reference to the blob. In order to free the blob, you'll have to free also all urls.
From the documentation, the urls won't be revoked by themselves... Which means that if you loose a reference to a URL you previously created, your web application will leak memory as the blob won't get freed unless the unload
event is called on the document.
So as you write your application, I'd suggest creating a pool of URLs that you can manage.
function UrlPool() {
this.assets = new Map()
}
UrlPool.prototype.getUrl = function (asset, blob) {
var url = this.assets.get(asset)
if (!url) {
url = URL.createObjectUrl(blob)
this.assets.set(asset, url)
}
return url
}
UrlPool.prototype.removeUrl = function (asset) {
var url = this.assets.get(asset)
if (url) {
URL.revokeObjectUrl(url)
this.assets.delete(asset)
}
}