iOS Safari requires a touch event to play/pause media elements. Without, you get the:
NotAllowedError: The request is not allowed by the user agent or the platform in the current context, possibly because the user denied permission. caught promiseReaction error message.
The question is "How to delay the <MediaElement>.play() call without loosing the touch event context??"
I'm trying to play a media element with a delay after the click, but in the two methods I've come up with (Promise & setTimeout), they both loose the connection to the touch event and I get the NotAllowedError error due to the scope change of the <MediaElement>.play() call. Both work on all ES6 devices/browsers other than iOS Safari, as expected.
Feel free to play with it here on codepen.
const delay = ms => new Promise(res => setTimeout(res, ms));
const video = document.querySelector('video'),
button = document.querySelector('button')
const playVideoSyncDelay = async e => {
document.body.classList.add('blackground')
await delay(3000)
video.play()
.then( e => video.onended = e => document.body.classList.remove('blackground', 'playing') )
.then( e => document.body.classList.add('playing') )
.catch( e => console.error('Oops:', e) )
}
const playVideoTimeoutDelay = e => {
document.body.classList.add('blackground')
setTimeout(e => {
video.play()
.then( e => video.onended = e => document.body.classList.remove('blackground', 'playing') )
.then( e => document.body.classList.add('playing') )
.catch( e => console.error('Oops:', e) )
}, 3000, e)
}
/**
BOTH BELOW RESULT IN DELAYED NotAllowedError: ...not in the current context...
**/
//button.onclick = playVideoTimeoutDelay;
button.onclick = playVideoSyncDelay;
If the user calls .load() before the delayed .play(), they can delayed play on mobile browsers.
Here is a codepen:
https://codepen.io/joeweitzel/pen/RwJVBNL
$media.load(); $setTimeout(()=>$media.play, 2000)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With