Start · Sprachen · JavaScript · Referenz · HTMLMediaElement: durationchange

HTMLMediaElement: durationchange

Ereignis

Wird an einem <code>&lt;audio&gt;</code>- oder <code>&lt;video&gt;</code>-Element ausgelöst, sobald sich der Wert der Eigenschaft <code>duration</code> ändert.

seit JavaScript Baseline: alle Browser Kategorie: webapi

Signatur

element.addEventListener("durationchange", handler)

Beschreibung

Das Ereignis durationchange wird an einem HTMLMediaElement (also <audio> oder <video>) ausgelöst, wenn die Eigenschaft duration einen neuen Wert bekommt. Das passiert typischerweise beim Laden der Metadaten, wenn der Wert von NaN auf die echte Länge in Sekunden wechselt. Das Ereignis lässt sich weder abbrechen noch steigt es im DOM nach oben (es „bubbelt“ nicht).

Sie können es mit addEventListener("durationchange", handler) abonnieren oder über die Eigenschaft ondurationchange einen Handler setzen. Der Handler bekommt ein gewöhnliches Event-Objekt. Die neue Dauer lesen Sie aus event.target.duration.

Typische Anwendungen sind die Anzeige der Gesamtlänge in eigenen Player-Steuerelementen, die Skalierung von Fortschrittsbalken und der Umgang mit Livestreams oder wachsenden Medien. Bei Streams (z. B. HLS oder MSE) kann sich duration während der Wiedergabe mehrmals ändern oder den Wert Infinity annehmen.

Beim Laden neuer Medien laufen die Ereignisse normalerweise in dieser Reihenfolge ab: loadstart → durationchange → loadedmetadata → loadeddata. Wenn Sie src ändern oder load() aufrufen, wird duration auf NaN zurückgesetzt, und auch das löst ein durationchange aus.

Parameter

Name Typ Default Beschreibung
$type Pflicht string Name des Ereignisses: "durationchange".
$handler Pflicht (event: Event) => void Funktion, die bei jeder Änderung von duration aufgerufen wird. Sie bekommt ein einfaches Event-Objekt.
$options boolean | AddEventListenerOptions false Optionen wie once, signal oder capture. Das Ereignis bubbelt nicht, deshalb ist capture nur für Handler auf übergeordneten Elementen sinnvoll.

Beispiele

Gesamtdauer im eigenen Player anzeigen

const video = document.querySelector('video');
const durationLabel = document.querySelector('#duration');

const formatTime = (seconds) => {
  if (!Number.isFinite(seconds)) return seconds === Infinity ? 'Live' : '--:--';
  const m = Math.floor(seconds / 60);
  const s = Math.floor(seconds % 60).toString().padStart(2, '0');
  return `${m}:${s}`;
};

video.addEventListener('durationchange', (event) => {
  const { duration } = event.target;
  durationLabel.textContent = formatTime(duration);
  console.log('Neue Dauer:', duration);
});

video.src = 'trailer.mp4';
Neue Dauer: 142.36

Fortschrittsbalken an die Dauer anpassen (ondurationchange)

const audio = document.querySelector('audio');
const progress = document.querySelector('input[type=range]');

audio.ondurationchange = () => {
  // Bei Livestreams (Infinity) oder unbekannter Dauer (NaN) Slider sperren
  const known = Number.isFinite(audio.duration);
  progress.disabled = !known;
  if (known) progress.max = audio.duration;
};

audio.addEventListener('timeupdate', () => {
  progress.value = audio.currentTime;
});

progress.addEventListener('input', () => {
  audio.currentTime = Number(progress.value);
});

Listener wieder entfernen

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

const logDuration = () => {
  console.log(`Dauer: ${video.duration.toFixed(1)} s`);
};

video.addEventListener('durationchange', logDuration);

// Später, z. B. beim Abbau der Player-Komponente:
video.removeEventListener('durationchange', logDuration);

// Alternative: mit AbortController mehrere Listener auf einmal entfernen
const controller = new AbortController();
video.addEventListener('durationchange', logDuration, { signal: controller.signal });
controller.abort();

Auf die Dauer warten (Promise)

const waitForDuration = (media) => new Promise((resolve) => {
  if (Number.isFinite(media.duration)) return resolve(media.duration);
  const onChange = () => {
    if (Number.isFinite(media.duration)) {
      media.removeEventListener('durationchange', onChange);
      resolve(media.duration);
    }
  };
  media.addEventListener('durationchange', onChange);
});

const audio = new Audio('podcast-folge-12.mp3');
const seconds = await waitForDuration(audio);
console.log(`Folge dauert ${Math.round(seconds / 60)} Minuten`);
Folge dauert 47 Minuten

// Wichtig · Fallstricke

  • NaN und Infinity: Bevor die Metadaten geladen sind, ist duration gleich NaN. Bei Livestreams ist der Wert Infinity. Prüfen Sie deshalb immer mit Number.isFinite(), bevor Sie mit dem Wert rechnen.
  • Mehrfaches Auslösen: Das Ereignis kann mehrmals kommen, zum Beispiel beim Zurücksetzen durch load() oder einen neuen src (dann ist der Wert wieder NaN), bei Media Source Extensions über MediaSource.duration oder wenn der Browser die Dauer von VBR-MP3-Dateien nachträglich korrigiert.
  • Handler zu spät registriert: Wenn das Medium schon geladen ist, bevor der Listener existiert, kommt kein Ereignis mehr an. Lesen Sie daher zusätzlich direkt media.duration aus oder registrieren Sie den Listener vor dem Setzen von src.
  • Kein Bubbling: Das Ereignis steigt nicht im DOM nach oben. Eine Delegation über ein Elternelement funktioniert nur mit { capture: true }.
  • WebM/MediaRecorder: Aufnahmen mit MediaRecorder haben in Chromium oft keine Dauer in den Metadaten (Infinity). Der echte Wert wird erst nach einem Sprung ans Ende gemeldet, dann ebenfalls per durationchange.
  • Kompatibilität: Wird von allen modernen Browsern unterstützt, auch mobil. Die Eigenschaft ondurationchange gehört zu GlobalEventHandlers.