goldfire / howler.js

Javascript audio library for the modern web.
https://howlerjs.com
MIT License
24.01k stars 2.23k forks source link

onplayerror not firing (2.1.2) #1176

Open indexofrefraction opened 5 years ago

indexofrefraction commented 5 years ago

using the code from the documentation i can not get onplayerror to fire

with example below / on safari and chrome desktop: audio play is denied, but onplayerror does not fire the sound then plays with the first touch/click (onplay is fired)

var sound = new Howl({
    src: ['blank.webm', 'blank.mp3'],
    onplay: function() {
        console.log('audio playing!');
    },
    onplayerror: function() {
        console.log('audio play denied!');
        sound.once('unlock', function() {
            console.log('audio play unlocked!');
        });
    }
});
sound.play();

ps. as playing limitations affect all mayor browsers now, maybe the error messages could be updated (line 898 and 917)

indexofrefraction commented 5 years ago

this code is a bit clearer, and i also noticed :

for safari / chrome desktop and safari ios : this code is enough to unlock audioplay by a click anywhere in the document

for chrome android: this does not work, i could not get a consistent behaviour on a huawei p20, but i think the playback must be invoked inside a click/touch event !

an audio file is actually not needed, the Howl needs a format in this case, tough.

as mentioned above, at least on the destop, onplayerror does not get executed

var sound = new Howl({
    src: [''], format: ['mp3'], 
    autoplay: true,
    onplay: function() {
        console.log('audio playing!');
    },
    onplayerror: function() {
        console.log('audio play denied!');
    },
    onunlock: function() {
        console.log('audio play unlocked!');
    },
});
jevinsidhu commented 5 years ago

Is anyone addressing this? I can't get onplayerror to fire when Chrome blocks the Audio Context.

goldfire commented 5 years ago

There is currently no way to detect that the audio is locked. There are some proposals in the works, but the progress seems to be moving slowly. I submitted a bug to Chromium that got marked as wontfix when the promise from a play just hangs if the audio is blocked, which seemed like it would be the logical place to catch in that scenario, rather than just doing nothing.

jevinsidhu commented 5 years ago

Thanks for the detailed answer - appreciate your work. @goldfire

vvvhung commented 5 months ago

It still not work. But with html5 audio, we have 2 ways: Method 1: On Suspend Event: audio.addEventListener('suspend', function(){})

Method 2: Catch play()

async audioPlay(audio) {
  var canPlay = true
  await new Promise(async (resolve) => {
    audio.onended = resolve
      audio.play().catch(error => {
        canPlay = false
        resolve()
      })
  });
  return canPlay
}