javascript 获取 HTML5 视频中的帧数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24827929/
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 numbers in HTML5 Video
提问by SayedTaqui
I am trying to capture each frame number of the video however it looks like there is no way of achieving it. So I started my own clock to match the frame numbers of the video but they never match and the difference keeps increasing as the video progress.
我正在尝试捕获视频的每个帧数,但看起来没有办法实现它。所以我开始使用自己的时钟来匹配视频的帧数,但它们永远不会匹配,并且随着视频的进展,差异不断增加。
Please have a look at my bin. http://jsbin.com/dopuvo/4/edit
请看看我的垃圾箱。http://jsbin.com/dopuvo/4/edit
I have added the frame number to each frame of the video from Adobe After Effect so I have more accurate information of the difference. The Video is running at 29.97fps and the requestAnimationFrame is also set to increase the number at the same rate, however I am not sure where this difference is coming from.
我已将帧号添加到 Adobe After Effect 视频的每一帧中,以便我有更准确的差异信息。视频以 29.97 fps 运行,并且 requestAnimationFrame 也设置为以相同的速率增加数字,但是我不确定这种差异的来源。
Sometimes they match and sometimes they don't. I also tried doing it offline but I get the same results. Any help.
有时它们匹配,有时它们不匹配。我也试过离线做,但我得到了相同的结果。任何帮助。
采纳答案by 2pha
I found something on github for this. https://github.com/allensarkisyan/VideoFrame
为此,我在 github 上找到了一些东西。https://github.com/allensarkisyan/VideoFrame
I have implemented it in this fiddle: https://jsfiddle.net/k0y8tp2v/
我已经在这个小提琴中实现了它:https: //jsfiddle.net/k0y8tp2v/
var currentFrame = $('#currentFrame');
var video = VideoFrame({
id : 'video',
frameRate: 25,
callback : function(frame) {
currentFrame.html(frame);
}
});
$('#play-pause').click(function(){
if(video.video.paused){
video.video.play();
video.listen('frame');
$(this).html('Pause');
}else{
video.video.pause();
video.stopListen();
$(this).html('Play');
}
});
EDIT:updated fiddle to new video so it works again.
编辑:将小提琴更新为新视频,使其再次工作。
EDIT:As pointed out, the video is 25fps, so I updated it, and while I was there removed reliance on jQuery.
Non jQuery version:
https://jsfiddle.net/k0y8tp2v/1/
编辑:正如所指出的,视频是 25fps,所以我更新了它,而我在那里消除了对 jQuery 的依赖。
非 jQuery 版本:https:
//jsfiddle.net/k0y8tp2v/1/
var currentFrame = document.getElementById('currentFrame');
var video = VideoFrame({
id : 'video',
frameRate: 25,
callback : function(frame) {
currentFrame.innerHTML = frame ;
}
});
document.getElementById('play-pause').addEventListener('click', function(e){
if(video.video.paused){
video.video.play();
video.listen('frame');
e.target.innerHTML = 'Pause';
}else{
video.video.pause();
video.stopListen();
e.target.innerHTML = 'Play';
}
});
回答by brianchirls
The problem is that setTimeout
is not really predictable, so you can't be sure that exactly one new frame has been displayed every time your function runs. You need to check the currentTime
of the video every time you update your frame display and multiply that by the frame rate.
问题是这setTimeout
并不是真正可预测的,因此您无法确定每次运行您的函数时都显示了一个新的帧。currentTime
每次更新帧显示时都需要检查视频的 ,并将其乘以帧速率。
Here's a working example: http://jsbin.com/xarekice/1/editIt's off by one frame, but it looks like you may have two frames at the beginning marked "000000".
这是一个工作示例:http: //jsbin.com/xarekice/1/edit它已关闭一帧,但看起来您可能在开头有两帧标记为“000000”。
A few things about the video element that you may want to be aware of:
您可能想要了解的有关视频元素的一些事项:
As you seem to have discovered, there's no reliable way to determine the frame rate, so you have to discover it elsewhere and hard-code it. There are some interesting things going on with video metrics, but they're non-standard, not widely supported and, in my experience, completely ineffective at determining the actual frame rate.
The
currentTime
is not always exactly representative of what's on the screen. Sometimes it's ahead a little bit, especially when seeking (which is why in my JSBin, I don't update the frame while you're seeking).
正如您似乎已经发现的那样,没有可靠的方法来确定帧速率,因此您必须在其他地方发现它并对其进行硬编码。视频指标有一些有趣的事情,但它们是非标准的,没有得到广泛支持,根据我的经验,在确定实际帧速率方面完全无效。
在
currentTime
并不总是准确地代表在屏幕上什么。有时它会提前一点,尤其是在查找时(这就是为什么在我的 JSBin 中,我不会在您查找时更新框架)。
I believe currentTime
updates on a separate thread from the actual video draw, so it kind of works like it's own clock that just keeps going. It's where the video wants to be, not necessarily where it is. So you can get close, but you need to round the results of the frame calculation, and once in a while, you may be off by one frame.
我相信currentTime
在与实际视频绘制不同的线程上进行更新,因此它的工作方式就像它自己的时钟一样一直在运行。这是视频想要的位置,不一定是它的位置。所以你可以接近,但你需要对帧计算的结果进行四舍五入,偶尔,你可能会偏离一帧。
回答by Thomas Guilbert
Starting in M83, Chromium has a requestVideoFrameCallback() API, which might solve your issue. You can use the mediaTime to get a consistent timestamp, as outlined in this Github issue. From there, you could try something like this:
从 M83 开始,Chromium 有一个 requestVideoFrameCallback() API,它可能会解决您的问题。您可以使用 mediaTime 获得一致的时间戳,如此 Github issue 中所述。从那里,你可以尝试这样的事情:
var frameCounter = (time, metadata) => {
let count = metadata.mediaTime * frameRate;
console.log("Got frame: " + Math.round(count));
// Capture code here.
video.requestVideoFrameCallback(frameCounter);
}
video.requestVideoFrameCallback(frameCounter)
This will only fire on new frames, but you may occasionally miss one (which you can detect from a discontinuity in the metadata.presentedFrames
count). You might also be slightly late in capturing the frame (usually 16ms, or one call to window.requestAnimationFrame()
later than when the video frame is available).
这只会在新帧上触发,但您可能偶尔会错过一个(您可以从metadata.presentedFrames
计数的不连续性中检测到)。您捕获帧的时间也可能稍晚(通常为 16 毫秒,或者window.requestAnimationFrame()
比视频帧可用时更晚一次调用)。
If you're interested in a high level overview of the API, here's a blogpost, or you can take a look at the API's offical github.
如果您对 API 的高级概述感兴趣,请参阅博客文章,或者您可以查看API 的官方 github。