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

MediaKeySession.update()

Methode

Übergibt eine Antwort des Lizenzservers (z. B. eine Lizenz) an das CDM der Sitzung und gibt ein <code>Promise&lt;void&gt;</code> zurück.

seit JavaScript Baseline: alle modernen Browser (Encrypted Media E Kategorie: webapi

Signatur

MediaKeySession.prototype.update(response)

Beschreibung

Die Methode update() ist Teil der Encrypted Media Extensions (EME). Mit ihr reicht die Anwendung Daten an das Content Decryption Module (CDM) weiter, die sie vom Lizenzserver erhalten hat. Meist handelt es sich um eine Lizenz mit den Schlüsseln, die das CDM zum Entschlüsseln des Medieninhalts braucht.

Der typische Ablauf: Nach generateRequest() löst das CDM ein message-Ereignis auf der MediaKeySession aus. Die Anwendung schickt event.message an den Lizenzserver und übergibt dessen Antwort als ArrayBuffer oder TypedArray an update(). Hat das CDM die Antwort verarbeitet, wird das Promise erfüllt. Danach aktualisiert sich die Eigenschaft keyStatuses, und das Ereignis keystatuseschange wird ausgelöst.

Das Format der Antwort hängt vom Schlüsselsystem ab. Bei org.w3.clearkey ist es ein JSON Web Key Set (JWK Set) als UTF-8-Bytes, bei Widevine, PlayReady oder FairPlay ein proprietäres Binärformat. Auch bei Lizenzerneuerungen (messageType ist dann "license-renewal") und bei der Freigabe persistenter Lizenzen ("license-release") wird update() aufgerufen.

Parameter

Name Typ Default Beschreibung
$response Pflicht ArrayBuffer | TypedArray | DataView Die Antwort des Lizenzservers bzw. die Daten für das CDM. Das Format hängt vom Schlüsselsystem ab (bei Clear Key ein JWK Set als UTF-8-Bytes).

Rückgabewert

Typ
Promise<void>
Beschreibung
Ein Promise, das mit undefined erfüllt wird, sobald das CDM die Daten verarbeitet hat. Es wird abgelehnt, wenn response leer ist (TypeError), die Sitzung geschlossen oder nicht initialisiert ist (InvalidStateError) oder das CDM die Daten nicht verarbeiten kann (z. B. TypeError oder NotSupportedError).

Beispiele

Lizenzanfrage beantworten (allgemeiner Ablauf)

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

video.addEventListener('encrypted', async (event) => {
  const access = await navigator.requestMediaKeySystemAccess('com.widevine.alpha', [{
    initDataTypes: ['cenc'],
    videoCapabilities: [{ contentType: 'video/mp4; codecs="avc1.42E01E"' }]
  }]);
  const mediaKeys = await access.createMediaKeys();
  await video.setMediaKeys(mediaKeys);

  const session = mediaKeys.createSession();
  session.addEventListener('message', async (msgEvent) => {
    // Nachricht des CDM an den Lizenzserver senden
    const res = await fetch('https://license.example.com/widevine', {
      method: 'POST',
      body: msgEvent.message
    });
    const license = await res.arrayBuffer();
    // Lizenz an das CDM übergeben
    await session.update(license);
    console.log('Lizenz geladen');
  });

  await session.generateRequest(event.initDataType, event.initData);
});
Lizenz geladen

Clear Key: JWK Set lokal erzeugen und übergeben

// Hilfsfunktion: Bytes → base64url ohne Padding
const toBase64Url = (bytes) =>
  btoa(String.fromCharCode(...bytes))
    .replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');

const keyId = new Uint8Array([0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f]);
const key   = new Uint8Array([0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf]);

const handleMessage = async (event) => {
  const jwkSet = {
    keys: [{ kty: 'oct', kid: toBase64Url(keyId), k: toBase64Url(key) }],
    type: 'temporary'
  };
  const response = new TextEncoder().encode(JSON.stringify(jwkSet));
  await event.target.update(response);
  console.log('Clear-Key-Lizenz übergeben');
};

// session.addEventListener('message', handleMessage);
Clear-Key-Lizenz übergeben

Fehlerbehandlung und Schlüsselstatus prüfen

const applyLicense = async (session, license) => {
  try {
    await session.update(license);
    for (const [keyId, status] of session.keyStatuses) {
      console.log(`Schlüssel ${keyId.byteLength} Bytes: ${status}`);
    }
  } catch (err) {
    // z. B. TypeError bei ungültiger Lizenz, InvalidStateError bei geschlossener Sitzung
    console.error(`update() fehlgeschlagen: ${err.name} – ${err.message}`);
  }
};
Schlüssel 16 Bytes: usable

// Wichtig · Fallstricke

  • Nur in sicheren Kontexten: EME steht nur über HTTPS (oder localhost) zur Verfügung. In iframes kann die Permissions Policy encrypted-media den Zugriff sperren.
  • Format des Schlüsselsystems: update() prüft die Daten nicht generisch. Ein falsches Format führt zu einer Ablehnung mit TypeError. Bei Clear Key müssen kid und k base64url-kodiert sein, ohne Padding.
  • Sitzungszustand: Vor generateRequest() bzw. load() oder nach close() führt der Aufruf zu einem InvalidStateError.
  • Leere Antwort: Ein leerer Puffer wird mit TypeError abgelehnt.
  • Nicht auf das Promise allein verlassen: Ob ein Schlüssel wirklich nutzbar ist (usable, expired, output-restricted …), zeigen erst keyStatuses bzw. das Ereignis keystatuseschange.
  • Sicherheit: Lizenzanfragen nur über authentifizierte HTTPS-Verbindungen an vertrauenswürdige Server senden. Die Lizenzserver-URL und Authentifizierungs-Token nicht ungeschützt im Client-Code hinterlegen.
  • Kompatibilität: Wird von allen modernen Browsern unterstützt. Welche Schlüsselsysteme verfügbar sind, unterscheidet sich aber: Chrome und Firefox bieten Widevine, Edge PlayReady, Safari FairPlay. Clear Key ist nicht überall verfügbar.