使用 HTML5 和 JavaScript 从视频中捕获帧

Posted

技术标签:

【中文标题】使用 HTML5 和 JavaScript 从视频中捕获帧【英文标题】:Capture frames from video with HTML5 and JavaScript 【发布时间】:2013-10-11 02:16:35 【问题描述】:

我想每 5 秒从视频中捕获一帧。

这是我的 javascript 代码:

video.addEventListener('loadeddata', function() 
    var duration = video.duration;
    var i = 0;

    var interval = setInterval(function() 
        video.currentTime = i;
        generateThumbnail(i);
        i = i+5;
        if (i > duration) clearInterval(interval);
    , 300);
);

function generateThumbnail(i)      
    //generate thumbnail URL data
    var context = thecanvas.getContext('2d');
    context.drawImage(video, 0, 0, 220, 150);
    var dataURL = thecanvas.toDataURL();

    //create img
    var img = document.createElement('img');
    img.setAttribute('src', dataURL);

    //append img in container div
    document.getElementById('thumbnailContainer').appendChild(img);

我遇到的问题是第一个生成的两个图像是相同的,并且没有生成持续时间为 5 秒的图像。我发现缩略图是在特定时间的视频帧显示在< video>标签之前生成的。

例如video.currentTime = 5时,生成帧0s的图像。然后视频帧跳转到时间 5s。所以当video.currentTime = 10时,会生成第5s帧的图像。

【问题讨论】:

generateThumbnail 函数中的 Canvas 是什么?您能否为这个问题提供更有用的 html 标签?我正在尝试做同样的事情,但我不确定应该如何在页面上声明 theCanvas。谢谢! 嗨,林,你问的这个问题还有源代码吗?可以给个链接吗? 【参考方案1】:

原因

问题在于寻找视频(通过设置为currentTime)是异步的。

您需要收听seeked 事件,否则它会冒着获取可能是您的旧值的实际当前帧的风险。

由于它是异步的,因此您必须不要使用setInterval(),因为它也是异步的,并且在寻找下一帧时您将无法正确同步。无需使用setInterval(),因为我们将使用seeked 事件来代替,这将保持一切同步。

解决方案

通过稍微重写代码,您可以使用seeked 事件来遍历视频以捕获正确的帧,因为此事件通过设置currentTime 属性确保我们实际上处于我们请求的帧.

示例

// global or parent scope of handlers
var video = document.getElementById("video"); // added for clarity: this is needed
var i = 0;

video.addEventListener('loadeddata', function() 
    this.currentTime = i;
);

将此事件处理程序添加到聚会中:

video.addEventListener('seeked', function() 

  // now video has seeked and current frames will show
  // at the time as we expect
  generateThumbnail(i);

  // when frame is captured, increase here by 5 seconds
  i += 5;

  // if we are not past end, seek to next interval
  if (i <= this.duration) 
    // this will trigger another seeked event
    this.currentTime = i;
  
  else 
    // Done!, next action
  
);

【讨论】:

我尝试使用您的代码。现在我有另一个问题。由于被搜索,当我通过点击时间轴搜索视频时,图像也会生成。但我不想那样。 编辑我已经解决了这个问题。谢谢。 video.currentTime = i; 不会为我触发任何搜索的事件。 @Matian2040 不,很遗憾 哦,您实际上可以比较帧并确保它们不同,然后再显示“新帧”。这是一个线索。 developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/… @Matian2040 当然,一个简单的方法是使用“差异”混合结合饱和过滤器(0%)和计数像素> 0。使用基于百分比的阈值以避免过多的噪声/压缩影响。总是有误报的机会,但如果这是一个目标,它可以减少不同拇指的数量(或根据目的使用更长的间隔)。

以上是关于使用 HTML5 和 JavaScript 从视频中捕获帧的主要内容,如果未能解决你的问题,请参考以下文章

使用 html5 视频标签从特定位置开始播放视频

HTML5 从图像生成视频

如何从 HTML5 中的视频中提取音频?

使用 JavaScript 获取 HTML5 视频的宽度和高度?

HTML5 和 Javascript 仅在可见时播放视频

使用 HTML5 和 Javascript 录制/上传带有进度条的固定长度视频