HTML5 逐帧查看/帧搜索?

发布于 2024-10-04 19:36:18 字数 519 浏览 4 评论 0原文

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

场景:有一个视频,有一个附加按钮,按下时会跳到下一帧。

您认为做到这一点的最佳方法是什么?

  1. 正常播放视频,监听timeUpdate事件,在FireFox上每帧都会调用该事件,然后暂停视频。然而,其他浏览器的行为与 Firefox 不同。
  2. currentTime 元素手动更改为 +1/24 秒,其中“24”是帧速率。不过我不知道如何获取 FPS。
  3. 您能想到的任何其他有用的方法。

编辑

我发现这个非常有用的HTML5测试页面,它跟踪所有浏览器实现准确框架的能力-寻求。

I'm looking for a way to view HTML5 <video>, frame-by-frame.

The scenario: Having a video, with an additional button that skips to the next frame when pressed.

What do you think is the best method to do this?

  1. Play the video normally, Listen to timeUpdate event, which on FireFox is called for every frame, and then just pause the video. However, the other browsers don't behave like Firefox.
  2. Change the currentTime element manually to +1/24 of a second, where "24" is the frame rate. I have no idea how to aquire the FPS, however.
  3. Any other helpful way you can think of.

EDIT

I have found this very useful HTML5 test page, which tracks all browsers' ability to achieve accurate frame-seeking.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

指尖上得阳光 2024-10-11 19:36:18

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

HTML:

<p id="time"></p>
<video id="v0" controls tabindex="0" autobuffer preload>
    <source type="video/webm; codecs="vp8, vorbis"" src="http://www.html5rocks.com/tutorials/video/basics/Chrome_ImF.webm"></source>
    <source type="video/ogg; codecs="theora, vorbis"" src="http://www.html5rocks.com/tutorials/video/basics/Chrome_ImF.ogv"></source>
    <source type="video/mp4; codecs="avc1.42E01E, mp4a.40.2"" src="http://www.html5rocks.com/tutorials/video/basics/Chrome_ImF.mp4"></source>
    <p>Sorry, your browser does not support the <video> 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);
};

It seems that most browsers allow the second approach, although you would need to know the frame rate. Opera, however, is the exception, and requires an approach similar to your first one (the result is not perfect). Here's a demo page I came up with that uses a 29.97 frames/s video (U.S. television standard). Note that it has not been extensively tested, so it might not work in IE 9, Firefox 4, or future versions of any browser.

HTML:

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

JavaScript (run on page load and uses jQuery 1.4.4 for the sake of brevity):

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);
};
神仙妹妹 2024-10-11 19:36:18

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

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

Having just been fighting this very same problem I cam up with a brute force method to find the frame rate.Knowing that the frame rate will never pass 60 frames a second I seek through the video at 1/60th second steps. Comparing each frame to the last by putting the video onto a canvas element and then using getImageData to get pixel data. I do this over a second of video and then count up the total number of unique frames to get the frame rate.

You do not have to check every single pixel. I Grab about 2/3rds of the inside of the video and then check about every 8th pixel across and down (depending on the size). You can stop the compare with just a single pixel different so this method in reasonably fast and reliable, well not compared to say reading a frameRate property, but better than guessing.

左岸枫 2024-10-11 19:36:18

这是我的小型 keyPress 处理程序,我用它来查找没有控件的视频。
如果视频暂停,它会跳过帧。

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

bookmarklet

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

This is my little keyPress handler I use to seek videos that don't have controls.
If the video is paused it skips by frames instead.

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

Note, you could easily add a keybinding to increase/decrease/switch the expectedFramerate on the fly to suit your needs.


Bonus: Add the script as Bookmarklet

bookmarklet

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

☆獨立☆ 2024-10-11 19:36:18

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

The best thing you can probably do until standards are confirmed and implemented (that'll be ages!) is take a guess at the frame-rate and increment by that time. Unless you're in a controlled environment, I'd advise against relying heavily on HTML5... as much as I love its features, it won't be reliably supported.

无声静候 2024-10-11 19:36:18

检查一下:

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

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

目前适用于 Firefox 56

var seekCompletePromise = HTMLMediaElement.seekToNextFrame();

HTMLMediaElement.seekToNextFrame();

Check this:

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

It's experimental at this moment and shouldn't be used on production site but looks like up-to-date solution.

It works for Firefox 56 for now

var seekCompletePromise = HTMLMediaElement.seekToNextFrame();

HTMLMediaElement.seekToNextFrame();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文