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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19175174/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-29 14:05:29  来源:igfitidea点击:

Capture frames from video with HTML5 and JavaScript

javascripthtmlvideocanvashtml5-canvas

提问by Lin

I want to capture a frame from video every 5 seconds.

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

This is my JavaScript code:

这是我的 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);
}

The problem I have is the 1st two images generated are the same and the duration-5 second image is not generated. I found out that the thumbnail is generated before the video frame of the specific time is displayed in < video>tag.

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

For example, when video.currentTime = 5, image of frame 0s is generated. Then the video frame jump to time 5s. So when video.currentTime = 10, image of frame 5s is generated.

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

回答by

Cause

原因

The problem is that seeking video (by setting it's currentTime) is asynchronous.

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

You need to listen to the seekedevent or else it will risk take the actual current frame which is likely your old value.

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

As it is asynchronous you must not use the setInterval()as it is asynchronous too and you will not be able to properly synchronize when the next frame is seeked to. There is no need to use setInterval()as we will utilize the seekedevent instead which will keep everything is sync.

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

Solution

解决方案

By re-writing the code a little you can use the seekedevent to go through the video to capture the correct frame as this event ensures us that we are actually at the frame we requested by setting the currentTimeproperty.

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

Example

例子

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

Add this event handler to the party:

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

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 passed end, seek to next interval
    if (i <= this.duration) {
        // this will trigger another seeked event
        this.currentTime = i;
    }
    else {
        // Done!, next action
    }
});