html5 audio: distingish NotAllowedError and NotSupportedError

Both latest Chrome and Firefox do pass a reason to the rejected promise, you could thus check it.

new Audio("bafile.mp3").play().catch(console.log)

But note that they didn’t always did.
Also note that the NotAllowedError will always win: even if the resource can’t be loaded, it is the reason that will get output.

So an other solution, able to distinguish between both and that will work even in prior versions that didn’t have this rejection message, would be to wait for whatever is the first to fire between the loadedmetadata and error events. If one of these fires, you know it failed because of a NotAllowedError or because of a NotSupportedError respectively.

function test( url ) {

  const aud = new Audio( url );
  const event_prom = Promise.race( [
    promisifyEvent( aud, "error" ),
    promisifyEvent( aud, "loadedmetadata" )
  ] );
  
  aud.play()  
    .then( () => {
       log.textContent += "\nERROR: " + url + " was authorized to play";
    } )
    .catch( async (reason) => {
        const evt = await event_prom;
      if( evt.type === "error" ) {
        log.textContent += "\n" + url + ": network error";
      }
      else {
        log.textContent += "\n" + url + ": not authorized";
      }
    });
}
test( "https://upload.wikimedia.org/wikipedia/en/transcoded/d/dc/Strawberry_Fields_Forever_%28Beatles_song_-_sample%29.ogg/Strawberry_Fields_Forever_%28Beatles_song_-_sample%29.ogg.mp3" );
test( "badfile.mp3" );

function promisifyEvent( target, event_name ) {
  return new Promise( (resolve) =>
    target.addEventListener( event_name, resolve, { once: true } )
  );
}
<pre id="log"></pre>

As a jsfiddle since it might be easier to control the authorizations.

CLICK HERE to find out more related problems solutions.

Leave a Comment

Your email address will not be published.

Scroll to Top