Start · Sprachen · JavaScript · Referenz · HTMLMediaElement: timeupdate

HTMLMediaElement: timeupdate

Ereignis

Wird ausgelöst, wenn sich die Wiedergabeposition <code>currentTime</code> eines Audio- oder Videoelements geändert hat.

seit JavaScript Baseline: alle Browser Kategorie: webapi

Signatur

element.addEventListener("timeupdate", handler)

Beschreibung

Das Ereignis timeupdate wird an einem HTMLMediaElement (also <audio> oder <video>) ausgelöst, sobald sich der Wert von currentTime geändert hat. Das passiert während der normalen Wiedergabe regelmäßig, aber auch beim Springen im Medium (Seeking) oder wenn currentTime per Skript gesetzt wird.

Typische Anwendungen sind eigene Fortschrittsbalken, Zeitanzeigen („1:23 / 4:56“), das Speichern der zuletzt gehörten Position, synchronisierte Untertitel oder Liedtexte sowie Kapitelmarken.

Wie oft das Ereignis ausgelöst wird, legt die Spezifikation nicht genau fest. Browser feuern es während der Wiedergabe etwa alle 15 bis 250 ms, meist ungefähr 4-mal pro Sekunde. Für bildgenaue Synchronisation reicht das deshalb nicht. Das Ereignis lässt sich nicht abbrechen und steigt nicht im DOM auf (kein Bubbling).

Den Handler registrierst du mit addEventListener("timeupdate", handler) oder über die Eigenschaft ontimeupdate. Er bekommt ein ganz normales Event-Objekt.

Parameter

Name Typ Default Beschreibung
$type Pflicht string Der Ereignisname "timeupdate".
$handler Pflicht (event: Event) => void Die Rückruffunktion. Sie bekommt ein allgemeines Event-Objekt. Das Medienelement erreichst du über event.target oder event.currentTarget.
$options boolean | AddEventListenerOptions false Optionen wie once, passive oder signal (ein AbortSignal, mit dem du den Listener wieder entfernst).

Rückgabewert

Typ
void
Beschreibung
addEventListener gibt nichts zurück. Das Ereignisobjekt ist vom Typ Event.

Beispiele

Fortschrittsbalken und Zeitanzeige

const video = document.querySelector('video');
const progress = document.querySelector('progress');
const label = document.querySelector('#zeit');

const format = (s) => {
  const m = Math.floor(s / 60);
  const sec = Math.floor(s % 60).toString().padStart(2, '0');
  return `${m}:${sec}`;
};

video.addEventListener('timeupdate', () => {
  const { currentTime, duration } = video;
  // Solange die Metadaten fehlen, ist duration NaN
  if (!Number.isFinite(duration)) return;
  progress.value = currentTime / duration;
  label.textContent = `${format(currentTime)} / ${format(duration)}`;
  console.log(label.textContent);
});
0:01 / 4:56 0:01 / 4:56 0:02 / 4:56 …

Wiedergabeposition gedrosselt in localStorage speichern

const audio = document.querySelector('audio');
const key = `position:${audio.currentSrc || audio.src}`;
let lastSaved = 0;

// Gespeicherte Position wiederherstellen
audio.addEventListener('loadedmetadata', () => {
  const saved = Number(localStorage.getItem(key));
  if (saved > 0 && saved < audio.duration) audio.currentTime = saved;
}, { once: true });

// Höchstens alle 5 Sekunden schreiben
audio.addEventListener('timeupdate', () => {
  if (Math.abs(audio.currentTime - lastSaved) >= 5) {
    lastSaved = audio.currentTime;
    localStorage.setItem(key, String(lastSaved));
  }
});

Vorschau stoppen über ontimeupdate und Listener per AbortController entfernen

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

// Variante 1: on-Property – Vorschau nach 30 Sekunden anhalten
video.ontimeupdate = () => {
  if (video.currentTime >= 30) {
    video.pause();
    video.ontimeupdate = null; // Handler entfernen
    console.log('Vorschau beendet');
  }
};

// Variante 2: addEventListener + removeEventListener
const logTime = () => console.log(video.currentTime.toFixed(2));
video.addEventListener('timeupdate', logTime);
setTimeout(() => video.removeEventListener('timeupdate', logTime), 3000);

// Variante 3: mehrere Listener gemeinsam per AbortSignal entfernen
const controller = new AbortController();
video.addEventListener('timeupdate', logTime, { signal: controller.signal });
video.addEventListener('ended', () => controller.abort(), { once: true });
0.25 0.51 0.76 … Vorschau beendet

// Wichtig · Fallstricke

  • Unregelmäßige Taktung: Das Ereignis kommt je nach Browser und Systemlast etwa alle 15 bis 250 ms. Für flüssige Animationen oder bildgenaue Synchronisation nimmst du besser requestAnimationFrame oder bei Videos HTMLVideoElement.requestVideoFrameCallback().
  • Nicht nur bei Wiedergabe: timeupdate kommt auch beim Seeking und wenn currentTime per Skript gesetzt wird. Wenn du im Handler selbst currentTime setzt, kannst du damit Endlosschleifen oder Ruckeln auslösen.
  • duration prüfen: Vor loadedmetadata ist duration gleich NaN, bei Livestreams Infinity. Prüfe das vor jeder Division.
  • Performance: Halte den Handler schlank und vermeide teure DOM-Operationen oder synchrone Speicherzugriffe (z. B. localStorage) bei jedem Aufruf. Drossle solche Arbeit.
  • Kein Bubbling: Das Ereignis steigt nicht auf. Für Event-Delegation an einem Elternelement musst du die Capture-Phase nutzen ({ capture: true }).
  • Kompatibilität: Wird von allen modernen Browsern unterstützt. Hintergrund-Tabs können die Taktung stark drosseln.