HTML5 video - currentTime not setting properly on iPhone

拈花ヽ惹草 提交于 2019-12-10 22:58:18

问题


I have a basic html 5 video set up from which I load one of four videos. The problem I'm having is that when I load the next video it continues playing from the previous time position. Efforts to set the currentTime property seem to be either short lived or ignored entirely.

I have added listeners to a collection of events and have something like this in each one;

myPlayer.addEventListener("loadeddata", function() {
        console.log(" loadeddata: before = " + myPlayer.currentTime);
        myPlayer.currentTime = 0.1;
        console.log(" loadeddata: after = " + myPlayer.currentTime);
    }, false);

Sometimes I see the time change for one event but not persist correctly;

durationchange: before = 19.773332595825195
durationchange: after = 0.10000000149011612

loadedmetadata: before = 0.10000000149011612
loadedmetadata: after = 19.773332595825195

loadeddata: before = 19.773332595825195
loadeddata: after = 0.10000000149011612

canplay: before = 0.10000000149011612
canplay: after = 19.773332595825195

And sometimes it never even seems to set at all;

durationchange: before = 50.66666793823242
durationchange: after = 50.66666793823242

loadedmetadata: before = 50.66666793823242
loadedmetadata: after = 50.66666793823242

loadeddata: before = 50.66666793823242
loadeddata: after = 50.66666793823242

canplay: before = 50.66666793823242
canplay: after = 50.66666793823242

This seems similar to the issue here HTML5 video - not setting the current time but there didn't seem to be any resolution. Has anyone encountered this issue on iPhone before?


回答1:


From my findings the issue seems to be that on iPhone only (iPad works fine) the currentTime property will not be set correctly until the "canplaythrough" event, however changing the currentTime at that point will cause a noticeable hiccup. The solution for that would be to intentionally pause the video after calling load...

myVideo.load();
myVideo.pause();        

...and then call play in the event when the time has reset.

The second problem however is when the duration of the new movie is shorter then the currentTime position. In this case not only does currentTime fail to set but "canplaythrough" is never called, and QT just sits at the end of the video doing nothing.

I discovered the solution to both problems was to force a secondary load if the currentTime was not reset in the event BEFORE "canplaythrough". Its a bit round about with the timer callback but it seems to do the trick;

var myVideo = document.getElementById("video1"); 

myVideo.addEventListener("canplay", function() {
    console.log(" canplay: before = " + myVideo.currentTime);
    myVideo.currentTime = 0.1;
    console.log(" canplay: after = " + myVideo.currentTime);

    if( myVideo.currentTime < 1 ) {
        myVideo.play();
    }
    else {
        myVideo.load();
        myVideo.pause();
        setTimeout(checkStarted, 500);
    }
}, false);

function checkStarted()
{ 
    console.log(" checkStarted called");
    myVideo.play();
}



回答2:


TL;DR: change currentTime on the loadeddata event. This works for audio too.

It looks like Safari (and the problem is still appearing for me on Safari 11.1) is Safari will not allow currentTime to be changed when a video is first loaded IF it hasn't loaded a frame for that currentTime yet. The bigger problem: the wrong solution can break Chrome (and likely other browsers too).

Fortunately, we have a lot of events we can listen for while media is loading:

During the loading process of an audio/video, the following events occur, in this order:

  1. loadstart
  2. durationchange
  3. loadedmetadata
  4. loadeddata
  5. progress
  6. canplay
  7. canplaythrough

-W3Schools (I know it's not a preferred source, but I couldn't find the same info on MDN)

I tried adjusting currentTime on different events, but on the first 3 events, Safari would move the time back to 0; and on 5 and 6 it seemed to prevent the video from playing in Chrome, because it would get stuck at currentTime (which I could've worked around, but I thought there was a better solution).

(I didn't want to have to load the whole file to go to the right spot, because I want to support hefty videos. So canplaythrough wasn't an option for me.)

The description for the loadeddata event reads:

The loadeddata event is fired when the first frame of the media has finished loading.

-MDN

When I changed currentTime on loadeddata, Safari could tell that the frame was loaded and available, and would update correctly. It also wouldn't cause Chrome to freeze in a single spot while playing.

The problem and solution are identical for audio.




回答3:


Below is my Angular/Ionic solution to restore the video position. It works on IOS, Android, Chrome and Safari.

HTML:

<video         preload="metadata"
               poster="{{ resource.thumbnail_file }}"
               playsinline webkit-playsinline
               #videos>
...
</video>

Typescript:

@ViewChildren('videos') videos: QueryList<any>;
videoCache: Map<number, number> = new Map<number, number>();

private restoreVideoPositions() {
    var context = this;
    setTimeout(() => {
      this.videos.forEach(function (item, idx) {
        var video = item.nativeElement;
        var currentTime = context.videoCache.get(video.id);

        if (currentTime != null && currentTime > 0) {
          console.log('add listener', currentTime);

          video.addEventListener("loadeddata", function () {
            if (video.readyState >= 3) {
              video.currentTime = currentTime;
              // video.play();
            }
          });
          video.load();
         }
      });
    }, 0);
}

private storeVideoPositions() {
    var context = this;
    this.videoCache.clear()
    this.videos.forEach(function (item, idx) {
      var video = item.nativeElement;
      video.pause();
      context.videoCache.set(video.id, video.currentTime)
    });
  }



回答4:


I used a combination of the last two answers here, but had to reduce the ready state limit to 2 (HTMLVideoElement.prototype.HAVE_CURRENT_DATA) as the loadeddata event on iOS would often never come in higher than 2.



来源:https://stackoverflow.com/questions/18266437/html5-video-currenttime-not-setting-properly-on-iphone

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!