Wenn du mit Media Source Extensions (MSE) arbeitest, musst du irgendwann mit einem übervollen Puffer umgehen. In diesem Fall erhalten Sie eine sogenannte QuotaExceededError
. In diesem Artikel stelle ich einige Möglichkeiten vor, wie Sie damit umgehen können.
Was ist QuotaExceededError?
Im Grunde ist QuotaExceededError
das Ergebnis, wenn Sie Ihrem SourceBuffer
-Objekt zu viele Daten hinzufügen. (Dieser Fehler kann auch auftreten, wenn einem übergeordneten MediaSource
-Element weitere SourceBuffer
-Objekte hinzugefügt werden. Das ist nicht Gegenstand dieses Artikels.) Wenn SourceBuffer
zu viele Daten enthält, wird durch das Aufrufen von SourceBuffer.appendBuffer()
die folgende Meldung im Chrome-Konsolenfenster ausgelöst.

Dabei sind einige Dinge zu beachten. Beachten Sie zuerst, dass der Name QuotaExceededError
in der Nachricht nicht vorkommt. Legen Sie dazu einen Haltepunkt an einer Stelle fest, an der Sie den Fehler abfangen und im Watch- oder Scope-Fenster untersuchen können. Das habe ich unten dargestellt.

Zweitens gibt es keine definitive Möglichkeit, herauszufinden, wie viele Daten SourceBuffer
verarbeiten kann.
Verhalten in anderen Browsern
Zum Zeitpunkt der Erstellung dieses Artikels wird in vielen Safari-Builds keine QuotaExceededError
ausgegeben. Stattdessen werden Frames mit einem zweistufigen Algorithmus entfernt. Der Vorgang wird beendet, wenn genügend Platz für die appendBuffer()
vorhanden ist. Zuerst werden Frames zwischen 0 und 30 Sekunden vor der aktuellen Zeit in 30-Sekunden-Chunks freigegeben. Als Nächstes werden Frames in 30-Sekunden-Chunks von der Dauer rückwärts bis zu 30 Sekunden nach currentTime
freigegeben. Weitere Informationen finden Sie in einer Webkit-Änderungsliste aus dem Jahr 2014.
Glücklicherweise wird dieser Fehler nicht nur in Chrome, sondern auch in Edge und Firefox ausgegeben. Wenn Sie einen anderen Browser verwenden, müssen Sie die Tests selbst durchführen. Der Test zum Grenzwert des Quellpuffers von François Beaufort ist zwar nicht das, was Sie für einen echten Mediaplayer entwickeln würden, aber Sie können damit zumindest das Verhalten beobachten.
Wie viele Daten kann ich anhängen?
Die genaue Anzahl variiert je nach Browser. Da Sie nicht nach der Menge der derzeit angehängten Daten fragen können, müssen Sie selbst nachverfolgen, wie viel Sie anhängen. Was du dir ansehen solltest, kannst du anhand der folgenden Daten entscheiden, die ich zum Zeitpunkt der Erstellung dieses Artikels zusammengetragen habe. Bei Chrome sind diese Zahlen Obergrenzen. Sie können also kleiner sein, wenn das System unter Speichermangel leidet.
Chrome | Chromecast* | Firefox | Safari | Edge | |
---|---|---|---|---|---|
Video | 150 MB | 30 MB | 100 MB | 290 MB | Unbekannt |
Audio | 12 MB | 2 MB | 15 MB | 14 MB | Unbekannt |
- oder ein anderes Chrome-Gerät mit begrenztem Arbeitsspeicher
Was soll ich tun?
Da die Anzahl der unterstützten Daten sehr unterschiedlich ist und Sie die Datenmenge nicht in einer SourceBuffer
finden, müssen Sie sie indirekt über die QuotaExceededError
abrufen. Sehen wir uns nun einige Möglichkeiten an.
Es gibt mehrere Ansätze, wie Sie mit QuotaExceededError
umgehen können. In der Praxis ist eine Kombination aus einem oder mehreren Ansätzen am besten. Du solltest die Arbeit darauf basieren, wie viel du abfragst und versuchst, über HTMLMediaElement.currentTime
hinaus anzuhängen, und diese Größe anhand der QuotaExceededError
anpassen. Mit einem Manifest wie einer mpd-Datei (MPEG-DASH) oder einer m3u8-Datei (HLS) kannst du die Daten im Auge behalten, die du dem Puffer hinzufügst.
Sehen wir uns nun einige Ansätze zur Behandlung der QuotaExceededError
an.
- Entfernen Sie nicht benötigte Daten und hängen Sie sie wieder an.
- Fügen Sie kleinere Fragmente an.
- Verringern Sie die Wiedergabeauflösung.
Sie können zwar kombiniert werden, ich werde sie aber einzeln behandeln.
Nicht benötigte Daten entfernen und wieder anhängen
Dieser Vorgang sollte eigentlich „Daten entfernen, die am wenigsten wahrscheinlich bald verwendet werden, und dann den Anhängen von Daten wiederholen, die wahrscheinlich bald verwendet werden“ heißen. Das war ein zu langer Titel. Sie müssen sich nur daran erinnern, was ich wirklich meine.
Das Entfernen aktueller Daten ist nicht so einfach wie das Aufrufen von SourceBuffer.remove()
. Wenn Sie Daten aus der SourceBuffer
entfernen möchten, muss das Aktualisierungsflag auf „false“ gesetzt sein. Andernfalls rufen Sie SourceBuffer.abort()
auf, bevor Sie Daten entfernen.
Beim Aufrufen von SourceBuffer.remove()
sind einige Dinge zu beachten.
- Das kann sich negativ auf die Wiedergabe auswirken. Wenn du beispielsweise möchtest, dass das Video bald wiederholt oder in einer Schleife abgespielt wird, solltest du den Anfang des Videos nicht entfernen. Wenn du oder der Nutzer zu einem Teil des Videos springen, aus dem du Daten entfernt hast, musst du diese Daten wieder anhängen, damit der Sprung funktioniert.
- Entfernen Sie die Elemente so schonend wie möglich. Entferne die gerade wiedergegebene Gruppe von Frames, die beim Keyframe bei oder vor
currentTime
beginnt, nicht. Andernfalls kann die Wiedergabe unterbrochen werden. Solche Informationen müssen möglicherweise von der Webanwendung aus dem Bytestream geparst werden, wenn sie nicht im Manifest verfügbar sind. Ein Medienmanifest oder App-Kenntnisse zu keyframe-Intervallen in den Medien können bei der Auswahl der Entfernungsbereiche Ihrer App helfen, um zu verhindern, dass die derzeit wiedergegebenen Medien entfernt werden. Entfernen Sie auf keinen Fall die aktuell abgespielte Gruppe von Bildern oder die ersten Bilder danach. Entfernen Sie die Daten in der Regel nicht über den aktuellen Zeitpunkt hinaus, es sei denn, Sie sind sich sicher, dass sie nicht mehr benötigt werden. Wenn du das Video zu nah am Wiedergabepfeil entfernst, kann es zu Rucklern kommen. - In Safari 9 und Safari 10 wird
SourceBuffer.abort()
nicht korrekt implementiert. Stattdessen werden Fehler ausgegeben, die die Wiedergabe beenden. Glücklicherweise gibt es hier und hier offene Fehler-Tracker. In der Zwischenzeit müssen Sie das Problem irgendwie umgehen. Shaka Player macht das, indem in diesen Versionen von Safari eine leereabort()
-Funktion erstellt wird.
Kleinere Fragmente anhängen
Unten habe ich die Vorgehensweise dargestellt. Das funktioniert möglicherweise nicht in jedem Fall, hat aber den Vorteil, dass die Größe der kleineren Chunks an Ihre Anforderungen angepasst werden kann. Außerdem ist kein Rückgriff auf das 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
Das ist vergleichbar mit dem Entfernen der letzten Daten und dem erneuten Anhängen. Sie können beides gleichzeitig tun, obwohl im Beispiel unten nur die Auflösung verringert wird.
Beachten Sie bei der Verwendung dieser Technik Folgendes:
- Sie müssen ein neues ‑Segment anhängen. Sie müssen dies tun, wenn Sie die Darstellungen ändern. Das neue Initiationssegment muss für die nachfolgenden Mediensegmente sein.
- Der Zeitstempel der Präsentation der angehängten Medien sollte dem Zeitstempel der Daten im Puffer möglichst genau entsprechen, darf aber nicht vorspringen. Das Überlappen der zwischengespeicherten Daten kann je nach Browser zu Rucklern oder kurzen Aussetzern führen. Unabhängig davon, was du anfügst, darfst du den Wiedergabestandort nicht überlappen, da sonst Fehler auftreten.
- Das Suchen kann die Wiedergabe unterbrechen. Du könntest versucht sein, zu einer bestimmten Stelle zu springen und die Wiedergabe von dort fortzusetzen. Die Wiedergabe wird unterbrochen, bis die Suche abgeschlossen ist.