Programmatically play video with sound on Safari and Mobile Chrome

Yes, you can bind on event that are not directly ones triggered on the video element:

btn.onclick = e => vid.play();
<button id="btn">play</button><br>
<video id="vid" src="https://dl.dropboxusercontent.com/s/bch2j17v6ny4ako/movie720p.mp4"></video>

So you can replace this button with any other splash screen requesting an user click, and you’ll be granted access to play the video.

But to keep this ability, you must call at least once the video’s play method inside the event handler itself.

Not working:

btn.onclick = e => {
  // won't work, we're not in the event handler anymore
  setTimeout(()=> vid.play().catch(console.error), 5000);
  }
<button id="btn">play</button><br>
<video id="vid" src="https://dl.dropboxusercontent.com/s/bch2j17v6ny4ako/movie720p.mp4"></video>

Proper fix:

btn.onclick = e => {
  vid.play().then(()=>vid.pause()); // grants full access to the video
  setTimeout(()=> vid.play().catch(console.error), 5000);
  }
<button id="btn">play</button><br>
<video id="vid" src="https://dl.dropboxusercontent.com/s/bch2j17v6ny4ako/movie720p.mp4"></video>

Ps: here is the list of trusted events as defined by the specs, I’m not sure if Safari limits itself to these, nor if it includes all of these.


Important note regarding Chrome and preparing multiple MediaElements

Chrome has a long-standing bug caused by the maximum simultaneous requests per host which does affect MediaElement playing in the page, limiting their number to 6.

This means that you can not use the method above to prepare more than 6 different MediaElements in your page.

At least two workarounds exist though:

  • It seems that once a MediaElement has been marked as user-approved, it will keep this state, even though you change its src. So you could prepare a maximum of MediaElements and then change their src when needed.
  • The Web Audio API, while also concerned by this user-gesture requirement can play any number of audio sources once allowed. So, thanks to the decodeAudioData() method, one could load all their audio resources as AudioBuffers, and even audio resources from videos medias, which images stream could just be displayed in a muted <video> element in parallel of the AudioBuffer.

Leave a Comment