Start · Sprachen · JavaScript · Referenz · MediaKeyMessageEvent

MediaKeyMessageEvent

Schnittstelle

Das Event, das eine <code>MediaKeySession</code> auslöst, wenn das Content-Decryption-Modul (CDM) eine Nachricht erzeugt, meist eine Lizenzanfrage an den Lizenzserver.

seit JavaScript Baseline: alle modernen Browser (sicherer Kontext Kategorie: webapi

Signatur

interface MediaKeyMessageEvent extends Event

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: ein ArrayBuffer mit 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

Typ
MediaKeyMessageEvent
Beschreibung
Beim Konstruktor: eine neue Event-Instanz. Sonst erhält dein 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);
});
Nachrichtentyp: license-request Lizenz übergeben

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);
});
["nrQFDeRLSAKTLifXUIPiZg"] temporary

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);
message license-request 34

// Wichtig · Fallstricke

  • Sicherer Kontext: EME gibt es nur über HTTPS (oder localhost). In Iframes muss zusätzlich die Permissions Policy encrypted-media erlaubt sein.
  • Nachricht ist undurchsichtig: Außer bei Clear Key (dort JSON) ist message ein 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 immer messageType aus.
  • 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.