Signatur
Beschreibung
Das Ereignis loadedmetadata feuert an einem <audio>- oder <video>-Element, sobald der Browser genug von der Mediendatei gelesen hat, um die Metadaten zu kennen. Dazu gehören die Gesamtdauer (duration), bei Videos die natürlichen Abmessungen (videoWidth, videoHeight) sowie Audio-, Video- und Textspuren. In diesem Moment wechselt readyState auf HAVE_METADATA (1).
Das Ereignis eignet sich, um die Oberfläche eines eigenen Players vorzubereiten: Dauer anzeigen, einen Fortschrittsbalken skalieren, das Seitenverhältnis eines Containers setzen oder eine Startposition über currentTime festlegen. Zu diesem Zeitpunkt sind aber noch keine Bilddaten dekodiert – für das erste darstellbare Bild ist loadeddata zuständig, für abspielbereit canplay.
Registrieren lässt sich der Handler per addEventListener("loadedmetadata", handler) oder über die Eigenschaft onloadedmetadata. Das Ereignis ist ein einfaches Event, es blubbert nicht (bubbles: false) und ist nicht abbrechbar.
Typische Ereignisreihenfolge beim Laden: loadstart → durationchange → loadedmetadata → loadeddata → canplay → canplaythrough.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Der Ereignisname "loadedmetadata". |
|
| $handler Pflicht | (event: Event) => void | Rückruffunktion; erhält ein einfaches Event, dessen target das Medienelement ist. |
|
| $options | boolean | AddEventListenerOptions | false | Optionen wie { once: true } oder { signal } zum automatischen Entfernen. |
Beispiele
Dauer und Auflösung eines Videos anzeigen
const video = document.querySelector('video');
const formatTime = (s) => {
const m = Math.floor(s / 60);
const sec = Math.floor(s % 60).toString().padStart(2, '0');
return `${m}:${sec}`;
};
video.addEventListener('loadedmetadata', () => {
console.log(`Dauer: ${formatTime(video.duration)}`);
console.log(`Auflösung: ${video.videoWidth}x${video.videoHeight}`);
});
video.src = 'film.mp4';
Wiedergabe an gespeicherter Position fortsetzen (on-Property)
const video = document.querySelector('#player');
const key = `pos:${video.currentSrc || video.src}`;
video.onloadedmetadata = () => {
const saved = Number(localStorage.getItem(key));
if (saved > 0 && saved < video.duration) {
video.currentTime = saved;
}
};
video.addEventListener('timeupdate', () => {
localStorage.setItem(key, String(video.currentTime));
});
Metadaten per Promise abwarten – auch wenn schon geladen
const waitForMetadata = (media) =>
new Promise((resolve, reject) => {
// Ereignis könnte bereits vorbei sein
if (media.readyState >= HTMLMediaElement.HAVE_METADATA) {
resolve(media);
return;
}
const controller = new AbortController();
const { signal } = controller;
media.addEventListener('loadedmetadata', () => {
controller.abort();
resolve(media);
}, { signal });
media.addEventListener('error', () => {
controller.abort();
reject(media.error);
}, { signal });
});
const audio = new Audio('podcast.mp3');
const el = await waitForMetadata(audio);
console.log(`Länge: ${Math.round(el.duration)} s`);
Listener wieder entfernen
const video = document.querySelector('video');
const setAspectRatio = () => {
video.parentElement.style.aspectRatio = `${video.videoWidth} / ${video.videoHeight}`;
video.removeEventListener('loadedmetadata', setAspectRatio);
};
video.addEventListener('loadedmetadata', setAspectRatio);
// Wichtig · Fallstricke
- Wettlaufsituation: Wird der Listener erst registriert, nachdem die Metadaten bereits geladen sind (z. B. bei gecachten Dateien oder Skripten am Seitenende), feuert das Ereignis nicht erneut. Vorher
readyState >= 1prüfen. - Kein Bubbling: Ein Listener auf
documentgreift nur in der Capture-Phase:document.addEventListener('loadedmetadata', fn, true). preload: Mitpreload="none"lädt der Browser keine Metadaten, bis der Nutzer die Wiedergabe startet. Mobile Browser (v. a. iOS Safari) ignorierenpreloadteils und laden erst nach Interaktion.durationkannInfinitysein – etwa bei Livestreams oder manchenMediaSource-/WebM-Aufnahmen ohne Dauerangabe. AuchNaNist möglich, wenn noch keine Daten vorliegen.- Bei Audiodateien sind
videoWidth/videoHeightgleich0. - Bei jedem Wechsel von
srcbzw. Aufruf vonload()wird das Ereignis erneut ausgelöst – Listener mit{ once: true }ggf. neu registrieren. - Kompatibilität: in allen modernen Browsern seit Langem unterstützt.