I'm seeing a problem with preload: true in Safari 12.
Calling play() while a file is preloading leaves things in a strange state where playback doesn't happen in the browser, but Howler thinks it is playing:
> Howler._howls[3].state()
< "loaded"
> Howler._howls[3].playing()
< true
> Howler._howls[3]._playLock
< false
> Howler._howls[3]._sounds[0]._node.readyState
< 4
From what I can tell
1) Enabling "Auto-Play" in Safari for the website in question fixes the behavior.
2) Making a manual call before play to Howler._enableMobileAudio() doesn't help (#1047 doesn't fix it)
3) Things work as expected if play() is called after the song is in a loaded state.
4) Things work as expected if the user manually clicks somewhere on the page before clicking the play button
5) onplayerror throws Playback was unable to start. This is most commonly an issue on mobile devices and Chrome where playback was not within a user interaction.
6) I've confirmed my play button event propagates via document.addEventListener('click')
Ran into this as well
Running into this too. Fine in Safari 11.x, started with Safari 12.
In my scenario, I have different ways to trigger playback: via a list of HTML links or via some SVG graph that gives info about each audio file. Clicking the links appears to be without effect (though the click events do propagate). Meanwhile, clicking the SVG links work same as before. Once I click an SVG link, it also plays back anything I tried to play earlier with the HTML link, as if releasing some sort of queue.
I'm unclear yet how Safari decides which user interactions are OK to honor right away and which ones are not. It's getting late here and will investigate some more tomorrow.
Hints welcome if anyone else got it to work.
(Firefox and Chrome are fine. Chrome does show this in the console The Web Audio autoplay policy will be re-enabled in Chrome 70 (October 2018). Please check that your website is compatible with it. https://goo.gl/7K7WLu so maybe this will become a concern in Chrome too.)
EDIT: using fork #1047 actually fixed it for me.
I'm unclear yet how Safari decides which user interactions are OK to honor right away and which ones are not. It's getting late here and will investigate some more tomorrow.
@fabwt Are you preloading? There's some detail hidden in this blog article: the https://webkit.org/blog/7734/auto-play-policy-changes-for-macos/ The summary is that each HTML5 audio tag has to be unlocked on a per element basis (so clicking won't unlock each track). That translates to: a node.play() has to occur within a click/touch. If you want to unlock multiple elements, you'll need to .play() each element you potentially want unlocked, or swap out the src of the already unlocked audio tag.
I'm working on a new and clean ES6 solution for https://alonetone.com/ with a limited feature set. I'm not sure yet how/if I will extract it as I don't plan on supporting/maintaining anything other than continuous playback of mp3s in a playlist. But I'll link it here once it's committed to http://github.com/sudara/alonetone
EDIT: Whups, just saw that #1047 worked for you. Does that mean you are using the web audio API and not HTML5? I didn't have luck with that fix...
I still have issues in Safari 12 when 'Stop Media With Sound' is enabled.
Expected behaviour:
You surf to the website, audio starts to play.
You click on a button, another audio starts to play.
Current behaviour in Safari 12
You surf to the website. Nothing is playing but playing() gives true. So I don't hear anything but the howler playing func. gives back 'true'. But this audio.on('play') is not fired.
const sound = new Howl({
src: [`${baseUrl}/assets/audio/${lang}/guides.mp3`],
sprite: sprite,
onload: () => {
window.audio = sound
commit('setAudioLoaded', { loaded: true })
}
})
if (this.$route.name === 'Home') {
this.audio = window.audio
this.currentAudioId = this.currentPage.audio[0].id
/* Function Never Fired */
// this.audio.onplayerror = () => {
// console.log('play error')
// this.audio.once('unlock', () => {
// this.audio.play(this.currentAudioId)
// })
// }
/* Function Never Fired */
this.audio.on('playerror', function () {
this.audio.once('unlock', () => {
this.audio.play(this.currentAudioId)
})
})
/* Function fired, but doesn't stop the first audio */
this.audio.on('stop', function (id) {
console.log('on stop')
console.log(id)
})
this.audio.play(this.currentAudioId)
},
@sudara yes, I'm using the WebAudioAPI by default.
@katiasmet did you try with this pull https://github.com/goldfire/howler.js/pull/1047 ?
@fabswt I updated my Howler version but the 'on play error' function is never called.
I 'fixed' it with a dirty fix for now. So that he doesn't play the first audio when it is Safari 12.
I also don't have a 'play' button. The first audio should play automatically and if it doesn't, it should play the second audio on click.
if (this.getBrowser() !== 'Safari 12') {
this.audio.play(this.currentAudioId)
}
Edit: Ok now I bummed into another problem with no workaround.
It's on another page. Where I load howler by clicking on a playbutton, but it doen's play when hitting the play function after loading it.
The playing() issue is fixed in master and will be released in an update soon.
Most helpful comment
The
playing()issue is fixed in master and will be released in an update soon.