Signatur
Beschreibung
MediaEncryptedEvent gehört zur Encrypted Media Extensions API (EME). Ein <video>- oder <audio>-Element löst das Ereignis encrypted aus, sobald der Browser in den Mediendaten Initialisierungsdaten für die Verschlüsselung findet, etwa eine pssh-Box in einem MP4-Container oder eine ContentEncKeyID in WebM. Das Ereignisobjekt enthält genau diese Daten. Deine Anwendung braucht sie, um beim Lizenzserver einen Schlüssel anzufordern.
Das Objekt hat zwei schreibgeschützte Eigenschaften:
initDataType: Ein String, der das Format der Daten angibt, z. B."cenc","keyids"oder"webm".initData: EinArrayBuffermit den Initialisierungsdaten odernull.
Der übliche Ablauf sieht so aus: Mit navigator.requestMediaKeySystemAccess() Zugriff auf ein Schlüsselsystem (Widevine, PlayReady, FairPlay oder Clear Key) anfordern und daraus MediaKeys erzeugen. Diese mit video.setMediaKeys() an das Element binden. Im encrypted-Handler eine MediaKeySession erstellen und session.generateRequest(event.initDataType, event.initData) aufrufen. Die Lizenzanfrage kommt dann über das message-Event der Sitzung. Die Antwort des Lizenzservers wird mit session.update() übergeben.
Einen eigenen Konstruktor new MediaEncryptedEvent(type, init) gibt es auch. Er dient vor allem für Tests oder dazu, Ereignisse nachzubilden. In echten Abspielern erzeugt der Browser die Ereignisse selbst.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Nur für den Konstruktor: der Name des Ereignisses, normalerweise "encrypted". |
|
| $init | { initDataType?: string, initData?: ArrayBuffer | null, bubbles?: boolean, cancelable?: boolean, composed?: boolean } | { initDataType: "", initData: null } | Nur für den Konstruktor: optionales Objekt mit dem Format (initDataType) und den Initialisierungsdaten (initData) sowie den üblichen EventInit-Feldern. |
Rückgabewert
initDataType (string) und initData (ArrayBuffer | null).Beispiele
encrypted-Event abfangen und Initialisierungsdaten lesen
const video = document.querySelector('video');
video.addEventListener('encrypted', (event) => {
// event ist ein MediaEncryptedEvent
console.log('Format:', event.initDataType);
console.log('Bytes:', event.initData?.byteLength ?? 0);
});
Vollständiger Clear-Key-Ablauf mit Lizenzanfrage
const video = document.querySelector('video');
const config = [{
initDataTypes: ['cenc', 'keyids'],
videoCapabilities: [{ contentType: 'video/mp4; codecs="avc1.42E01E"' }]
}];
const setupEme = async () => {
const access = await navigator.requestMediaKeySystemAccess('org.w3.clearkey', config);
const mediaKeys = await access.createMediaKeys();
await video.setMediaKeys(mediaKeys);
video.addEventListener('encrypted', async ({ initDataType, initData }) => {
const session = mediaKeys.createSession();
session.addEventListener('message', async (msg) => {
// Lizenzanfrage an den eigenen Server schicken
const res = await fetch('/license', {
method: 'POST',
body: msg.message
});
await session.update(await res.arrayBuffer());
});
await session.generateRequest(initDataType, initData);
});
};
setupEme().catch((err) => console.error('EME-Fehler:', err));
Handler per on-Property registrieren und entfernen
const video = document.querySelector('video');
video.onencrypted = (event) => {
console.log(`Verschlüsselung erkannt (${event.initDataType})`);
video.onencrypted = null; // nur einmal reagieren
};
Event manuell erzeugen (z. B. für Tests)
const keyIds = new TextEncoder().encode(JSON.stringify({ kids: ['LwVHf8JLtPrv2GUXFW2v_A'] }));
const event = new MediaEncryptedEvent('encrypted', {
initDataType: 'keyids',
initData: keyIds.buffer
});
console.log(event.type, event.initDataType, event.initData.byteLength);
// Wichtig · Fallstricke
- Nur in sicheren Kontexten: EME und damit
requestMediaKeySystemAccess()funktionieren nur über HTTPS (oderlocalhost). Über reines HTTP ist die API in modernen Browsern nicht verfügbar. - Mehrfaches Auslösen: Das Event kann für dieselben Daten mehrmals kommen, z. B. einmal pro Spur oder bei jedem Init-Segment. Merke dir schon verarbeitete
initData, damit du keine doppelten Sitzungen und Lizenzanfragen erzeugst. - Reihenfolge: Wenn noch keine
MediaKeysgesetzt sind, währendencryptedausgelöst wird, musst dusetMediaKeys()im Handler nachholen. Sonst bleibt die Wiedergabe hängen (waitingforkey). initDatakannnullsein, etwa wenn die Daten aus Sicherheitsgründen zurückgehalten werden (Cross-Origin-Medien ohne CORS). Prüfe den Wert, bevor du ihn verwendest.- Unterstützte Formate: Welche Werte von
initDataTypeund welche Schlüsselsysteme unterstützt werden, hängt vom Browser ab. Safari nutzt FairPlay, meist mitinitDataType"sinf"oder"skd". Chrome und Firefox nutzen Widevine, Edge zusätzlich PlayReady. Clear Key ist nicht in allen Browsern vollständig umgesetzt. - Datenschutz: CDMs können eindeutige Geräte-Kennungen erzeugen. Browser zeigen dafür teils Berechtigungsabfragen an, besonders in privaten Fenstern kann EME eingeschränkt sein.