Javascript 在HTML5视频中获取帧编号
我试图捕捉视频的每一帧编号,但似乎没有办法实现它。所以我启动了我自己的时钟来匹配视频的帧数,但它们从不匹配,而且随着视频的进展,差异不断增加 请看一下我的垃圾箱 我在AdobeAfter Effect视频的每一帧中都添加了帧数,这样我就有了更准确的差异信息。视频以29.97fps的速度运行,requestAnimationFrame也设置为以相同的速率增加该数字,但是我不确定这种差异来自何处Javascript 在HTML5视频中获取帧编号,javascript,html,video,requestanimationframe,popcornjs,Javascript,Html,Video,Requestanimationframe,Popcornjs,我试图捕捉视频的每一帧编号,但似乎没有办法实现它。所以我启动了我自己的时钟来匹配视频的帧数,但它们从不匹配,而且随着视频的进展,差异不断增加 请看一下我的垃圾箱 我在AdobeAfter Effect视频的每一帧中都添加了帧数,这样我就有了更准确的差异信息。视频以29.97fps的速度运行,requestAnimationFrame也设置为以相同的速率增加该数字,但是我不确定这种差异来自何处 有时他们匹配,有时不匹配。我也尝试过离线操作,但得到了相同的结果。任何帮助。我在github上找到了有关
有时他们匹配,有时不匹配。我也尝试过离线操作,但得到了相同的结果。任何帮助。我在github上找到了有关此的内容 我在这把小提琴中实现了它: 编辑:将小提琴更新为新视频,使其再次工作 编辑:如前所述,视频速度为25fps,因此我对其进行了更新,并在那里消除了对jQuery的依赖。
非jQuery版本:
问题在于,
setTimeout
实际上是不可预测的,因此您无法确保每次运行函数时都会显示一个新帧。每次更新帧显示时,需要检查视频的currentTime
,并将其乘以帧速率
这里有一个工作示例:它关闭了一帧,但看起来您可能在开头有两帧标记为“000000”
关于视频元素,您可能需要注意以下几点:
currentTime
并不总是完全代表屏幕上的内容。有时它会向前一点,特别是在搜索时(这就是为什么在我的JSBin中,我不会在搜索时更新帧)我相信,
currentTime
会在一个独立于实际视频绘制的线程上进行更新,所以它的工作方式就像它自己的时钟一样,一直在运行。这是视频想要的地方,不一定是它所在的地方。因此,您可以接近,但需要对帧计算的结果进行四舍五入,有时,您可能会偏离一帧。从M83开始,Chromium有一个requestVideoFrameCallback()API,它可能会解决您的问题。
您可以使用mediaTime获得一致的时间戳,如中所述。从那里,您可以尝试以下内容:
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)
这只会在新帧上触发,但您可能偶尔会错过一个帧(您可以从metadata.presentedFrames
count中的不连续性中检测到)。您也可能在捕获帧时稍晚(通常为16ms,或者比视频帧可用时晚一次调用window.requestAnimationFrame()
)
如果您对API的高级概述感兴趣,或者您可以看看。谢谢Samuel,是的,事实上这是我遵循的解决方案,但我需要随着视频的发展不断获取帧编号。我也尝试过不舍入总帧数,但没有运气。可能(如果你控制它正在绘制的画布)会在那里保留一个计数器:虽然从我的角度看这也像是黑暗魔法LOL,请看,有时视频停止时,它也会间隔1帧,但这可能是通过在视频暂停/停止时再次设置帧号html来解决的。看起来该库通过设置一个计时器来完成帧速率跟踪,该计时器为跟随者“每个预期帧速率轮询两次:)
framerate
应该与视频中的实际帧速率匹配。将其设置为100不会影响播放速度,但会影响帧计数。@2pha感谢您的小提琴。当前视频(大公兔)的帧率是25,而不是29.97。当你纠正它是给一个更准确的帧编号。@Dipu Raj,啊,你是正确的,我更新了小提琴和代码。哇,回答距离5岁还有2天,仍然在帮助人们。它给我一种温暖而模糊的感觉:)谢谢,真是太好了。
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';
}
});
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)