Pertanyaan Tangkap frame dari video dengan HTML5 dan JavaScript


Saya ingin menangkap bingkai dari video setiap 5 detik.

Ini adalah kode JavaScript saya:

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

Masalah yang saya miliki adalah dua gambar pertama yang dihasilkan adalah sama dan gambar durasi-5 detik tidak dihasilkan. Saya menemukan bahwa gambar mini dibuat sebelum bingkai video dari waktu tertentu ditampilkan < video> menandai.

Misalnya, kapan video.currentTime = 5, gambar frame 0s dihasilkan. Kemudian frame video melompat ke waktu 5 detik. Jadi ketika video.currentTime = 10, gambar frame 5s dihasilkan.


32
2017-10-04 06:59


asal


Jawaban:


Sebab

Masalahnya adalah mencari video (dengan mengaturnya currentTime) tidak sinkron.

Anda perlu mendengarkan seeked acara atau yang lain itu akan mengambil risiko frame aktual yang mungkin nilai lama Anda.

Karena asynchronous Anda tidak harus menggunakan setInterval() karena asynchronous juga dan Anda tidak akan dapat melakukan sinkronisasi dengan benar ketika frame berikutnya dicari. Tidak perlu digunakan setInterval() karena kami akan memanfaatkan seeked bukan acara yang akan membuat semuanya tetap sinkron.

Larutan

Dengan menulis ulang kode sedikit Anda dapat menggunakan seeked acara untuk pergi melalui video untuk menangkap frame yang benar karena acara ini memastikan kita bahwa kita benar-benar pada frame yang kami minta dengan pengaturan currentTime milik.

Contoh

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

Tambahkan event handler ini ke pesta:

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

Demo di sini


41
2017-10-04 07:55