我知道如何逐帧复制从播放HTML5视频到使用2D上下文的画布。
但我希望使用暂停的视频,将其currentTime
改为动态,并将当前视频帧复制到画布。
我的猜测是,当视频位置设置为currentTime
属性时,某些进程尚未被调用,尽管视频本身确实更新了它显示的图像(但不是更新到画布)。
我发现通过在下一步中设置setTimeout来执行画布'drawImage'来克服这个问题是可行的。
You can see here a jsfiddle that proves the point
正如您可以在小提琴中看到的那样,您可以播放视频和画布更新,但如果您暂停视频,鼠标滚动会移动currentTime
视频。在那里,如果我直接调用drawImage
方法,画布不会更新,则需要'timeTimeout'来更新画布。
简而言之,我的问题是:
有更好的方法吗?没有setTimeout和内部de循环本身可以做到这一点吗?优点&缺点
非常感谢你在这里阅读!
答案 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>