HTML5逐帧查看/逐帧寻找?

78
我正在寻找一种逐帧查看HTML5 <video> 的方法。
情景描述:有一个视频,以及一个附加的按钮,按下该按钮会跳转到下一帧。
你认为最好的方法是什么?
  1. 正常播放视频,监听timeUpdate事件,在Firefox中为每一帧调用一次,然后暂停视频。但是,其他浏览器的行为不像Firefox。
  2. 手动更改currentTime元素到+1 / 24秒,其中“24”是帧速率。但是我不知道如何获得FPS。
  3. 如果您有任何其他有用的方式。

编辑

我发现这个非常有用的HTML5测试页面,它跟踪所有浏览器实现准确的帧查找的能力。


@Ory Band 这正是我目前正在研究的。你有过任何成功的经验吗? - Ben Racicot
@BenRacicot基本上就是接受的答案所说的:设置时间并除以帧速率。您还可以将其除以小于帧速率的数字以获得误差边界(尝试不同数字,直到找到最佳值)。 - Ory Band
7
测试页面返回404错误,请问有人保存了内容吗? - Germain
1
@Germain: inconduit.com/smpte/。以下链接也可能与此相关:erasche.github.io/videojs-framebyframe - lyrically wicked
1
@JoãoPereira 抱歉,我已经很久没有处理这个问题了。我记得,如果你将帧率比率除以远远大于你所需的值,可能会解决问题并给你一个很好的精度。然而,这只是我的初步想法。 - Ory Band
显示剩余4条评论
5个回答

36

似乎大多数浏览器都允许第二种方法,尽管您需要知道帧速率。不过,Opera是个例外,需要类似于您的第一个方法(结果并不完美)的方法。这里是我创建的一个演示页面,使用29.97帧/秒的视频(美国电视标准)。请注意,它尚未经过广泛测试,因此可能无法在IE 9、Firefox 4或任何浏览器的未来版本中运行。 demo page

HTML:

<p id="time"></p>
<video id="v0" controls tabindex="0" autobuffer preload>
    <source type="video/webm; codecs=&quot;vp8, vorbis&quot;" src="http://www.html5rocks.com/tutorials/video/basics/Chrome_ImF.webm"></source>
    <source type="video/ogg; codecs=&quot;theora, vorbis&quot;" src="http://www.html5rocks.com/tutorials/video/basics/Chrome_ImF.ogv"></source>
    <source type="video/mp4; codecs=&quot;avc1.42E01E, mp4a.40.2&quot;" src="http://www.html5rocks.com/tutorials/video/basics/Chrome_ImF.mp4"></source>
    <p>Sorry, your browser does not support the &lt;video&gt; element.</p>
</video>

JavaScript (在页面加载时运行,使用jQuery 1.4.4为了简洁):

var vid = $('#v0')[0];

vid.onplay = vid.onclick = function() {
    vid.onplay = vid.onclick = null;

    setTimeout(function() {
        vid.pause();
        setInterval(function() {
            if($.browser.opera) {
                var oldHandler = vid.onplay;
                vid.onplay = function() {
                    vid.pause();
                    vid.onplay = oldHandler;
                };
                vid.play();
            } else {
                vid.currentTime += (1 / 29.97);
            }
        }, 2000);
    }, 12000);

    setInterval(function() {
        $('#time').html((vid.currentTime * 29.97).toPrecision(5));
    }, 100);
};

3
提醒一下,var something = things = 'stuff'; 实际上会使得"things"成为全局变量。在这种情况下它可以工作,但在其他情况下可能不行。 - newshorts
这对于videojs播放器有效吗? - EdG
1
我认为这不会起作用,因为帧时间不是恒定的。某些帧速度快,某些帧速度慢。您可以通过读取每个帧的currentTime来进行验证。 - Bill Yan

15

刚刚我也遇到了同样的问题,我想出了一种暴力方法来查找帧速率。知道帧速率不会超过每秒60帧,我通过1/60秒的步长在视频中进行搜索。将视频放入画布元素中并使用getImageData获取像素数据,逐帧与上一帧进行比较。我在一秒钟的视频中执行此操作,然后计算总唯一帧数以获得帧速率。

您不必检查每个单独的像素。我抓取大约2/3的视频内部,然后每隔8个像素横向和纵向检查一次(取决于大小)。您只需比较一个像素即可停止比较,因此这种方法相当快速可靠,当然无法与读取frameRate属性相比,但比猜测要好。


1
你用什么来查找和比较? - alexandercannon
2
我使用 video.currentTime = time; 开始查找,然后 time = time + 1/60; 在 video.seeked 事件中,我使用 setTimeout(frameCompare.bind(videoHandler),0); 来比较帧,如果 time < 1,则开始下一个查找。 - Blindman67
抱歉回复晚了。29.97帧率将在一秒钟内报告29帧。您可以使用此来推断出29.97。 - Blindman67
2
视频如果开头是空白或者有一些随机的部分不变化,会怎么样呢? - Cocoa Nub
非常希望有一个示例,这很容易成为一个npm库 :) - TOPKAT
显示剩余3条评论

6

在标准确认并实施之前,你可以做的最好的事情(那会儿要等很久!)就是猜测帧率并按照该时间递增。除非你处于受控环境中,否则我建议不要过度依赖HTML5...尽管我喜欢它的功能,但它不会得到可靠的支持。


5
但这正是我正在尝试做的!用HTML5以Web应用程序的方式实现它! :) 这就是挑战所在。 - Ory Band

6
这是我用来寻找没有控制器的视频的小型keyPress处理程序。
如果视频处于paused状态,则跳过帧。
const video = document.querySelector('#yourVideo')
const expectedFramerate = 60 // yourVideo's framerate

function handleKey(ev) {
  let d = 0;

  switch (ev.key) {
    case ",": d = -5; break;  // normal
    case ".": d = +5; break;
    case "?": d = -10; break; // shift
    case ":": d = +10; break;
    case "<": d = -2; break;  // rightAlt
    case ">": d = +2; break;
    case " ": togglePlayback(); break;
  }

  if (d) {
    if (video.paused) video.currentTime += Math.sign(d) * 1/expectedFramerate
    else video.currentTime += d
  }
}

document.onkeypress = handleKey

function togglePlayback() {
  video.paused
    ? video.play()
    : video.pause()
}
注意,您可以轻松地添加一个按键绑定来动态调整expectedFramerate的增加/减少/切换以适应您的需求。

奖励: 将脚本添加为书签工具

bookmarklet

https://gist.github.com/ackvf/b180e9883069ad753969a30cb2622787


1
我认为1/60是为了允许每秒60帧?如果是这样,可能需要强调用户可能希望根据自己的帧速率进行调整,假设他们知道它并且它是恒定的。 - Mick
@Mick 很好的观点,谢谢你的评论,现在,请做个好朋友,给我的答案点个赞。 - Qwerty

4

1
这种非标准的方法已被Firefox弃用,并且从未被任何其他浏览器供应商实现。 - Jens Habegger

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接