web-dev-qa-db-ja.com

HTML5ビデオバッファリング属性機能

カスタムHTML5ビデオプレーヤーを設計しています。したがって、ビデオの進行状況を模倣する独自のカスタムスライダーがあるため、HTML5ビデオのバッファリングシバン全体を理解する必要があります。

私はこの記事に出くわしました: ビデオバッファリング 。バッファリングされたオブジェクトは、開始時間の線形順序で複数の時間範囲で構成されていると言います。しかし、次のことがわかりませんでした。

  1. ビデオが開始すると言います。単独で1:45まで継続し(場合によってはストールし、さらにデータを待機する)、その後突然32:45にジャンプします。しばらくして、(ジャンプする前に最初にロードされて再生された時間範囲内で)1:27に戻ると、以前にロードされていたのですぐに再生を開始しますか?それとも、私がジャンプをしたので、その部分が失われ、再び取得する必要があるということですか?いずれにせよ、そのようなすべてのシナリオで動作は一貫していますか?

  2. このようなジャンプを5回または6回行い、そのたびに、ジャンプ後にデータがロードされるのを数秒間待ちます。それは、bufferedオブジェクトにそれらのすべての時間範囲が格納されることを意味しますか?または、一部が迷子になる可能性がありますか?それはスタックのようなものですか?さらにジャンプしてより多くの範囲がロードされると以前の範囲がポップされますか?

  3. bufferedオブジェクトに1つの時間範囲が0(ライブストリーミングを忘れる)で始まり、ビデオ期間の長さで終わるかどうかをチェックすることで、ビデオリソース全体が完全にロードされたことを確認できますか?そうでない場合、ビデオ全体がダウンロードされており、ビデオが最後まで途切れることなく連続して再生できる部分がシーク可能であることを知る方法はありますか?

W3Cの仕様はこの点についてあまり明確ではありません。また、テストするのに適切な大きさ(1時間以上)のリモートビデオリソースが見つかりません。

21
SexyBeast

ビデオのバッファリング方法はブラウザの実装に依存するため、ブラウザごとに異なる場合があります。

さまざまなブラウザがさまざまな要因を使用して、バッファの一部を保持するか破棄するかを決定できます。古いセグメント、ディスク容量、メモリ、パフォーマンスが一般的な要因です。

本当に知る唯一の方法は、ブラウザが持っているものや読み込んでいるものを「見る」ことです。

たとえば-in Chrome私は数秒プレイした後、約30秒スキップし、その位置から始まる別のパーツのロードを開始することがわかります。

(バッファはキーフレームにバインドされているように見えるため、バッファ内のnフレームをデコードできます。これは、バッファが実際の位置の少し前にデータのロードを開始できることを意味します)。

Example

約1分間のデモビデオを提供しましたが、適切なテストを行うのに十分な長さではありません。より長いビデオを含むビデオリンクを無料で提供します(または、これでデモを更新したい場合は共有してください)。

メイン関数は、ビデオ要素のbufferedオブジェクトを反復処理します。赤で表示されているビデオの真下のキャンバスに存在するすべてのパーツをレンダリングします。

このビューアをクリックして(ビットではなくドラッグ)、ビデオを別の位置に移動できます。

/// buffer viewer loop (updates about every 2nd frame)
function loop() {

    var b = vid.buffered,  /// get buffer object
        i = b.length,      /// counter for loop
        w = canvas.width,  /// cache canvas width and height
        h = canvas.height,
        vl = vid.duration, /// total video duration in seconds
        x1, x2;            /// buffer segment mark positions

    /// clear canvas with black
    ctx.fillStyle = '#000';
    ctx.fillRect(0, 0, w, h);

    /// red color for loaded buffer(s)
    ctx.fillStyle = '#d00';

    /// iterate through buffers
    while (i--) {
        x1 = b.start(i) / vl * w;
        x2 = b.end(i) / vl * w;
        ctx.fillRect(x1, 0, x2 - x1, h);
    }

    /// draw info
    ctx.fillStyle = '#fff';

    ctx.textBaseline = 'top';
    ctx.textAlign = 'left';
    ctx.fillText(vid.currentTime.toFixed(1), 4, 4);

    ctx.textAlign = 'right';
    ctx.fillText(vl.toFixed(1), w - 4, 4);

    /// draw cursor for position
    x1 = vid.currentTime / vl * w;

    ctx.beginPath();
    ctx.arc(x1, h * 0.5, 7, 0, 2 * Math.PI);
    ctx.fill();

    setTimeout(loop, 29);
}
31
user1693593

による

buffered属性は、現在バッファリングされているすべての時間範囲に関する情報を保持します。私の理解では、バッファリングされた部分が失われた場合、オブジェクトから削除されます(それが発生した場合)。

