Подтвердить что ты не робот

Захват кадров из видео с помощью HTML5 и JavaScript

Я хочу захватить кадр из видео каждые 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. Затем видеокадра переместится на время 5 секунд. Поэтому, когда video.currentTime = 10 создается изображение кадра 5s.

4b9b3361

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

Демо здесь