将暂停的视频帧捕获到画布的最佳方法

时间:2018-04-24 02:14:17

标签: javascript scroll html5-canvas html5-video pause

我知道如何逐帧复制从播放HTML5视频到使用2D上下文的画布。

但我希望使用暂停的视频,将其currentTime改为动态,并将当前视频帧复制到画布。

我的猜测是,当视频位置设置为currentTime属性时,某些进程尚未被调用,尽管视频本身确实更新了它显示的图像(但不是更新到画布)。

我发现通过在下一步中设置setTimeout来执行画布'drawImage'来克服这个问题是可行的。

You can see here a jsfiddle that proves the point

正如您可以在小提琴中看到的那样,您可以播放视频和画布更新,但如果您暂停视频,鼠标滚动会移动currentTime视频。在那里,如果我直接调用drawImage方法,画布不会更新,则需要'timeTimeout'来更新画布。

简而言之,我的问题是:

有更好的方法吗?没有setTimeout和内部de循环本身可以做到这一点吗?优点&缺点

非常感谢你在这里阅读!

1 个答案:

答案 0 :(得分:1)

每次更改视频元素的currentTime时,视频实际更改其位置时都会触发seeked事件。

var vid = document.getElementById("v");
var canvas = document.getElementById("c");
var context = canvas.getContext('2d');
var targetFrame = document.getElementById('t');
var cw = canvas.width = 200;
var ch = canvas.height = Math.round(cw / 1.7777);
var targetOffset = 0;

window.addEventListener('wheel', function(e) {
  e.preventDefault();
  targetOffset = targetOffset + (e.deltaY / 1000);
  targetFrame.value = targetOffset;
  seek(); // for demo purpose, we only listen to wheel
  return false;
});
// that's all is needed
vid.addEventListener('seeked', function() {
  context.drawImage(vid, 0, 0, cw, ch);
});
// for demo
// removed the rendering loop
// now it only changes the video's currentTime property
function seek() {
  targetOffset = targetOffset * 0.9;
  targetFrame.value = Math.round(targetOffset * 100) / 100;
  var vct = vid.currentTime - targetOffset;
  if (vct < 0) {
    vct = vid.duration + vct;
  } else if (vct > vid.duration) {
    vct = vct - vid.duration;
  }
  vid.currentTime = vct;
}
.column {
  float: left;
  width: 50%;
}
.row:after {
  content: "";
  display: table;
  clear: both;
}
#c {
  border: 1px solid black;
}
<h3>
  scroll up is forward
</h3>
<div class="row">
  <div class="column">
    <div>
      Video element:
    </div>
    <video controls height="120" id="v" tabindex="-1" autobuffer="auto" preload="auto">
    <source type="video/webm" src="https://www.html5rocks.com/tutorials/video/basics/Chrome_ImF.webm"/>
</video>
  </div>
  <div class="column">
    <div>
      Canvas element:
    </div>
    <canvas id="c"></canvas>
    <div>
      Momentum: <input type=text id="t">
    </div>
  </div>
</div>