mardi 4 juin 2019

How to play video with sound on user-initiated event before video element is added to DOM? iOS Safari/Chrome/Webkit

I have two elements in the DOM: 1) Viewer Window (shows a large image or video) 2) grid of thumbnails (representing videos or images).

When the user clicks on the corresponding thumbnail for a video, the video should load into the viewer window and begin playing with sound on mobile/ios/android. I am testing specifically on iOS safari.

I am aware of the webkit policies on user-initiated events, requiring videos to be muted unless the user explicitly clicks on things (which is the action I am doing here), but am having troubles understanding the specific implementation details.

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.

I believe the issue for me is that the video element is not added to the dom until the next render loop. Even though the user is initiating the event by clicking on the thumbnail to play the video, webkit isn't recognizing it as a user-initiated event and blocking playing the video because it has sound.

User Click:

    updateCurrentItem(item) {
      set(this, "currentItem", item);

      this.videoManager.playWhenLoaded.perform(item);
    }

videoManager.playWhenLoaded is an ember-concurrency task. When a video is loaded to the dom, it registers itself with the videoManager service.

  playWhenLoaded: task(function*(item) {
    let id = item.id;
    while (this.videos.findBy("modelId", id) === undefined) {
      yield timeout(200);
    }

    let video = this.videos.findBy("modelId", id);
    video.player.muted = false;
    video.player.play();
  })

Could you please explain to me why this doesn't work? and what strategies might I attempt to get it to work for my use-case?




Aucun commentaire:

Enregistrer un commentaire