获取视频 HTML5 中的帧变化

Posted

技术标签:

【中文标题】获取视频 HTML5 中的帧变化【英文标题】:Get frame change in video HTML5 【发布时间】:2013-06-07 07:55:00 【问题描述】:

我需要检测 html 5 中视频的所有帧变化,我尝试了以下代码,但我无法获得所有变化,我每秒只能获得 8 或 9 次更新..

<body>
    <canvas id="Canvas"   style="position:absolute; left:5; top:5">Can't Load Canvas</canvas>
    <video id="videoPlay" muted controls>
        <source src="assets/soccer.webm" type="video/webm">
            <source src="assets/soccer.mp4" type="video/mp4">
            Your browser does not support the video tag.
    </video>
</body>
<script type="text/javascript">
            videoPlay.addEventListener('timeupdate', function ()
                putOverlay();
            );
            function putOverlay()                  
                console.log(videoPlay.currentTime);
                console.log("another frame");
            
    </script>
</html>

我也尝试了以下代码,但是随着时间的推移,随着时间的推移,帧和计时器给出的值之间会失去同步。

<body>
        <canvas id="LeCanvas"   style="position:absolute; left:5; top:5">Can't Load Canvas</canvas>
        <!-- Video -->
        <video id="videoPlay"  controls>
            <source src="assets/soccer.webm" type="video/webm">
            <source src="assets/soccer.mp4" type="video/mp4">
            Your browser does not support the video tag.
        </video>
    </body>
    <!-- Play Video-->  
    <script>
        //Play Damn Video
        var videoPlay = $('#videoPlay')[0];
        videoPlay.play(1);
    </script>
    <!-- Canvas Animation  -->
    <script>
        //Animation
        function animate() 
            console.log("frame change");
               
        setInterval(animate, 1000/29.97); 
    </script>

对我的问题有什么建议吗?

对不起我的英语

问候 亚历克斯

【问题讨论】:

信息可能不再是 100% 最新的,但请参阅 How often does the timeupdate event fire for an html5 video?,并查看链接的 Bugzilla 页面。 根据 HTML5 规范,浏览器必须每隔 15 到 250 毫秒触发一次 timeupdate 事件——但这与您的帧数无关。 setInterval 不会同步 1 到 1。如果您绝对需要帧精度,您可以尝试尽可能快地运行 setInterval。请注意,登录到控制台可能会减慢速度,具体取决于浏览器。 这就是我对我的第二个代码所做的事情。问题是,随着时间的推移,差异会越来越大.. 【参考方案1】:

如上面的 cmets 所述,timeupdate 仅每 15-250 毫秒触发一次,实际上它似乎更接近 250 毫秒。似乎timeupdate 旨在提供足够的精度以每秒显示currentTime。因此,您最好的选择是运行一个以您想要的速率运行的计时器,并在每次迭代时查询 currentTime

但是,您应该使用requestAnimationFrame,而不是使用setInterval 甚至setTimeout。这将大约每 16 毫秒 (60fps) 运行一次,但它会与视频卡刷新率同步。如果您使用setTimeout,您可能会在某些设备上看到闪烁或屏幕撕裂,尤其是移动设备。它还允许浏览器在选项卡不可见时限制帧速率,以节省 CPU 周期(从而节省电池使用量)。

它也比setInterval 好,因为如果由于某种原因您的渲染代码花费的时间超过了您分配的 30 或 16 毫秒,setInterval 可能会堆积调用并导致时间问题,但requestAnimationFrame 会跳帧让您重回正轨。

假设你已经使用了上面的 polyfill,代码看起来像这样:

var video = document.getElementById('videoPlay'),
    lastTime = -1;
function draw() 
    var time = video.currentTime;
    if (time !== lastTime) 
        console.log('time: ' + time);
        //todo: do your rendering here
        lastTime = time;
    

    //wait approximately 16ms and run again
    requestAnimationFrame(draw);


draw();

上面的代码对时间进行了检查,以确保您不会连续两次绘制同一帧。您真的不需要它,但它会为您节省几个 CPU 周期。但是在画布上绘制视频时,帧比 currentTime 报告的帧晚几毫秒。所以如果你暂停视频然后跳来跳去,你几乎肯定会落后一帧。通常,如果自上次绘制以来 currentTime 没有改变但视频已暂停,我将在每个周期再绘制半秒左右。或者你可以花时间检查一下。

【讨论】:

以上是关于获取视频 HTML5 中的帧变化的主要内容,如果未能解决你的问题,请参考以下文章

加载另一个源时 HTML5 视频大小发生变化

MKMapView 点击 pin 会导致奇怪的帧变化

Martrix源码分析系列-如何监控帧率变化

实现抖音视频抖动效果---OpenCV-Python开发指南(53)

视频编解码 — 帧内预测

iOS 确定视频中的帧数