Überschreiten des Pufferkontingents

Joe Medley
Joe Medley

Wenn Sie mit Media Source Extensions (MSE) arbeiten, müssen Sie sich letztendlich möglicherweise mit einem zu vollen Puffer auseinandersetzen. In diesem Fall erhalten Sie eine sogenannte QuotaExceededError. In diesem Artikel werde ich einige Möglichkeiten behandeln, damit umzugehen.

Was ist der QuotaExceededError?

Im Grunde erhalten Sie QuotaExceededError, wenn Sie versuchen, Ihrem SourceBuffer-Objekt zu viele Daten hinzuzufügen. Dieser Fehler kann ebenfalls auftreten, wenn einem übergeordneten MediaSource-Element weitere SourceBuffer-Objekte hinzugefügt werden. Das würde den Rahmen dieses Artikels sprengen.) Wenn SourceBuffer zu viele Daten enthält, wird durch den Aufruf von SourceBuffer.appendBuffer() die folgende Meldung im Fenster der Chrome-Konsole ausgelöst.

Kontingentkonsolenfehler.

Hierzu gibt es einige Dinge zu beachten. Beachten Sie zuerst, dass der Name QuotaExceededError nirgendwo in der Nachricht erscheint. Dazu setzen Sie einen Haltepunkt an einer Stelle, an der Sie den Fehler abfangen und im Überwachungs- oder Bereichsfenster untersuchen können. Dies wird im Folgenden gezeigt.

Zeitfenster zum Überwachen von Kontingenten

Zweitens gibt es keine definitive Möglichkeit herauszufinden, wie viele Daten SourceBuffer verarbeiten kann.

Verhalten in anderen Browsern

Zum Zeitpunkt der Erstellung dieses Dokuments wirft Safari in vielen seiner Builds kein QuotaExceededError. Stattdessen werden Frames mithilfe eines zweistufigen Algorithmus entfernt und angehalten, wenn genügend Platz für die Verarbeitung von appendBuffer() vorhanden ist. Erstens werden Frames zwischen 0 und 30 Sekunden vor der aktuellen Zeit in 30-Sekunden-Blöcken freigegeben. Als Nächstes werden Frames in 30-Sekunden-Blöcken von der Dauer bis zu 30 Sekunden nach currentTime freigegeben. Weitere Informationen hierzu finden Sie in einem WebKit-Änderungset aus dem Jahr 2014.

Glücklicherweise geben Chrome, Edge und Firefox diesen Fehler zurück. Wenn Sie einen anderen Browser verwenden, müssen Sie die Tests selbst durchführen. François Beauforts Quellpuffer-Limit-Test ermöglicht es Ihnen zumindest, das Verhalten zu beobachten.

Wie viele Daten kann ich anhängen?

Die genaue Anzahl variiert von Browser zu Browser. Da Sie die Menge der aktuell angehängten Daten nicht abfragen können, müssen Sie im Auge behalten, wie viele Daten Sie selbst anfügen. Hier sind die besten Daten, die ich zum Zeitpunkt der Erstellung Bei Chrome sind diese Zahlen Obergrenzen, d. h., sie können kleiner sein, wenn das System Speicherauslastung stößt.

Chrome Chromecast* Firefox Safari Edge
Video 150MB 30MB 100 MB 290MB Unbekannt
Audio 12MB 2 MB 15 MB 14MB Unbekannt
  • oder ein anderes Chrome-Gerät mit begrenztem Arbeitsspeicher.

Was soll ich tun?

Da die Menge der unterstützten Daten sehr unterschiedlich ist und Sie die Datenmenge in einem SourceBuffer nicht finden können, müssen Sie sie indirekt über die Verarbeitung von QuotaExceededError abrufen. Sehen wir uns dazu ein paar Möglichkeiten an.

Es gibt mehrere Ansätze für den Umgang mit QuotaExceededError. In Wirklichkeit ist eine Kombination aus einem oder mehreren Ansätzen am besten. Ihr Ansatz sollte sein, die Arbeit darauf zu basieren, wie viel Sie abrufen, und versuchen, über HTMLMediaElement.currentTime hinaus anzuhängen und diese Größe basierend auf QuotaExceededError anzupassen. Auch die Verwendung eines Manifests wie einer MPD-Datei (MPEG-DASH) oder einer M3u8-Datei (HLS) kann Ihnen dabei helfen, den Überblick über die Daten zu behalten, die Sie an den Zwischenspeicher anhängen.

Sehen wir uns jetzt mehrere Ansätze für den Umgang mit dem QuotaExceededError an.

  • Entfernen Sie nicht benötigte Daten und hängen Sie sie noch einmal an.
  • Hängen Sie kleinere Fragmente an.
  • Verringern Sie die Wiedergabeauflösung.

Sie können sie zwar auch in Kombination verwenden, ich werde sie aber nacheinander behandeln.

Nicht benötigte Daten entfernen und noch einmal anhängen

Eigentlich sollte sie heißen: „Daten, die am wahrscheinlichsten bald verwendet werden, entfernen und dann das Anfügen von Daten wiederholen, die wahrscheinlich bald verwendet werden“. Der Titel war zu lang. Du musst dir nur merken, was ich wirklich meine.

