在HTML5视频中获取帧编号

Say*_*qui 14 javascript video html5 requestanimationframe popcornjs

我试图捕获视频的每个帧编号,但看起来没有办法实现它.所以我开始使用自己的时钟来匹配视频的帧数,但它们从不匹配,随着视频的进展,差异也在不断增加.

请看看我的垃圾箱.http://jsbin.com/dopuvo/4/edit

我已经将帧编号添加到Adobe After Effects的每个视频帧中,因此我可以获得更准确的差异信息.视频以29.97fps运行,requestAnimationFrame也设置为以相同的速率增加数量,但我不确定这种差异来自何处.

有时他们匹配,有时他们不匹配.我也尝试离线,但我得到相同的结果.任何帮助.

2ph*_*pha 14

我在github上找到了一些东西.https://github.com/allensarkisyan/VideoFrame

我已经在这个小提琴中实现了它:http://jsfiddle.net/Ck6Zq/184/

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');
    }
});
Run Code Online (Sandbox Code Playgroud)

编辑:更新小提琴新视频,以便它再次工作.

  • @2pha 谢谢你的小提琴。当前视频(Big Buck Bunny)的帧速率是 25,而不是 29.97。当您纠正它时,它会给出更准确的帧号。 (2认同)
  • @Dipu Raj,啊,你是对的,我更新了小提琴和代码。哇,距离回答还差 2 天,还差 5 岁了,而且还在帮助别人。它给我一种温暖模糊的感觉:) (2认同)

bri*_*rls 7

问题是setTimeout实际上不可预测,所以每次运行函数时都无法确定是否显示了一个新帧.currentTime每次更新帧显示时都需要检查视频,并将其乘以帧速率.

这是一个工作示例:http://jsbin.com/xarekice/1/edit它关闭了一帧,但看起来你可能在开头有两个标记为"000000"的帧.

关于您可能想要了解的视频元素的一些事项:

  1. 正如您似乎已经发现的那样,没有可靠的方法来确定帧速率,因此您必须在其他地方发现它并对其进行硬编码.视频指标有一些有趣的事情,但它们是非标准的,没有广泛支持,而且根据我的经验,在确定实际帧速率方面完全无效.

  2. currentTime并不总是准确地代表在屏幕上什么.有时它会领先一点,特别是在寻找时(这就是为什么在我的JSBin中,我不会在你寻找的时候更新框架).

我相信currentTime在实际视频绘制的单独线程上更新,所以它有点像它自己的时钟一样继续前进.这是视频想要的地方,而不一定是它的位置.所以你可以靠近,但是你需要对帧计算的结果进行舍入,偶尔你可能会偏离一帧.


小智 5

从 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)
Run Code Online (Sandbox Code Playgroud)

这只会在新帧上触发,但您可能偶尔会错过一帧(您可以从metadata.presentedFrames计数的不连续性中检测到)。您在捕获帧时也可能稍晚一些(通常是 16 毫秒,或者window.requestAnimationFrame()比视频帧可用时更晚一次调用)。

如果您对 API 的高级概述感兴趣,请参阅博客文章,或者您可以查看API 的官方 github