Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
346 views
in Technique[技术] by (71.8m points)

javascript - 使用HTML5和JavaScript从视频捕获帧(Capture frames from video with HTML5 and JavaScript)

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.

(我的问题是,第一次生成的两个图像是相同的,而持续时间为5秒的图像却没有生成。)

I found out that the thumbnail is generated before the video frame of the specific time is displayed in < video> tag.

(我发现缩略图是在< video>标签中显示特定时间的视频帧之前生成的。)

For example, when video.currentTime = 5 , image of frame 0s is generated.

(例如,当video.currentTime = 5 ,将生成帧0s的图像。)

Then the video frame jump to time 5s.

(然后视频帧跳到时间5s。)

So when video.currentTime = 10 , image of frame 5s is generated.

(因此,当video.currentTime = 10 ,将生成帧5s的图像。)

  ask by Lin translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Cause(原因)

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

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

You need to listen to the seeked event 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.

(由于它是异步的,因此您也不能使用setInterval()因为它也是异步的,并且当寻求下一帧时,您将无法正确同步。)

There is no need to use setInterval() as we will utilize the seeked event instead which will keep everything is sync.

(无需使用setInterval()因为我们将利用seeked事件来保持所有内容同步。)

Solution(解)

By re-writing the code a little you can use the seeked event 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 currentTime property.

(通过稍微重写代码,您可以使用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
    }
});

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...