Start · Sprachen · JavaScript · Referenz · SourceBuffer.remove()

SourceBuffer.remove()

Methode

Entfernt gepufferte Mediendaten im Zeitbereich von <code>start</code> bis <code>end</code> (in Sekunden) asynchron aus einem <code>SourceBuffer</code>.

seit JavaScript Media Source Extensions; Baseline: alle modernen B Kategorie: webapi

Signatur

SourceBuffer.prototype.remove(start, end)

Beschreibung

Mit remove() löschst du Mediendaten aus einem SourceBuffer, der zu einer MediaSource gehört. Das ist vor allem bei Streaming-Playern (HLS, DASH, Live-Streams) wichtig: Der Browser hat für jeden Puffer nur ein begrenztes Kontingent. Wer Segmente endlos per appendBuffer() anhängt, bekommt irgendwann einen QuotaExceededError. Deshalb entfernt man regelmäßig Daten, die weit hinter der aktuellen Abspielposition liegen.

Der Vorgang läuft asynchron. Direkt nach dem Aufruf steht updating auf true, und der Browser feuert updatestart. Ist der Vorgang fertig, folgen update und updateend. Erst danach darfst du den Puffer wieder mit appendBuffer() oder remove() ansprechen. Deshalb baut man in der Praxis meist eine Warteschlange für die Puffer-Operationen.

Ein weiterer Anwendungsfall ist das Springen an eine andere Stelle (Seeking) oder das Wechseln der Qualitätsstufe. Dabei entfernt man bereits gepufferte Daten ab einem bestimmten Zeitpunkt, um sie durch Segmente in einer anderen Qualität zu ersetzen. Der Browser entfernt nur ganze Codier-Einheiten. Der tatsächlich gelöschte Bereich kann also bis zum nächsten Schlüsselbild (Keyframe) über den angegebenen Bereich hinausgehen.

Parameter

Name Typ Default Beschreibung
$start Pflicht number Beginn des zu entfernenden Bereichs in Sekunden. Muss ≥ 0 und kleiner als end sein; zudem kleiner oder gleich MediaSource.duration.
$end Pflicht number Ende des Bereichs in Sekunden (exklusiv). Muss größer als start sein; Infinity ist erlaubt, um alles ab start zu entfernen.

Rückgabewert

Typ
void
Beschreibung
Kein Rückgabewert (undefined). Das Ende des Vorgangs wird über das Event updateend signalisiert.

Beispiele

Alten Puffer hinter der Abspielposition aufräumen

const video = document.querySelector('video');

// sourceBuffer stammt aus mediaSource.addSourceBuffer(mime)
const trimBackBuffer = (sourceBuffer, keepSeconds = 30) => {
  if (sourceBuffer.updating || sourceBuffer.buffered.length === 0) return;

  const bufferStart = sourceBuffer.buffered.start(0);
  const removeEnd = video.currentTime - keepSeconds;

  if (removeEnd > bufferStart) {
    console.log(`Entferne ${bufferStart.toFixed(1)}s bis ${removeEnd.toFixed(1)}s`);
    sourceBuffer.remove(bufferStart, removeEnd);
  }
};

video.addEventListener('timeupdate', () => trimBackBuffer(sourceBuffer));
Entferne 0.0s bis 12.4s

remove() als Promise verpacken

const removeRange = (sourceBuffer, start, end) =>
  new Promise((resolve, reject) => {
    const onEnd = () => { cleanup(); resolve(); };
    const onError = () => { cleanup(); reject(new Error('remove fehlgeschlagen')); };
    const cleanup = () => {
      sourceBuffer.removeEventListener('updateend', onEnd);
      sourceBuffer.removeEventListener('error', onError);
    };
    sourceBuffer.addEventListener('updateend', onEnd);
    sourceBuffer.addEventListener('error', onError);
    sourceBuffer.remove(start, end);
  });

// Nutzung: alles ab 60 s löschen (z. B. vor einem Qualitätswechsel)
await removeRange(sourceBuffer, 60, Infinity);
console.log('Gepuffert:', sourceBuffer.buffered.length, 'Bereich(e)');
Gepuffert: 1 Bereich(e)

Auf QuotaExceededError reagieren

const appendSegment = async (sourceBuffer, video, data) => {
  try {
    sourceBuffer.appendBuffer(data);
  } catch (err) {
    if (err.name === 'QuotaExceededError') {
      // Platz schaffen: alles bis 10 s vor der aktuellen Position löschen
      const end = Math.max(0, video.currentTime - 10);
      if (end > 0) {
        await removeRange(sourceBuffer, 0, end);
        sourceBuffer.appendBuffer(data); // erneut versuchen
      }
    } else {
      throw err;
    }
  }
};

// Wichtig · Fallstricke

  • InvalidStateError: Tritt auf, wenn updating noch true ist oder der SourceBuffer bereits aus der MediaSource entfernt wurde. Warte deshalb immer auf updateend, bevor du die nächste Operation startest.
  • TypeError: Tritt auf, wenn start negativ ist, größer als duration oder NaN, oder wenn end kleiner oder gleich start ist oder NaN.
  • Steht MediaSource.readyState auf "ended", wechselt der Zustand durch remove() zurück auf "open" (sourceopen wird erneut gefeuert).
  • Den Bereich um currentTime nicht löschen, sonst bleibt die Wiedergabe hängen (waiting). Halte einen Sicherheitsabstand von einigen Sekunden ein.
  • Der Browser entfernt nur ganze Codier-Einheiten bis zum nächsten Schlüsselbild. Der gelöschte Bereich kann deshalb vom angeforderten abweichen. Prüfe danach buffered.
  • Kompatibilität: Chrome, Edge, Firefox und Safari (macOS) unterstützen die Methode. Auf dem iPhone steht MSE erst ab iOS 17.1 bereit, und zwar über ManagedMediaSource. Dort kann der Browser Daten auch selbst entfernen (Event bufferedchange).