javascript 获取视频 HTML5 中的帧更改
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17044567/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Get frame change in video HTML5
提问by Alexandre Pinheiro
I need detect all frames changes of a video in HTML 5, i tried the follow code, but i can't get all changes, only i can get eight or nine updates per second..
我需要检测 HTML 5 中视频的所有帧更改,我尝试了以下代码,但我无法获得所有更改,只能每秒获得 8 或 9 次更新。
<body>
<canvas id="Canvas" width="800" height="450" style="position:absolute; left:5; top:5">Can't Load Canvas</canvas>
<video id="videoPlay" muted controls>
<source src="assets/soccer.webm" type="video/webm">
<source src="assets/soccer.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
</body>
<script type="text/javascript">
videoPlay.addEventListener('timeupdate', function (){
putOverlay();
});
function putOverlay(){
console.log(videoPlay.currentTime);
console.log("another frame");
}
</script>
</html>
I tried the following code too, but with a timer there is a loss of synchronization between the frame and the value given by the timer, over time..
我也尝试了以下代码,但是随着时间的推移,随着时间的推移,帧与计时器给出的值之间会失去同步。
<body>
<canvas id="LeCanvas" width="800" height="450" style="position:absolute; left:5; top:5">Can't Load Canvas</canvas>
<!-- Video -->
<video id="videoPlay" controls>
<source src="assets/soccer.webm" type="video/webm">
<source src="assets/soccer.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
</body>
<!-- Play Video-->
<script>
//Play Damn Video
var videoPlay = $('#videoPlay')[0];
videoPlay.play(1);
</script>
<!-- Canvas Animation -->
<script>
//Animation
function animate() {
console.log("frame change");
}
setInterval(animate, 1000/29.97);
</script>
Any suggestions for my problem?
对我的问题有什么建议吗?
Sorry my english
对不起我的英语
regards Alex
问候亚历克斯
回答by brianchirls
As noted in the comments above, timeupdate
only fires every 15-250ms, and in practice it appears to be closer to 250ms. It seems as though timeupdate
was designed to provide enough accuracy to display the currentTime
every second. So your best option is to run a timer that runs at the rate you want and query currentTime
on every iteration.
正如上面的评论中所指出的,timeupdate
每 15-250 毫秒才触发一次,实际上它似乎更接近 250 毫秒。似乎timeupdate
旨在提供足够的精度来显示currentTime
每秒。因此,您最好的选择是运行一个以您想要的速率运行的计时器,并currentTime
在每次迭代时进行查询。
But rather than use setInterval
or even setTimeout
, you should be using requestAnimationFrame. This will run approximatelyevery 16ms (60fps), but it will be synchronized with the video card refresh rate. If you use setTimeout
, you may see flicker or screen tearing on certain devices, especially mobile ones. It also allows the browser to throttle your frame rate when the tab is not visible to save on CPU cycles (and therefore battery usage).
但是,您应该使用requestAnimationFrame而不是 usesetInterval
或 even 。这将大约每 16 毫秒 (60fps)运行一次,但它将与视频卡刷新率同步。如果您使用,您可能会在某些设备上看到闪烁或屏幕撕裂,尤其是移动设备。它还允许浏览器在选项卡不可见时限制您的帧速率以节省 CPU 周期(从而节省电池使用量)。setTimeout
setTimeout
It's also better than setInterval
because, if for some reason your render code takes longer than the 30 or 16ms you've allotted, setInterval
may pile up calls and cause timing problems, but requestAnimationFrame
will skip frames to get you back on track.
这也比setInterval
因为,如果由于某种原因您的渲染代码花费的时间超过您分配的 30 或 16 毫秒,setInterval
可能会堆积调用并导致计时问题,但requestAnimationFrame
会跳过帧以使您回到正轨。
Assuming you've used the polyfill as above, the code would look something like this:
假设您已经使用了上述 polyfill,代码将如下所示:
var video = document.getElementById('videoPlay'),
lastTime = -1;
function draw() {
var time = video.currentTime;
if (time !== lastTime) {
console.log('time: ' + time);
//todo: do your rendering here
lastTime = time;
}
//wait approximately 16ms and run again
requestAnimationFrame(draw);
}
draw();
The above code has a check on time to make sure you don't draw the same frame twice in a row. You don't reallyneed that, but it will save you a few CPU cycles. But when drawing a video to canvas, the frame is a couple of milliseconds behind what's reported by currentTime. So if you pause the video and then skip around, you will almost definitely be one frame behind. Usually, if the currentTime hasn't changed since my last draw but the video is paused, I'll keep drawing every cycle for another half second or so. Or you could just take the time check out.
上面的代码对时间进行了检查,以确保您不会连续绘制同一帧两次。您并不真正需要它,但它会为您节省一些 CPU 周期。但是当在画布上绘制视频时,该帧比 currentTime 报告的帧慢几毫秒。所以如果你暂停视频然后跳过,你几乎肯定会落后一帧。通常,如果 currentTime 自上次绘制以来没有改变但视频已暂停,我将在每个循环中继续绘制半秒左右。或者你可以花时间检查一下。