2013-10-04 13 views
28

Chcę przechwytywać klatkę z wideo co 5 sekund.Przechwytywanie klatek wideo z HTML5 i JavaScriptem

To jest mój kod 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); 
} 

Problem mam jest 1 dwa obrazy generowane są takie same, a drugi obraz czas trwania-5 nie jest generowany. Dowiedziałem się, że miniatura jest generowana, zanim ramka wideo o określonej godzinie zostanie wyświetlona w tagu < video>.

Na przykład, gdy video.currentTime = 5, generowany jest obraz ramki 0s. Następnie ramka wideo przeskakuje do czasu 5s. Tak więc, gdy video.currentTime = 10, generowany jest obraz ramki 5s.

+1

Co jest theCanvas na swojej funkcji generateThumbnail? Czy możesz podać tagi HTML dla tego pytania, aby były bardziej przydatne? Próbuję zrobić to samo, ale nie jestem pewien, jak powinny być ogłaszane na stronie. Dzięki! – alejosoft

Odpowiedz

36

Przyczyna

Problem polega na tym, że poszukiwanie wideo (poprzez ustawienie to currentTime) jest asynchroniczna.

Musisz posłuchać zdarzenia seeked, ponieważ może to spowodować, że pobierzesz aktualną ramkę, która prawdopodobnie jest Twoją starą wartością.

Ponieważ jest to ustawienie asynchroniczne, nie wolno używać wartości setInterval(), ponieważ jest ona również asynchroniczna i nie będzie można poprawnie przeprowadzić synchronizacji, gdy zostanie wykonana następna klatka. Nie ma potrzeby używania numeru setInterval(), ponieważ wykorzystamy zdarzenie seeked, dzięki czemu wszystko będzie zsynchronizowane.

Rozwiązanie

Przez ponownego pisania kodu trochę można użyć zdarzenia seeked przejść filmie uchwycić prawidłową ramkę jako wydarzenie to gwarantuje nam, że jesteśmy rzeczywiście w ramce poprosiliśmy o ustawienie currentTime Właściwość.

Przykład

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

Dodaj obsługi zdarzeń do strony:

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 here

+2

Próbowałem użyć twojego kodu. Teraz mam inny problem. Ze względu na poszukiwanie, gdy szukałem wideo klikając na osi czasu, generowany jest również obraz. Ale nie chcę tego. ** Edytuj ** Rozwiązałem już ten problem. Dziękuję Ci. – Lin

+0

'video.currentTime = i;' nie wyzwala dla mnie żadnego szukanego zdarzenia. – Michael

+0

@Michael, czy wtedy rozwiązałeś swój problem? – Martian2049

Powiązane problemy