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

IT技术 javascript html video canvas html5-canvas
2021-01-14 06:27:38

我想每 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,生成第 0 帧的图像。然后视频帧跳到时间5s。所以当 时video.currentTime = 10,生成第 5s 帧的图像。

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