Signatur
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
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);
});
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 });
// 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
requestAnimationFrameoder bei VideosHTMLVideoElement.requestVideoFrameCallback(). - Nicht nur bei Wiedergabe:
timeupdatekommt auch beim Seeking und wenncurrentTimeper Skript gesetzt wird. Wenn du im Handler selbstcurrentTimesetzt, kannst du damit Endlosschleifen oder Ruckeln auslösen. durationprüfen: VorloadedmetadataistdurationgleichNaN, bei LivestreamsInfinity. 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.