Start · Sprachen · JavaScript · Referenz · MediaKeySession.generateRequest()

MediaKeySession.generateRequest()

Methode

Erzeugt anhand von Initialisierungsdaten eine Lizenzanfrage und gibt ein <code>Promise&lt;undefined&gt;</code> zurück; die Anfrage selbst wird über ein <code>message</code>-Event geliefert.

seit JavaScript Baseline: alle modernen Browser (EME, seit 2019 br Kategorie: webapi

Signatur

MediaKeySession.prototype.generateRequest(initDataType, initData)

Beschreibung

generateRequest() gehört zu den Encrypted Media Extensions (EME) und startet den Lizenzaustausch für verschlüsselte Medieninhalte. Die Methode übergibt die Initialisierungsdaten (z. B. einen PSSH-Block aus einer MP4-Datei) an das Content Decryption Module (CDM). Das CDM erzeugt daraus eine Lizenzanfrage.

Wichtig: Das zurückgegebene Promise enthält nicht die Lizenzanfrage selbst. Das CDM löst stattdessen auf der Sitzung ein message-Event aus (messageType: "license-request"). Dessen message-Eigenschaft (ein ArrayBuffer) schickt man an den Lizenzserver. Die Antwort des Servers gibt man anschließend mit MediaKeySession.update() an die Sitzung zurück.

Typischerweise ruft man die Methode im Handler des encrypted-Events eines HTMLMediaElement auf. Das Event liefert initDataType und initData direkt mit. Vorher müssen die Schlüssel über navigator.requestMediaKeySystemAccess(), createMediaKeys() und video.setMediaKeys() eingerichtet sein. Die Sitzung selbst erzeugt man mit mediaKeys.createSession().

Pro Sitzung darf generateRequest() nur einmal aufgerufen werden. Für weitere Initialisierungsdaten legt man eine neue Sitzung an.

Parameter

Name Typ Default Beschreibung
$initDataType Pflicht string Format der Initialisierungsdaten, z. B. "cenc" (Common Encryption, PSSH), "keyids" (JSON-Liste von Key-IDs) oder "webm". Das Format muss vom Schlüsselsystem unterstützt werden.
$initData Pflicht ArrayBuffer|TypedArray|DataView Die eigentlichen Initialisierungsdaten, meist event.initData aus dem encrypted-Event.

Rückgabewert

Typ
Promise<undefined>
Beschreibung
Ein Promise, das ohne Wert erfüllt wird, sobald die Anfrage erzeugt wurde. Die Lizenzanfrage selbst kommt über das message-Event der Sitzung. Bei ungültigen Daten wird das Promise abgelehnt, z. B. mit TypeError, NotSupportedError oder InvalidStateError.

Beispiele

Lizenzanfrage im encrypted-Event erzeugen (Clear Key)

const video = document.querySelector('video');

const config = [{
  initDataTypes: ['cenc'],
  videoCapabilities: [{ contentType: 'video/mp4; codecs="avc1.42E01E"' }]
}];

const access = await navigator.requestMediaKeySystemAccess('org.w3.clearkey', config);
const mediaKeys = await access.createMediaKeys();
await video.setMediaKeys(mediaKeys);

video.addEventListener('encrypted', async (event) => {
  const session = mediaKeys.createSession();

  session.addEventListener('message', async (msgEvent) => {
    // Lizenzanfrage an den Server senden
    const response = await fetch('https://license.example.com/clearkey', {
      method: 'POST',
      body: msgEvent.message
    });
    const license = await response.arrayBuffer();
    await session.update(license);
    console.log('Lizenz übernommen');
  });

  await session.generateRequest(event.initDataType, event.initData);
  console.log('Lizenzanfrage erzeugt:', event.initDataType);
});
Lizenzanfrage erzeugt: cenc Lizenz übernommen

Anfrage mit bekannten Key-IDs (keyids-Format)

const toBase64Url = (bytes) =>
  btoa(String.fromCharCode(...bytes))
    .replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');

const keyId = new Uint8Array([0x10,0x77,0xef,0xec,0xc0,0xb2,0x4d,0x02,
                              0xac,0xe3,0x3c,0x1e,0x52,0xe2,0xfb,0x4b]);

const initData = new TextEncoder().encode(
  JSON.stringify({ kids: [toBase64Url(keyId)] })
);

const access = await navigator.requestMediaKeySystemAccess('org.w3.clearkey', [{
  initDataTypes: ['keyids'],
  videoCapabilities: [{ contentType: 'video/webm; codecs="vp9"' }]
}]);
const mediaKeys = await access.createMediaKeys();
const session = mediaKeys.createSession('temporary');

session.addEventListener('message', (e) => {
  console.log('Nachrichtentyp:', e.messageType);
});

await session.generateRequest('keyids', initData);
Nachrichtentyp: license-request

Fehlerbehandlung bei nicht unterstütztem Format

const handleEncrypted = async (mediaKeys, event) => {
  const session = mediaKeys.createSession();
  try {
    await session.generateRequest(event.initDataType, event.initData);
  } catch (err) {
    // z. B. NotSupportedError, wenn das CDM das Format nicht kennt
    console.error(`generateRequest fehlgeschlagen: ${err.name}`);
    await session.close();
  }
};
generateRequest fehlgeschlagen: NotSupportedError

// Wichtig · Fallstricke

  • Nur einmal pro Sitzung: Ein zweiter Aufruf auf derselben MediaKeySession führt zu einem InvalidStateError. Das gilt auch für eine bereits geschlossene Sitzung.
  • Listener zuerst registrieren: Den message-Listener vor generateRequest() anhängen, sonst kann die Lizenzanfrage verloren gehen.
  • Leere Initialisierungsdaten führen zu einem TypeError. Ein von der Konfiguration nicht unterstütztes initDataType führt zu einem NotSupportedError.
  • Doppelte encrypted-Events: Browser lösen encrypted oft mehrfach aus, etwa für Audio und Video oder mehrere PSSH-Boxen. Bereits verarbeitete initData sollte man erkennen und ignorieren, um überflüssige Sitzungen und Lizenzanfragen zu vermeiden.
  • Sicherer Kontext: EME ist nur über HTTPS verfügbar. Welche Schlüsselsysteme es gibt, hängt vom Browser ab: Widevine in Chrome, Firefox und Edge, FairPlay in Safari, PlayReady in Edge. Nur org.w3.clearkey ist weitgehend überall vorhanden. Safari/FairPlay verwendet teils das eigene initDataType "sinf" bzw. "skd".
  • In iframes kann die Permissions-Policy encrypted-media die Nutzung blockieren.