Start · Sprachen · JavaScript · Referenz · TimeRanges

TimeRanges

Schnittstelle

Beschreibt eine Liste von Zeitbereichen (Start/Ende in Sekunden) einer Medienressource – etwa gepufferte, abgespielte oder suchbare Abschnitte.

seit JavaScript Baseline: alle Browser Kategorie: webapi

Signatur

interface TimeRanges

Beschreibung

Die Schnittstelle TimeRanges steht für eine geordnete Liste von Zeitbereichen einer Medienressource. Sie liefern <audio>- und <video>-Elemente (also HTMLMediaElement) über die Eigenschaften buffered, played und seekable zurück. Außerdem gibt es sie in der Media Source Extensions API unter SourceBuffer.buffered.

Jeder Bereich hat eine Start- und eine Endzeit in Sekunden. Die Bereiche sind aufsteigend sortiert, überlappen sich nicht und grenzen nicht direkt aneinander. Aneinanderstoßende Abschnitte fasst der Browser zu einem Bereich zusammen. Die Anzahl steht in length. Die Grenzen eines Bereichs liest du mit start(index) und end(index).

Typische Einsätze sind:

  • Pufferanzeige in eigenen Player-Oberflächen, etwa ein grauer Balken hinter dem Fortschrittsbalken.
  • Auswertung, welche Teile eines Videos wirklich angesehen wurden (played).
  • Prüfung vor einem Sprung, ob eine Zielzeit überhaupt angesteuert werden kann (seekable), zum Beispiel bei Livestreams.

Ein TimeRanges-Objekt ist eine Momentaufnahme. Die Liste ist schreibgeschützt, und man kann sie nicht selbst erzeugen: Es gibt keinen öffentlichen Konstruktor. Wer den aktuellen Stand braucht, liest die Eigenschaft erneut aus, zum Beispiel im Ereignis progress oder timeupdate.

Parameter

Name Typ Default Beschreibung
$length number Schreibgeschützte Eigenschaft: Anzahl der Zeitbereiche in der Liste. Bei 0 gibt es keine Bereiche.
$start(index) (index: number) => number Methode: gibt die Startzeit (in Sekunden) des Bereichs mit dem Index index zurück. Der Index reicht von 0 bis length - 1.
$end(index) (index: number) => number Methode: gibt die Endzeit (in Sekunden) des Bereichs mit dem Index index zurück. Bei Livestreams kann der Wert Infinity sein.

Rückgabewert

Typ
TimeRanges
Beschreibung
Man erhält Instanzen nur über HTMLMediaElement.buffered, .played, .seekable oder SourceBuffer.buffered.

Beispiele

Alle gepufferten Bereiche eines Videos ausgeben

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

const logRanges = (ranges) => {
  for (let i = 0; i < ranges.length; i++) {
    console.log(`Bereich ${i}: ${ranges.start(i).toFixed(1)}s – ${ranges.end(i).toFixed(1)}s`);
  }
};

video.addEventListener('progress', () => logRanges(video.buffered));
Bereich 0: 0.0s – 12.4s Bereich 1: 30.0s – 41.8s

Pufferanzeige für einen eigenen Fortschrittsbalken

const video = document.querySelector('video');
const canvas = document.querySelector('#buffer-bar');
const ctx = canvas.getContext('2d');

const drawBuffer = () => {
  const { buffered, duration } = video;
  if (!Number.isFinite(duration) || duration === 0) return;
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.fillStyle = '#bbb';
  for (let i = 0; i < buffered.length; i++) {
    const x = (buffered.start(i) / duration) * canvas.width;
    const w = ((buffered.end(i) - buffered.start(i)) / duration) * canvas.width;
    ctx.fillRect(x, 0, w, canvas.height);
  }
};

video.addEventListener('progress', drawBuffer);
video.addEventListener('loadedmetadata', drawBuffer);

Prüfen, ob eine Zeitposition gepuffert bzw. suchbar ist

const isInRanges = (ranges, time) => {
  for (let i = 0; i < ranges.length; i++) {
    if (time >= ranges.start(i) && time <= ranges.end(i)) return true;
  }
  return false;
};

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

if (isInRanges(video.seekable, target)) {
  video.currentTime = target;
  console.log('Sofort abspielbar:', isInRanges(video.buffered, target));
} else {
  console.log('Zeitpunkt nicht suchbar');
}
Sofort abspielbar: false

Gesamte angesehene Dauer über played berechnen

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

video.addEventListener('pause', () => {
  const { played } = video;
  let watched = 0;
  for (let i = 0; i < played.length; i++) {
    watched += played.end(i) - played.start(i);
  }
  const percent = ((watched / video.duration) * 100).toFixed(1);
  console.log(`Angesehen: ${watched.toFixed(1)}s (${percent} %)`);
});
Angesehen: 48.3s (26.8 %)

// Wichtig · Fallstricke

  • Index außerhalb des Bereichs: start(i) und end(i) werfen eine IndexSizeError-DOMException, wenn i kleiner als 0 oder mindestens length ist. Prüfe deshalb immer zuerst length. Direkt nach dem Laden ist sie oft 0.
  • Kein Array: TimeRanges ist weder iterierbar noch indexierbar (ranges[0] funktioniert nicht). for…of und Array.from() helfen daher nicht. Nutze eine klassische for-Schleife mit start() und end().
  • Momentaufnahme: Das Objekt aktualisiert sich nicht von selbst. Lies buffered jedes Mal neu aus, statt eine alte Referenz aufzuheben.
  • Mehrere Bereiche: Nach Sprüngen im Video können Lücken entstehen. Wer nur end(0) auswertet, rechnet dann falsch. Suche stattdessen den Bereich, der currentTime enthält.
  • Livestreams: seekable kann ein gleitendes Fenster sein, und duration ist dann womöglich Infinity. Prozentrechnungen vorher mit Number.isFinite() absichern.
  • Browser-Unterstützung: Seit Jahren in allen modernen Browsern verfügbar. Das Ereignis progress wird je nach Browser unterschiedlich oft ausgelöst. Für eine flüssige Anzeige kann man zusätzlich timeupdate abfragen.