web-dev-qa-db-ja.com

HTML5ビデオがバッファリングのために一時停止したかどうかを検出する方法は?

ビデオが途切れているかどうかをテストしようとしています。ビデオがバッファリングのために一時停止しても、pauseイベントはトリガーされないことに気付きました。ビデオがバッファリングのために一時停止したかどうかを検出する最良の方法は何ですか?

36
Supreet Totagi

プレーヤーの進行状況をxミリ秒ごとに検査することでこれを行いました。 50.プレイヤーが期待したほど進んでいない場合、バッファリングしています。 waitingstalledなどの他のイベントがビデオバッファリングのすべてのケースで発生するわけではないことがわかったため、これは非常に信頼できます。

間隔は、予想されるフレーム間差よりも大きくなければならないことに注意してください。しかし、とにかく正確になりたいとは思わないでしょう。人間がその領域の違いを認識できない可能性が最も高いことを考えると、±300ms以内のバッファリング時間の推定はそれでも問題ありません。

ただし、ユーザーが再生をアクティブに一時停止していないかどうかを確認することが重要です。

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
}
43
slhck

探しているイベントはwaitingです。

spec から:

待機中のDOMイベントは、readyState属性がHAVE_FUTURE_DATAよりも低い値に変更されているために再生を停止している可能性のある要素の結果として発生する可能性があります。

pausedの状態は、ビデオがまだ「潜在的に再生中」(つまり、「再生しようとしている」)であるため変更されません。そのため、waitingイベントが発生します。十分なデータがロードされると、playingが起動します。

networkStatereadyState の2つのプロパティを調べることで、いつでも状態を確認することもできます

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
}
18
brianchirls

バッファリングされたビデオコンテンツの長さを確認し、現在の再生部分より短い場合は、一時停止イベントを起動するだけです。次のコードを使用して、バッファリングされたビデオの長さを確認できます。

$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));
    }
});
1
Arjun Thakur

バッファが現在のビデオ時間よりも短いかどうかを確認する必要があります。その場合、ビデオはバッファリングされています。ただし、バッファリングする必要がある前にそれを確実に検出するには、小さな許容値でこれをチェックする必要があります。

例:

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