Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS Safari - Playing media element (from click) with delay - NotAllowedError

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;
like image 752
Joe Weitzel Avatar asked Nov 17 '22 04:11

Joe Weitzel


1 Answers

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)

like image 89
Joe Weitzel Avatar answered May 16 '23 05:05

Joe Weitzel