1

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!

Cameron
  • 2,805
  • 3
  • 31
  • 45
  • Works for me in Chrome Version 71.0.3578.98 (Official Build) (64-bit) – Kosh Jan 18 '19 at 02:11
  • that's really strange. I have the exact same version and the exact same code but have this problem – Cameron Jan 18 '19 at 02:14
  • @KoshVery - right click on the tab and select "Mute Site", then reload the page. Won't play. If the user turns off autoplay there is nothing you can do to enable it. – Randy Casburn Jan 18 '19 at 02:15
  • While this is true, I find that even with Mute Site disabled I cannot get it to autoplay. There must be something else going on... – Cameron Jan 18 '19 at 02:17
  • For the ones able to autoplay on Chrome (e.g @KoshVery) , you probably had an interaction with the page (e.g if you tried from jsfiddle, just interacting with the parent page counts as interaction). Here is a [live example](http://jsfiddle.net/6joan7dc/), be sure to not click anywhere when the page loads. Can repro on 71 and 73, both on macOs – Kaiido Jan 18 '19 at 02:21
  • @RandyCasburn, thanks, reproduced when page's muted. – Kosh Jan 18 '19 at 02:28

2 Answers2

8

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 ;-).

Kaiido
  • 123,334
  • 13
  • 219
  • 285
  • I like this answer a lot and will look at it tomorrow morning and probably then award best answer if it works – Cameron Jan 18 '19 at 02:31
  • +1 Using on all type of dynamically creaded element will automatically assign to compatible Elements while don't on others. – eapo May 08 '23 at 21:46
  • Came across this answer as in my case videos are not playing synchronously. Didn't realize the `muted` attribute is causing the issue! – lqi Jun 30 '23 at 00:55
0

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>`);
}
Community
  • 1
  • 1
zer00ne
  • 41,936
  • 6
  • 41
  • 68