Cameron
Cameron

Reputation: 2965

video will not autoplay on chrome when it is inserted into the DOM

I have a video (meant for background purposes), that is muted and I intend to auto-play. If I were to put the following code into an html file:

<video playsinline autoplay muted loop>
  <source src="https://res.cloudinary.com/dthskrjhy/video/upload/v1545324364/ASR/Typenex_Dandelion_Break_-_Fade_To_Black.mp4">
</video>

It would work just fine on Chrome.

However, If I were to insert the exact same video using DOM manipulation, I would have trouble on Chrome but success in other browsers like Firefox.

<html>
<body>
</body>
<script>
  function render() {
    const video = document.createElement('video');
    video.setAttribute('muted', true);
    video.setAttribute('autoplay', true);
    video.setAttribute('loop', true);
    video.setAttribute('playsinline', true);

    const source = document.createElement('source');
    source.setAttribute('src', 'https://res.cloudinary.com/dthskrjhy/video/upload/v1545324364/ASR/Typenex_Dandelion_Break_-_Fade_To_Black.mp4');

    video.appendChild(source);
    document.body.appendChild(video);
  }
  render();
</script>    
</html>

Chrome appears notorious for blocking autoplay. The general solutions are either to be muted (which I already do), or to use dom manipulation to call play (which doesn't work). Is there a way to get this to work after inserting the video into the dom. The reason I care is because my actual website requires everything to be rendered (My site is in ember.js).

This is in Chrome version 71.

Thanks!

Upvotes: 2

Views: 1937

Answers (2)

zer00ne
zer00ne

Reputation: 43880

Async, Await, & IIFE

After finding this article a couple of months ago, I still couldn't get a consistent autoplay behavior, muted or otherwise. So the only thing I hadn't tried is packing the async function in an IIFE (Immediately Invoked Function Expression).

In the demo:

  • It is dynamically inserted into the DOM with .insertAdjacentHTML()

  • It should autoplay

  • It should be unmuted

  • All of the above should happen without user interaction.


Demo

var clip = document.getElementById('clip');

(function() {
  playMedia();
})();

async function playMedia() {
  try {
    await stamp();
    await clip.play();
  } catch (err) {
  }
}

function stamp() {
  document.body.insertAdjacentHTML('beforeend', `<video id='clip' poster='https://image.ibb.co/iD44vf/e2517.jpg' src='https://storage04.dropshots.com/photos8000/photos/1381926/20181019/182332.mp4' width='100%' autoplay loop playsinline></video>`);
}

Upvotes: 0

Kaiido
Kaiido

Reputation: 136678

This is probably a bug (and not the only one with this autoplay policy...).

When you set the muted attribute through Element.setAttribute(), the policy is not unleashed like it should be.

To workaround that, set the IDL attribute through the Element's property:

function render() {
  const video = document.createElement('video');
  video.muted = true;
  video.autoplay = true;
  video.loop = true;
  video.setAttribute('playsinline', true);

  const source = document.createElement('source');
  source.setAttribute('src', 'https://res.cloudinary.com/dthskrjhy/video/upload/v1545324364/ASR/Typenex_Dandelion_Break_-_Fade_To_Black.mp4');

  video.appendChild(source);
  document.body.appendChild(video);
}
render();

As a fiddle since StackSnippets requiring a click event form the parent page are anyway always allowed to autoplay ;-).

Upvotes: 9

Related Questions