Je veux capturer une image de la vidéo toutes les 5 secondes.
Voici mon 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);
}
Le problème que j'ai est que les deux premières images générées sont les mêmes et que l'image de durée-5 secondes n'est pas générée. J'ai découvert que la vignette est générée avant que l'image vidéo de l'heure spécifique ne s'affiche dans < video>
tag.
Par exemple, lorsque video.currentTime = 5
, l'image de la trame 0 est générée. Ensuite, l'image vidéo saute au temps 5s. Donc quand video.currentTime = 10
, l'image de l'image 5s est générée.
Le problème est que la recherche de vidéo (en définissant c'est currentTime
) est asynchrone.
Vous devez écouter l'événement seeked
sinon il risque de prendre la trame actuelle réelle qui est probablement votre ancienne valeur.
Comme il est asynchrone, vous ne devez pas utiliser la setInterval()
car elle est également asynchrone et vous ne pourrez pas synchroniser correctement lorsque la prochaine trame sera recherchée. Il n'est pas nécessaire d'utiliser setInterval()
car nous utiliserons à la place l'événement seeked
qui gardera tout synchronisé.
En réécrivant un peu le code, vous pouvez utiliser l'événement seeked
pour parcourir la vidéo afin de capturer l'image correcte car cet événement nous garantit que nous sommes réellement à l'image que nous avons demandée en définissant currentTime
propriété.
Exemple
// 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;
});
Ajoutez ce gestionnaire d'événements à la fête:
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
}
});