AlpineCarver
AlpineCarver

Reputation: 1708

Android browser unloads HTML5 audio element after each play(), causing delay

I have a simple app, which plays a short sound repeatedly, by invoking the play() method on the audio element in JavaScript. It works well on desktop browsers, ipads, iphones, etc. On a mobile device running Android 2.3.3, the first time I play the sound, I hear it immediately after invoking the play() method, but on subsequent invocations, there is a noticeable and variable delay.

I have done some sleuthing and found that the device is fetching the audio file from the server each time the play() method is invoked. I can invoke the load() method on the audio element to re-load it after each play, thus queueing it up for the next play, but there are a number of problems with that band-aid. I'd really like to make the browser just keep the audio element loaded permanently, instead of unloading it as soon as it finishes playing. Does anyone know if that's possible?

EDIT: I've done a little more investigating, and I've found that after playing the sound, the audio element's readystate remains at HAVE_ENOUGH_DATA, even though the browser won't play that sound again without re-fetching it from the server. I believe this is a bug. I'd hoped to use the readystate to detect browsers that unload after playing, and only explicitly load if necessary, but that's not going to work.

Upvotes: 3

Views: 1684

Answers (3)

Adrian Panasiuk
Adrian Panasiuk

Reputation: 7343

You can bind on updatetime to pause() the playback a second before reaching the end of the audio and rewind before playing it again. Android will not flush the audio then.

Upvotes: 0

user914866
user914866

Reputation: 1

best solution i've found. Another options is to just use the video tag but there are some problems with that as well. Nothing seems to work good enough to implement.

luckily im using phone gap so I'll give their audio methods a shot.

Upvotes: 0

AlpineCarver
AlpineCarver

Reputation: 1708

The more experiments I do, the more rough edges I find in Android 2.3.3's implementation of the HTML5 audio tag. There's a lot broken there, at least on the Droid X phone I'm using for testing.

The best I have come up with so far is the band-aid alluded to in my original question: as soon as an invocation of play() completes, invoke the load() method, to prepare for the next play():

if (navigator.userAgent.toLowerCase().indexOf("android") > -1)
  audElt.addEventListener('ended', function () {
    var t = setTimeout(function () { audElt.load(); }, 1000);
  }, false);

I had to restrict the work-around to Android user agents, because simply invoking the load() method creates problems on Chrome and generates unnecessary trips to the server on non-Android systems.

I had to add a 1-sec delay, because if I simply invoked load() from the "ended" handler, it interrupted the playback, which, apparently, hadn't really "ended" yet....

Of course, it's still fetching the sound from the server repeatedly, so if you try to play the sound multiple times in rapid succession, things go south quickly.

Upvotes: 5

Related Questions