简体   繁体   中英

Setting currentTime for HTML5 video window.onscroll is lagging

I'm trying to set the currentTime for the html5 video on window scroll event. Basically the idea is to move forward or backward in the video timeline as you scroll the page.

This example here is doing it nicely without a problem: http://codepen.io/ollieRogers/pen/lfeLc

Here is the code:

 // select video element var vid = document.getElementById('v0'); //var vid = $('#v0')[0]; // jquery option // pause video on load vid.pause(); // alternative & optimized implementation thanks to http://codepen.io/daveroma/ window.onscroll = function(){ vid.currentTime = window.pageYOffset/400; };
 #set-height display block height 13500px #v0 position fixed top 0 left 0 width 100% p font-family helvetica font-size 24px
 <div id="set-height"></div> <p id="time"></p> <video id="v0" tabindex="0" autobuffer="autobuffer" preload="preload"> <source type="video/webm; codecs=&quot;vp8, vorbis&quot;" src="http://www.html5rocks.com/tutorials/video/basics/Chrome_ImF.webm"></source> <source type="video/ogg; codecs=&quot;theora, vorbis&quot;" src="http://www.html5rocks.com/tutorials/video/basics/Chrome_ImF.ogv"></source> <source type="video/mp4; codecs=&quot;avc1.42E01E, mp4a.40.2&quot;" src="http://www.html5rocks.com/tutorials/video/basics/Chrome_ImF.mp4"></source> <p>Sorry, your browser does not support the &lt;video&gt; element.</p> </video>

But when I try it with my own video, the video lags: http://codepen.io/futurecrazy/pen/ZWGYBj

Here is my code:

 // select video element var vid = document.getElementById('v0'); //var vid = $('#v0')[0]; // jquery option // pause video on load vid.pause(); // alternative & optimized implementation thanks to http://codepen.io/daveroma/ window.onscroll = function(){ vid.currentTime = window.pageYOffset/400; };
 #set-height display block height 13500px #v0 position fixed top 0 left 0 width 100% p font-family helvetica font-size 24px
 <div id="set-height"></div> <p id="time"></p> <video id="v0" tabindex="0" autobuffer="autobuffer" preload="preload"> <source type="video/webm" src="http://philippsokolov.com/fm-4.webm"></source> <source type="video/ogg" src="http://philippsokolov.com/fm-4.ogv"></source> <source type="video/mp4" src="http://philippsokolov.com/fm-4.m4v"></source> <p>Sorry, your browser does not support the &lt;video&gt; element.</p> </video>

I've tried different video compressions but still cant fix the issue.

Would appreciate any help.

I experienced the exact same thing — what a pain to solve, After poking around, I noticed that the video would only visibly change once the seeked event had fired. Evidently, every time you update currentTime (in my case, on any scroll event), it kicks off a new seeking process, which delays the rendering of the new currentTime until a seeking process is resolved.

I fixed it by listening for the seeking and seeked events, and only updating currentTime if the video is not currently seeking — let the seeking process finish, so the updates don't just keep piling up.

Here's the relevant bits of my script:

let seeking = false;

heroVideo.addEventListener('seeking', function() {
    seeking = true;
});

heroVideo.addEventListener('seeked', function() {
    seeking = false;
});

function tick(lastKnownScrollPosition) {
    if (!seeking) heroVideo.currentTime = lastKnownScrollPosition / 300;
}

let ticking = false;

window.addEventListener('scroll', function(e) {
  const lastKnownScrollPosition = window.scrollY;

  if (!ticking) {
    window.requestAnimationFrame(function() {
      tick(lastKnownScrollPosition);
      ticking = false;
    });

    ticking = true;
  }
});

I ran into a similar problem, the issue was the video encoding.
Having a low video keyframe rate causes the lag.

My guess is that changing video.currentTime makes the browser's video decoder search for the closest keyframe to the specified time position, and this can take a while on videos with rare keyframes. Reencoding the video with higher keyframe rate fixed the problem for me.

Note that keyframe spacing can be controled with FFMPEGs -g flag.

Configuring Video Streams for Seeking Performance

I was doing the same thing, but was unable to achieve a usable level of performance using HTML5 <video>. There are unfortunately no supported codecs that do intraframe compression, so seeking is just unfortunately going to be expensive if you're using HTML5 video.

Instead I extracted the frames from the video with ffmpeg and tar'd them. Then, on the browser side, I fetched the tar, used js-untar to extract the individual JPGs. From there it's straightforward to manually change the image source on an tag, or use a canvas, to animate the video.

Here's what that looks like:

  let images = [];

   fetch("assets/launch.tar").then(response => {
       return response.arrayBuffer();
   })
       .then(buffer => untar(buffer))
       .then(files => {
           files.forEach((file) => {
               let img = new Image();
               img.src = file.getBlobUrl();
               images.push(img);
           });
       });

   let div = document.getElementById("yourDiv");


   let frame = () => {
       let scrolled = (document.documentElement.scrollTop + document.body.scrollTop) / (document.documentElement.scrollHeight - document.documentElement.clientHeight);
       let currentFrame = Math.floor(scrolled * (images.length - 1));
       let img = images[currentFrame];
       img.decode().then(() => {
           div.style.backgroundImage = `url(${img.src})`;
       });
       window.requestAnimationFrame(frame);
   }
   window.requestAnimationFrame(frame);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM