Signatur
Beschreibung
Das message-Ereignis gehört zu den Encrypted Media Extensions (EME). Es wird an einer MediaKeySession ausgelöst, sobald das Inhaltsentschlüsselungsmodul (Content Decryption Module, CDM) Daten an die Anwendung übergeben möchte, meistens nach generateRequest(). Das Ereignisobjekt ist ein MediaKeyMessageEvent mit den Eigenschaften messageType und message (ein ArrayBuffer).
Die Anwendung sieht in die Nachricht nicht hinein. Sie schickt sie unverändert an den Lizenzserver, zum Beispiel per fetch(), und übergibt die Antwort des Servers über session.update(response) wieder an das CDM. Erst danach kann das Video entschlüsselt und abgespielt werden.
Den Listener registriert man mit session.addEventListener("message", handler) oder über die Eigenschaft session.onmessage = handler. Wichtig: Der Listener muss vor dem Aufruf von generateRequest() registriert werden, sonst geht die erste Lizenzanfrage verloren.
Mögliche Werte von messageType: "license-request", "license-renewal", "license-release" und "individualization-request".
Rückgabewert
addEventListener hat keinen Rückgabewert. Die Daten stehen im übergebenen MediaKeyMessageEvent.Beispiele
Lizenzanfrage an einen Lizenzserver weiterleiten (ClearKey)
const video = document.querySelector('video');
const LICENSE_URL = 'https://license.example.com/clearkey';
video.addEventListener('encrypted', async (event) => {
if (!video.mediaKeys) {
const access = await navigator.requestMediaKeySystemAccess('org.w3.clearkey', [{
initDataTypes: ['cenc'],
videoCapabilities: [{ contentType: 'video/mp4; codecs="avc1.42E01E"' }]
}]);
const mediaKeys = await access.createMediaKeys();
await video.setMediaKeys(mediaKeys);
}
const session = video.mediaKeys.createSession();
// Listener VOR generateRequest() registrieren
session.addEventListener('message', async (msgEvent) => {
console.log('Nachrichtentyp:', msgEvent.messageType);
const response = await fetch(LICENSE_URL, {
method: 'POST',
body: msgEvent.message
});
const license = await response.arrayBuffer();
await session.update(license);
console.log('Lizenz übergeben');
});
await session.generateRequest(event.initDataType, event.initData);
});
Nach messageType unterscheiden mit der onmessage-Eigenschaft
const handleMessage = async (session, event) => {
switch (event.messageType) {
case 'license-request':
case 'license-renewal': {
const res = await fetch('/drm/license', { method: 'POST', body: event.message });
if (!res.ok) throw new Error(`Lizenzserver: HTTP ${res.status}`);
await session.update(await res.arrayBuffer());
break;
}
case 'license-release':
// Bestätigung der Freigabe an den Server senden
await fetch('/drm/release', { method: 'POST', body: event.message });
break;
default:
console.warn('Unbekannter Nachrichtentyp:', event.messageType);
}
};
const setupSession = (mediaKeys) => {
const session = mediaKeys.createSession();
session.onmessage = (event) => {
handleMessage(session, event).catch(console.error);
};
return session;
};
Listener beim Schließen der Session entfernen
const attachLicenseHandler = (session) => {
const onMessage = async (event) => {
const res = await fetch('/drm/license', { method: 'POST', body: event.message });
await session.update(await res.arrayBuffer());
};
session.addEventListener('message', onMessage);
// Wenn die Session geschlossen wird, Listener aufräumen
session.closed.then(() => {
session.removeEventListener('message', onMessage);
console.log('Session geschlossen, Listener entfernt');
});
};
// Wichtig · Fallstricke
- Reihenfolge: Registriere den
message-Listener immer vorgenerateRequest()bzw.load(). Sonst wird die erste Nachricht nicht verarbeitet. - Nachricht nicht verändern:
event.messageist ein Binärpuffer, dessen Format vom Schlüsselsystem abhängt (Widevine, PlayReady, FairPlay, ClearKey). Leite ihn unverändert weiter. Manche Lizenzserver, etwa bei PlayReady oder FairPlay, erwarten eigene Header oder eine eigene Hülle (z. B. XML oder Base64). Das steht in der Dokumentation des Anbieters. - Sicherer Kontext: EME steht nur über HTTPS zur Verfügung. In iframes muss die Permissions-Policy
encrypted-mediaerlaubt sein. - Fehlerbehandlung: Wenn
fetch()oderupdate()fehlschlägt, entsteht ein nicht abgefangenes Promise. Fange Fehler ab und zeige den Nutzern eine verständliche Meldung. - Browserunterstützung: Alle modernen Browser unterstützen das Ereignis. Welche Schlüsselsysteme verfügbar sind, unterscheidet sich aber: Chrome und Firefox bieten Widevine, Edge bietet PlayReady und Widevine, Safari bietet FairPlay. ClearKey ist nur zum Testen gedacht und bietet keinen echten Schutz.
- Verlängerungen:
"license-renewal"-Nachrichten können während der Wiedergabe jederzeit erneut eintreffen. Der Listener sollte deshalb für die ganze Lebensdauer der Session aktiv bleiben.