webentwicklung-frage-antwort-db.com.de

HTML5 Video gepufferte Attributfunktionen

Ich entwerfe einen benutzerdefinierten HTML5-Videoplayer. Daher wird es einen eigenen Schieberegler zum Nachahmen des Videofortschritts haben. Daher muss ich den gesamten Puffer-Shebang eines HTML5-Videos verstehen.

Ich bin auf diesen Artikel gestoßen: Video Buffering . Das gepufferte Objekt besteht aus mehreren Zeitbereichen in linearer Reihenfolge der Startzeit. Folgendes konnte ich nicht herausfinden:

  1. Sagen Sie, das Video beginnt. Es geht bis zu 1:45 von selbst weiter (gelegentlich steckenbleiben, warten auf weitere Daten), danach springe ich plötzlich auf 32:45. Wenn ich nun nach einiger Zeit wieder auf 1:27 zurückspringe (innerhalb des Zeitbereichs, der vor dem Sprung zuerst geladen und durchgespielt wurde), wird er sofort wiedergegeben, da er bereits zuvor geladen wurde? Oder ist es so, dass, seit ich einen Sprung gemacht habe, dieser Teil verloren ist und erneut abgerufen werden muss? Ist das Verhalten in allen diesen Szenarien gleich?

  2. Angenommen, ich mache fünf oder sechs solcher Sprünge und warte jedes Mal, bis einige Daten nach dem Sprung geladen wurden. Bedeutet das, dass das buffered-Objekt alle Zeitbereiche gespeichert hat? Oder könnten einige verloren gehen? Ist es eine Art Stapel, bei dem die früheren Reichweiten wegfallen, wenn durch weitere Sprünge mehr Reichweiten geladen werden?

  3. Wird durch die Prüfung, ob das buffered-Objekt einen Zeitbereich hat, der bei 0 beginnt (Live-Streaming vergessen) und bei der Videodauer endet, sichergestellt, dass die gesamte Video-Ressource vollständig geladen ist? Wenn nicht, gibt es eine Möglichkeit zu wissen, dass das gesamte Video heruntergeladen wurde und ein beliebiger Teil gesucht werden kann, von dem aus das Video ohne Verzögerung sofort bis zum Ende abgespielt werden kann?

Die W3C-Spezifikationen sind hier nicht sehr klar, und ich kann auch keine ausreichend große (etwa mehr als eine Stunde dauernde) Remote-Video-Ressource zum Testen finden. 

18
SexyBeast

Wie Video gepuffert wird, ist von der Browser-Implementierung abhängig und kann daher von Browser zu Browser variieren.

Verschiedene Browser können verschiedene Faktoren verwenden, um zu bestimmen, ob ein Teil des Puffers erhalten oder verworfen werden soll. Alte Segmente, Speicherplatz, Speicher und Leistung sind typische Faktoren.

Die einzige Möglichkeit, wirklich zu wissen, besteht darin, zu "sehen", was der Browser lädt oder lädt.

Dafür habe ich einen Puffer-Viewer erstellt, der anzeigt, welcher Teil sich im Puffer befindet. Der Viewer zeigt den aktuellen und alle Teile des gesamten Puffers an:

ONLINE BUFFER VIEWER

Zum Beispiel - in Chrome habe ich ein paar Sekunden gespielt, dann habe ich etwa 30 Sekunden übersprungen, und Sie können sehen, dass ab dieser Position ein anderer Teil geladen wird.

(Der Puffer scheint auch an Keyframes gebunden zu sein, so dass es möglich ist, die n-Frames in diesem Puffer zu decodieren. Dies bedeutet, dass der Puffer etwas vor der tatsächlichen Position Daten laden kann.).

Example

Ich habe ein Demo-Video mit einer Länge von etwa 1 Minute zur Verfügung gestellt - dies reicht jedoch nicht aus, um korrekte Tests durchzuführen. Geben Sie frei, um Videoverbindungen bereitzustellen, die längere Videodateien enthalten (oder teilen Sie diese bitte mit, wenn Sie möchten, dass die Demoversion hiermit aktualisiert wird).

Die Hauptfunktion durchläuft das buffered-Objekt des Videoelements. Es werden alle vorhandenen Teile auf der Leinwand direkt unter dem Video rot dargestellt.

Sie können auf diesen Viewer klicken, um das Video an verschiedene Positionen zu verschieben.

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

Gemäß

das Attribut buffered enthält Informationen zu allen aktuell gepufferten Zeitbereichen. Wenn ein gepufferter Teil verloren geht, wird er meines Erachtens aus dem Objekt entfernt (für den Fall, dass dies jemals passiert).

Insofern scheint der letzte Link für das Verständnis der Angelegenheit sehr hilfreich zu sein (da er ein Codebeispiel enthält). Beachten Sie jedoch, dass es sich um Mozilla-Dokumente handelt und die Unterstützung in anderen Browsern möglicherweise anders ist.