特に最後のリンクは問題を理解するのに非常に役立つようです(コードサンプルを提供しているため)が、これらはmozillaドキュメントであり、他のブラウザではサポートが異なる可能性があることに注意してください。

質問に答えるために

ビデオが開始すると言います。単独で1:45まで継続し(場合によってはストールし、さらにデータを待機する)、その後突然32:45にジャンプします。しばらくして、(ジャンプする前に最初にロードされて再生された時間範囲内で)1:27に戻ると、以前にロードされていたのですぐに再生を開始しますか?

そのshouldは、その部分のバッファがアンロードされない限り、ジャンプしてすぐに再生します。全体のバッファサイズが特定のボリュームを超える場合、ある時点でバッファまたはバッファ範囲がアンロードされると仮定することは非常に合理的だと思います。

このようなジャンプを5回または6回行い、そのたびに、ジャンプ後にデータがロードされるのを数秒間待ちます。それは、バッファリングされたオブジェクトにそれらのすべての時間範囲が保存されることを意味しますか?

はい、すべてのバッファされた範囲は属性を介して読み取り可能である必要があります。

バッファリングされたオブジェクトに、0から始まる1つの時間範囲(ライブストリーミングを忘れる)があり、ビデオ期間の長さで終わるかどうかをチェックすると、ビデオリソース全体が完全にロードされます。

はい、これは最後のリンクのコード例です。どうやらこれは、ビデオ全体がロードされたかどうかを判断するための適用可能な方法です。

if (buf.start(0) == 0 && buf.end(0) == v.duration)
7
Cobra_Fast
  1. ほとんどすべてのブラウザーは、そのセッションのキャッシュされたデータをキャッシュに保存します。キャッシュは、ユーザーがそのページから移動すると失効します。ユーザーは、ビデオがロードされたポイントからビデオをロードするたびにページをロードする必要があるとは思わない。ユーザーがこの問題に直面するのは、サーバーがすべてのキャッシュデータを消去している場合のみです。 HTML5ビデオタグはこれをサポートし、ビデオがロードされるまでポイントまでビデオを保存します。

  2. セッションが失われたことを意味するのではなく、オブジェクト(フラッシュプレーヤーを使用している場合)が特定のポイントからデータを探しているか、またはhtml5ビデオタグがインターネット接続障害のために問題を抱えていることを意味します。またはその他のサーバーエラー。

  3. これを使用するまで、メタデータは自動的にロードされます<audio preload="none"...これにより、ブラウザはサーバーから何もダウンロードしないようになります。次のように使用できます。
    <audio preload="auto|metadata|none"... noneを使用すると、ユーザーが再生ボタンをクリックしない限り何もダウンロードされず、メタデータはサーバーから名前、タイミング、その他のメタデータをダウンロードしますが、ファイルはダウンロードせず、ページが読み込まれるとすぐにダウンロードを開始します。

JQueryによるいくつかのドキュメントを読むように常に指示します。 jQueryを使用すると、ajax APIを使用してコンテンツを変更および更新できるため、これも役立ちます。あなたが成功することを願っています!乾杯。

受け入れられた答えの説明は素晴らしいものですが、いくつかの理由から、コードサンプルを更新することにしました。

  • プログレスレンダータスクは、実際にはprogressイベントでのみ起動する必要があります。
  • 進行状況レンダリングタスクは、タイムスタンプや再生ヘッドの位置の描画など、他のいくつかのタスクと混同されます。
  • コードは、document.getElementById()を使用せずに、IDで複数のDOM要素を参照します。
  • 変数名はすべて不明瞭でした。
  • フォワードfor()ループは、バックワードwhile()ループよりもエレガントだと思いました。

この回答は純粋にビデオバッファの視覚化に焦点を合わせているため、コードをクリーンに保つために再生ヘッドとタイムスタンプを削除したことに注意してください。

オンラインビデオバッファビジュアライザへのリンク

受け入れられた回答のloop()関数の書き換え:

function drawProgress(canvas, buffered, duration){
    // I've turned off anti-aliasing since we're just drawing rectangles.
    var context = canvas.getContext('2d', { antialias: false });
    context.fillStyle = 'blue';

    var width = canvas.width;
    var height = canvas.height;
    if(!width || !height) throw "Canvas's width or height weren't set!";
    context.clearRect(0, 0, width, height); // clear canvas

    for(var i = 0; i < buffered.length; i++){
        var leadingEdge = buffered.start(i) / duration * width;
        var trailingEdge = buffered.end(i) / duration * width;
        context.fillRect(leadingEdge, 0, trailingEdge - leadingEdge, height);
    }
}
1
Jamie Birch