【问题标题】:HTML5 frame-by-frame viewing / frame-seeking?HTML5逐帧查看/逐帧?
【发布时间】:2011-05-16 22:23:56
【问题描述】:

我正在寻找一种逐帧查看 HTML5 <video> 的方法。

场景:有一个视频,有一个额外的按钮,按下时会跳到下一帧。

你认为最好的方法是什么?

  1. 正常播放视频,Listen to timeUpdate event, which on FireFox is called for every frame,然后暂停视频。但是,其他浏览器的行为与 Firefox 不同。
  2. 手动将currentTime 元素更改为+1/24 秒,其中“24”是帧速率。但是,我不知道如何获取 FPS。
  3. 您能想到的任何其他有用的方法。

编辑

我找到了this very useful HTML5 test page,它跟踪所有浏览器实现准确寻帧的能力。

【问题讨论】:

  • IIRC 在 WHATWG 中仍在争论,目前还没有好的解决方案。
  • @Ory Band 这正是我目前正在玩的。你有什么运气吗?
  • 测试页面返回404,是否有人保存了内容?
  • @Germain: inconduit.com/smpte/。以下链接也可能是相关的:erasche.github.io/videojs-framebyframe.
  • @JoãoPereira 抱歉,我已经很久没有处理这个问题了。我记得如果你除以一个远大于你需要的帧速率比,可能会解决问题并给你一个很好的精度。然而,这只是在我的头上。

标签: html video html5-video


【解决方案1】:

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

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);
};

【讨论】:

  • 仅供参考,var something = things = 'stuff';实际上使“事物”全球化。在这种情况下它可以工作,在其他情况下它可能不会
  • 对videojs播放器有效吗?
  • 我认为这不会起作用,因为帧时间不是恒定的。某些帧很快,某些帧很慢。您可以通过回读每一帧的 currentTime 来验证
【解决方案2】:

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

您不必检查每个像素。我抓取大约 2/3 的视频内部,然后检查大约每 8 个像素的横向和向下(取决于大小)。您可以仅通过一个像素不同来停止比较,因此此方法相当快速且可靠,与读取 frameRate 属性相比,但比猜测要好。

【讨论】:

  • 你用什么来寻找和比较?
  • 我开始寻找 video.currentTime = time;然后时间 = 时间 + 1/60;在 video.seeked 事件中,我使用 setTimeout(frameCompare.bind(videoHandler),0);比较帧,然后在时间 时开始下一次搜索
  • 可以扩展它以考虑我们 29.97 的电视帧速率还是只是捏造数字?使帧速率达到该精度所需的额外数学运算是否会大大提高处理能力?
  • 抱歉回复晚了。 29.97 帧速率将在一秒钟内报告 29 帧。您可以使用它来推断 29.97。
  • 如果视频有一个空白的开始部分,或者任何一秒钟不变的随机部分怎么办?
【解决方案3】:

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

【讨论】:

  • 但这正是我想要做的!以网络应用的方式使用 HTML5 来实现! :) 这就是挑战所在。
【解决方案4】:

这是我用来寻找没有控件的视频的小 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 以满足您的需求。

【讨论】:

  • 我认为1/60是允许每秒60帧?如果是这样,最好强调一下用户可能希望调整到自己的帧速率,假设他们知道并且它是恒定的。
  • @Mick 好点,谢谢你的评论,现在,成为一个好朋友并支持我的回答?
【解决方案5】:

检查一下:

https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/seekToNextFrame

目前处于试验阶段,不应在生产站点上使用,但看起来是最新的解决方案。

目前适用于 Firefox 56

var seekCompletePromise = HTMLMediaElement.seekToNextFrame();

HTMLMediaElement.seekToNextFrame();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-14
    相关资源
    最近更新 更多