Um Ihre Fragen zu beantworten

Sprich das Video startet. Es geht bis 1:45 von alleine weiter (gelegentlich blockiert es vielleicht und wartet auf weitere Daten), danach springe ich plötzlich auf 32:45. Wenn ich jetzt nach einiger Zeit auf 1:27 zurückspringe (innerhalb des Zeitbereichs, der ursprünglich geladen und durchgespielt wurde, bevor ich den Sprung ausgeführt habe), wird die Wiedergabe sofort beginnen, da sie bereits zuvor geladen wurde?

Es sollte beim Zurückspringen sofort wiedergegeben werden, es sei denn, der Puffer dieses Teils wurde entladen. Ich denke, es ist sehr vernünftig anzunehmen, dass Puffer oder Pufferbereiche irgendwann entladen werden, wenn die Gesamtpuffergröße ein bestimmtes Volumen überschreitet.

Angenommen, ich mache 5 oder 6 solcher Sprünge und warte jedes Mal einige Sekunden, bis nach dem Sprung einige Daten geladen sind. Bedeutet das, dass für das gepufferte Objekt alle diese Zeitbereiche gespeichert sind?

Ja, alle gepufferten Bereiche sollten über das Attribut lesbar sein.

Wird überprüft, ob das gepufferte Objekt einen Zeitbereich hat, der bei 0 beginnt (Live-Streaming vergessen) und bei der Videodauer endet, um sicherzustellen, dass die gesamte Videoressource vollständig geladen wurde?

Ja, dies ist das Codebeispiel im letzten Link. Anscheinend ist dies eine anwendbare Methode, um festzustellen, ob das gesamte Video geladen wurde.

if (buf.start(0) == 0 && buf.end(0) == v.duration)
7
Cobra_Fast
  1. Nahezu jeder Browser speichert die zwischengespeicherten Daten für diese Sitzung im Cache. Der Cache läuft ab, nachdem der Benutzer diese Seite verlassen hat. Ich glaube nicht, dass der Benutzer die Seite jedes Mal laden muss, wenn er das Video von einem Punkt lädt, an dem das Video geladen wurde. Der Benutzer wird nur dann mit diesem Problem konfrontiert, wenn der Server alle Cache-Daten löscht. Das HTML5-Video-Tag unterstützt dies und speichert das Video bis zu dem Punkt, an dem es geladen wurde.

  2. Dies bedeutet nicht, dass die Sitzung verloren gegangen ist. Dies bedeutet, dass entweder das Objekt (wenn Sie Flash Player verwenden) nach bestimmten Daten an diesem bestimmten Punkt sucht, oder dass das html5-Videotag aufgrund von Fehlern bei der INTERNET-Verbindung Probleme aufweist. oder einige andere Serverfehler.

  3. Die Metadaten werden automatisch geladen. Solange Sie diese <audio preload="none"... nicht verwenden, wird der Browser dazu veranlasst, nichts vom Server herunterzuladen. Sie können sie wie folgt verwenden:
    <audio preload="auto|metadata|none"... Wenn Sie none verwenden, wird nichts heruntergeladen, es sei denn, der Benutzer klickt auf die Wiedergabeschaltfläche. Metadaten laden den Namen, das Timing und andere Metadaten vom Server herunter. Die Datei wird jedoch nicht irgendwie geladen, sobald die Seite geladen wird.

Ich werde Sie immer darauf hinweisen, einige Dokumentationen von jQuery zu lesen. Mit der jQuery können Sie den Inhalt mit Hilfe der ajax-API ändern und aktualisieren und auch hilfreich sein. Ich hoffe du hast Erfolg! Prost.

Obwohl die Beschreibung der akzeptierten Antwort ausgezeichnet ist, habe ich mich aus verschiedenen Gründen für die Aktualisierung des Codebeispiels entschieden:

  • Die Aufgabe zum Rendern des Fortschritts sollte wirklich nur bei einem progress-Ereignis ausgelöst werden.
  • Die Aufgabe zum Fortschrittsrendern wird mit einigen anderen Aufgaben vermischt, wie dem Zeitstempel und der Abspielposition.
  • Der Code bezieht sich auf mehrere DOM-Elemente anhand ihrer IDs, ohne document.getElementById() zu verwenden.
  • Die Variablennamen waren alle verdeckt.
  • Ich dachte, eine for()-Schleife wäre eleganter als eine while()-Schleife.

Beachten Sie, dass ich den Abspielkopf und den Zeitstempel entfernt habe, um den Code sauber zu halten, da sich diese Antwort ausschließlich auf die Visualisierung des Videopuffers konzentriert.

LINK ZU ONLINE VIDEO PUFFER VISUALISER

loop()-Funktion der akzeptierten Antwort neu schreiben:

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