Das Entfernen aktueller Daten ist nicht so einfach wie das Aufrufen von SourceBuffer.remove(). Um Daten aus dem SourceBuffer zu entfernen, muss das Update-Flag auf „false“ gesetzt sein. Ist dies nicht der Fall, rufen Sie SourceBuffer.abort() auf, bevor Sie Daten entfernen.

Es gibt einige Dinge zu beachten, wenn du SourceBuffer.remove() aufrufst.

  • Das könnte sich negativ auf die Wiedergabe auswirken. Wenn Sie beispielsweise möchten, dass das Video bald noch einmal oder in einer Schleife wiedergegeben wird, sollten Sie den Anfang des Videos nicht entfernen. Wenn Sie oder der Nutzer zu einem Teil des Videos springen, in dem Sie Daten entfernt haben, müssen Sie diese Daten noch einmal anhängen, um diese Suche zu erfüllen.
  • Entferne so konservativ wie möglich. Vorsicht: Entfernen Sie die aktuell abspielende Gruppe von Frames, die im Keyframe bei oder vor currentTime beginnt, da dies zu einer Verzögerung bei der Wiedergabe führen kann. Diese Informationen müssen möglicherweise von der Webanwendung aus dem Bytestream geparst werden, wenn sie im Manifest nicht verfügbar sind. Ein Medienmanifest oder App-Kenntnisse zu Keyframe-Intervallen in den Medien können bei der Auswahl der Entfernungsbereiche Ihrer App helfen, damit die aktuell wiedergegebenen Medien nicht entfernt werden. Was auch immer Sie entfernen, entfernen Sie nicht die aktuell wiedergegebene Gruppe von Bildern oder die ersten Bilder darüber hinaus. Im Allgemeinen sollten Sie die Medien nicht nach dem aktuellen Zeitpunkt entfernen, es sei denn, Sie sind sicher, dass die Medien nicht mehr benötigt werden. Wenn Sie ihn nah am Abspielkopf entfernen, kann dies zu einer Verzögerung führen.
  • In Safari 9 und Safari 10 wird SourceBuffer.abort() nicht richtig implementiert. Es werden Fehler ausgegeben, die die Wiedergabe anhalten. Glücklicherweise gibt es hier und hier offene Programmfehler-Tracker. In der Zwischenzeit müssen Sie dies irgendwie umgehen. Shaka Player erledigt dies, indem er in diesen Safari-Versionen eine leere abort()-Funktion überschneidet.

Kleinere Fragmente anhängen

Das entsprechende Verfahren wird unten beschrieben. Dies funktioniert möglicherweise nicht in jedem Fall, hat aber den Vorteil, dass die Größe der kleineren Blöcke an Ihre Anforderungen angepasst werden kann. Außerdem ist kein Zurück zum Netzwerk erforderlich, was für einige Nutzer zusätzliche Datenkosten verursachen könnte.

const pieces = new Uint8Array([data]);
(function appendFragments(pieces) {
    if (sourceBuffer.updating) {
    return;
    }
    pieces.forEach(piece => {
    try {
        sourceBuffer.appendBuffer(piece);
    }
    catch e {
        if (e.name !== 'QuotaExceededError') {
        throw e;
        }

        // Reduction schedule: 80%, 60%, 40%, 20%, 16%, 12%, 8%, 4%, fail.
        const reduction = pieces[0].byteLength * 0.8;
        if (reduction / data.byteLength < 0.04) {
        throw new Error('MediaSource threw QuotaExceededError too many times');
        }
        const newPieces = [
        pieces[0].slice(0, reduction),
        pieces[0].slice(reduction, pieces[0].byteLength)
        ];
        pieces.splice(0, 1, newPieces[0], newPieces[1]);
        appendBuffer(pieces);  
    }
    });
})(pieces);

Wiedergabeauflösung verringern

Dies ist vergleichbar mit dem Entfernen aktueller Daten und dem erneuten Anhängen. Die beiden können auch zusammen erstellt werden, das folgende Beispiel zeigt jedoch nur, dass die Auflösung verringert wird.

Bei dieser Technik sollten Sie Folgendes beachten:

  • Sie müssen ein neues Initialisierungssegment anhängen. Sie müssen dies jedes Mal tun, wenn Sie Darstellungen ändern. Das neue Initialisierungssegment muss sich auf die folgenden Mediensegmente beziehen.
  • Der Darstellungszeitstempel der angehängten Medien sollte dem Zeitstempel der Daten im Zwischenspeicher möglichst genau entsprechen, aber nicht nach vorn springen. Eine Überschneidung der zwischengespeicherten Daten kann je nach Browser zu einem Ruckeln oder einer kurzen Verzögerung führen. Unabhängig davon, was Sie anhängen, sollten Sie den Abspielkopf nicht überlappen, da sonst Fehler ausgegeben werden.
  • Die Suche kann die Wiedergabe unterbrechen. Sie könnten versucht sein, zu einem bestimmten Ort zu springen und die Wiedergabe von dort aus fortzusetzen. Beachten Sie, dass dies zu einer Unterbrechung der Wiedergabe führt, bis die Suche abgeschlossen ist.