Signatur
Beschreibung
MediaKeyMessageEvent gehört zur Encrypted Media Extensions API (EME). Eine MediaKeySession löst dieses Event als message-Event aus, sobald das Content-Decryption-Modul (CDM) Daten an den Lizenzserver schicken will. Das passiert zum Beispiel nach generateRequest(), bei einer Lizenzverlängerung oder bei der Freigabe einer Lizenz.
Das Event hat zwei eigene, schreibgeschützte Eigenschaften:
messageType: Art der Nachricht, einer der Werte"license-request","license-renewal","license-release"oder"individualization-request".message: einArrayBuffermit den undurchsichtigen Binärdaten des CDM. Deine Anwendung schickt diese Daten unverändert an den Lizenzserver.
Der übliche Ablauf sieht so aus: Du holst dir die Nachricht aus dem Event, schickst sie per fetch() an den Lizenzserver und übergibst die Antwort mit session.update(response) an die Sitzung. Deinen Handler registrierst du mit session.addEventListener("message", handler) oder über die Eigenschaft session.onmessage. Den Konstruktor new MediaKeyMessageEvent(type, init) brauchst du in der Praxis kaum, höchstens für Tests.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Name des Events, in der Regel "message" (nur beim Konstruktor). |
|
| $options Pflicht | MediaKeyMessageEventInit | Objekt mit messageType ("license-request" | "license-renewal" | "license-release" | "individualization-request") und message (ArrayBuffer) sowie den üblichen Event-Optionen bubbles, cancelable und composed. |
Rückgabewert
message-Handler das Event als Argument.Beispiele
Lizenzanfrage an den Server weiterleiten (Clear Key)
const video = document.querySelector('video');
const config = [{
initDataTypes: ['cenc'],
videoCapabilities: [{ contentType: 'video/mp4; codecs="avc1.42E01E"' }]
}];
video.addEventListener('encrypted', async (event) => {
if (!video.mediaKeys) {
const access = await navigator.requestMediaKeySystemAccess('org.w3.clearkey', config);
const mediaKeys = await access.createMediaKeys();
await video.setMediaKeys(mediaKeys);
}
const session = video.mediaKeys.createSession();
session.addEventListener('message', async (msgEvent) => {
console.log('Nachrichtentyp:', msgEvent.messageType);
const response = await fetch('/license', {
method: 'POST',
body: msgEvent.message // ArrayBuffer unverändert senden
});
const license = await response.arrayBuffer();
await session.update(license);
console.log('Lizenz übergeben');
});
await session.generateRequest(event.initDataType, event.initData);
});
Nach messageType unterscheiden (onmessage-Eigenschaft)
const handleMessage = async (session, event) => {
switch (event.messageType) {
case 'license-request':
case 'license-renewal': {
const res = await fetch('/license', { method: 'POST', body: event.message });
if (!res.ok) throw new Error(`Lizenzserver: ${res.status}`);
await session.update(await res.arrayBuffer());
break;
}
case 'license-release':
await fetch('/release', { method: 'POST', body: event.message });
break;
default:
console.warn('Unbekannter Typ:', event.messageType);
}
};
// session stammt von mediaKeys.createSession()
session.onmessage = (event) => handleMessage(session, event);
Clear-Key-Nachricht dekodieren (JSON)
session.addEventListener('message', (event) => {
// Bei Clear Key ist die Nachricht UTF-8-kodiertes JSON
const text = new TextDecoder().decode(event.message);
const request = JSON.parse(text);
console.log(request.kids, request.type);
});
Event für Tests selbst erzeugen
const payload = new TextEncoder().encode('{"kids":["abc"],"type":"temporary"}').buffer;
const fakeEvent = new MediaKeyMessageEvent('message', {
messageType: 'license-request',
message: payload
});
console.log(fakeEvent.type, fakeEvent.messageType, fakeEvent.message.byteLength);
// Wichtig · Fallstricke
- Sicherer Kontext: EME gibt es nur über HTTPS (oder
localhost). In Iframes muss zusätzlich die Permissions Policyencrypted-mediaerlaubt sein. - Nachricht ist undurchsichtig: Außer bei Clear Key (dort JSON) ist
messageein proprietäres Binärformat, zum Beispiel für Widevine, PlayReady oder FairPlay. Schicke die Daten unverändert an den Server. Manche Lizenzserver, etwa bei PlayReady, erwarten sie aber eingebettet in XML oder mit bestimmten HTTP-Headern. - Handler vor
generateRequest()registrieren: Sonst kann die erste Nachricht verloren gehen. - Mehrere Nachrichten: Eine Sitzung kann während ihrer Laufzeit mehrere
message-Events auslösen, zum Beispiel für Verlängerungen. Werte deshalb immermessageTypeaus. - Browser-Unterstützung: Das Interface selbst ist in Chrome, Edge, Firefox und Safari verfügbar. Welche Schlüsselsysteme unterstützt werden, hängt aber von Browser und Plattform ab: Safari nutzt vor allem FairPlay, Firefox und Chrome Widevine. Prüfe das vorher mit
navigator.requestMediaKeySystemAccess(). - Sicherheit: Schütze den Endpunkt des Lizenzservers mit Authentifizierung (Token, Cookies) und beachte CORS, wenn der Server auf einer anderen Domain liegt.