J'essaie de tester si une vidéo est saccadée. J'ai remarqué que l'événement pause
n'est pas déclenché lorsque la vidéo s'interrompt pour la mise en mémoire tampon. Quelle est la meilleure façon de détecter si la vidéo s'est interrompue pour la mise en mémoire tampon?
Je l'ai fait en inspectant la progression du lecteur toutes les x millisecondes, par ex. 50. Si le joueur n'a pas avancé autant que prévu, nous tamponnons. C'est assez fiable, car j'ai trouvé que d'autres événements tels que waiting
ou stalled
ne sont pas déclenchés dans tous les cas de mise en mémoire tampon vidéo.
Notez que l'intervalle doit être plus grand que la différence inter-trame attendue, mais je suis sûr que vous ne voudrez pas être aussi précis de toute façon. Une estimation du temps de mise en mémoire tampon à ± 300 ms serait toujours correcte, étant donné que les humains ne peuvent très probablement pas percevoir de différences dans cette région.
Il est toutefois important de vérifier si l'utilisateur n'a pas activement interrompu la lecture.
var checkInterval = 50.0 // check every 50 ms (do not use lower values)
var lastPlayPos = 0
var currentPlayPos = 0
var bufferingDetected = false
var player = document.getElementById('videoPlayer')
setInterval(checkBuffering, checkInterval)
function checkBuffering() {
currentPlayPos = player.currentTime
// checking offset should be at most the check interval
// but allow for some margin
var offset = (checkInterval - 20) / 1000
// if no buffering is currently detected,
// and the position does not seem to increase
// and the player isn't manually paused...
if (
!bufferingDetected
&& currentPlayPos < (lastPlayPos + offset)
&& !player.paused
) {
console.log("buffering")
bufferingDetected = true
}
// if we were buffering but the player has advanced,
// then there is no buffering
if (
bufferingDetected
&& currentPlayPos > (lastPlayPos + offset)
&& !player.paused
) {
console.log("not buffering anymore")
bufferingDetected = false
}
lastPlayPos = currentPlayPos
}
L'événement que vous recherchez est waiting
.
De la spec :
Un événement DOM en attente peut être déclenché à la suite d'un élément qui est en cours de lecture arrêtant la lecture en raison de la modification de son attribut readyState à une valeur inférieure à HAVE_FUTURE_DATA.
L'état paused
ne change pas car la vidéo est toujours "potentiellement en cours de lecture" (c'est-à-dire "en train d'essayer" de jouer). L'événement waiting
se déclenche donc. Lorsque suffisamment de données ont été chargées, playing
se déclenche.
Vous pouvez également vérifier l'état à tout moment en consultant deux propriétés, networkState et readyState
if (video.networkState === video.NETWORK_LOADING) {
// The user agent is actively trying to download data.
}
if (video.readyState < video.HAVE_FUTURE_DATA) {
// There is not enough data to keep playing from this point
}
Vous pouvez simplement vérifier la durée du contenu vidéo en mémoire tampon et si elle est inférieure à la partie en cours de lecture, puis déclencher l'événement de pause.En utilisant le code suivant, vous pouvez vérifier la durée de la vidéo en mémoire tampon.
$vid = $("#video_id");
$vid.on('progress', function(e) {
percentVidLoaded = null;
// FF4+, Chrome
if ($vid[0] && $vid[0].buffered && $vid[0].buffered.length > 0 && $vid[0].buffered.end && $vid[0].duration) {
percentVidLoaded = $vid[0].buffered.end(0) / $vid[0].duration;
}
/* Some browsers (e.g., FF3.6 and Safari 5) cannot calculate target.bufferered.end()
* to be anything other than 0. If the byte count is available we use this instead.
* Browsers that support the else if do not seem to have the bufferedBytes value and
* should skip to there.
*/
else if ($vid[0] && $vid[0].bytesTotal != undefined && $vid[0].bytesTotal > 0 && $vid[0].bufferedBytes != undefined) {
percentVidLoaded = $vid[0].bufferedBytes / $vid[0].bytesTotal;
}
if (percentVidLoaded !== null) {
percentVidLoaded = 100 * Math.min(1, Math.max(0, percentVidLoaded));
}
});
Vous devez vérifier si la mémoire tampon est inférieure à la durée vidéo actuelle. Si c'est le cas, la vidéo est mise en mémoire tampon. Cependant, vous devez vérifier cela avec une petite tolérance pour vous assurer de le détecter avant qu'il ne soit nécessaire de le tamponner.
Exemple:
var video = document.getElementById("myVideo");
var prevBuffer = {
"buffer": null,
"time": null
};
var isBuffering = function(){
if(video && video.buffered && video.buffered.end && video.buffered.length > 0){
var buffer = video.buffered.end(0);
var time = video.currentTime;
// Check if the video hangs because of issues with e.g. performance
if(prevBuffer.buffer === buffer && prevBuffer.time === time && !video.paused){
return true;
}
prevBuffer = {
"buffer": buffer,
"time": time
};
// Check if video buffer is less
// than current time (tolerance 3 sec)
if((buffer - 3) < time){
return true;
}
}
return false;
};
video.addEventListener("play", function(e){
// Make sure this handler is only called once
e.target.removeEventListener(e.type, arguments.callee);
// Give browsers 3secs time to buffer
setTimeout(function(){
// As "progress", "stalled" or "waiting" aren't fired
// reliable, we need to use an interval
var interval = setInterval(function(){
if(isBuffering()){
clearInterval(interval);
console.log("Buffering");
}
}, 500);
}, 3000);
});