McLovin
McLovin

Reputation: 1601

Videos do not autoplay with audio after user gesture

I have a simple webpage with multiple <video> elements within different slides in a carousel. When a video is in the active slide in the carousel I am .play()ing the video and .pause()ing all others. I want the videos to autoplay off of mute and am fully aware of each browser's autoplay policies, however even after a user has interacted with the webpage (by pausing/playing/unmuting the first video that plays) any subsequent videos will not play off of mute because of the error:

The request is not allowed by the user agent or the platform in the current context, possibly because the user denied permission.

What is the proper way to enable videos to play off of mute after the user has interacted with the page?

I have created a codesandbox to reproduce the issue.

      var vid1 = document.getElementById("video1");
      var vid2 = document.getElementById("video2");
      var vid3 = document.getElementById("video3");

      carousel.on("slideChange", function () {
        vid1.currentTime = 0;
        vid2.currentTime = 0;
        vid3.currentTime = 0;
        vid1.pause();
        vid2.pause();
        vid3.pause();

        if (carousel.activeIndex === 0) {
          var currentVideo = vid1;
          var prevVideo = vid3;
        } else if (carousel.activeIndex === 1) {
          var currentVideo = vid2;
          var prevVideo = vid1;
        } else {
          var currentVideo = vid3;
          var prevVideo = vid2;
        }

        currentVideo.volume = 1;
        currentVideo
          .play()
          .catch((e) => {
            console.error(`Error playing: ${e.message}`);
            currentVideo.muted = true;
            return currentVideo
              .play()
              .catch((err) => console.error("Error caught again", err.message));
          })
      });

Some additional observations:

Upvotes: 2

Views: 1139

Answers (2)

hoodie
hoodie

Reputation: 1

First set the video to muted=true, then add a touchstart event to set the video to muted=false

Upvotes: 0

McLovin
McLovin

Reputation: 1601

The issue was that we were listening for the touchend event, after a touchmove, which is the gesture registered when swiping. But this is not registered as a user gesture allowing autoplay on iOS.

User gestures that should allow autoplay are defined in the spec. Through my testing, I have identified that the only user gestures that allow autoplaying include click, pointerup, and mouseup. touchend also works when fired after a click, but not after a touchmove.

It's also important to understand how to handle user gestures properly as defined by the Safari team:

A note about the user gesture requirement: when we say that an action must have happened “as a result of a user gesture”, we mean that the JavaScript which resulted in the call to video.play(), for example, must have directly resulted from a handler for a touchend, click, doubleclick, or keydown event. So, button.addEventListener('click', () => { video.play(); }) would satisfy the user gesture requirement. video.addEventListener('canplaythrough', () => { video.play(); }) would not.

Upvotes: 3

Related Questions