Start · Sprachen · JavaScript · Referenz · new RTCRtpScriptTransform()

new RTCRtpScriptTransform()

Methode

Erstellt ein <code>RTCRtpScriptTransform</code>, das kodierte WebRTC-Mediendaten eines Senders oder Empfängers zur Verarbeitung an einen Worker weiterleitet.

seit JavaScript Firefox 117+, Safari 15.4+; Chrome ab Version 141 Kategorie: webapi

Signatur

new RTCRtpScriptTransform(worker, options, transfer)

Beschreibung

Der Konstruktor RTCRtpScriptTransform() gehört zur API WebRTC Encoded Transform. Er verbindet einen RTCRtpSender oder RTCRtpReceiver mit einem Worker. Die kodierten Audio- oder Videoframes laufen durch den Worker, bevor sie paketiert und versendet oder nach dem Empfang dekodiert werden.

So setzt man zum Beispiel Ende-zu-Ende-Verschlüsselung (E2EE) über einen SFU-Server um, hängt Metadaten an Frames an oder fängt Frames zum Debuggen ab. Die Verarbeitung findet komplett im Worker statt und blockiert den Haupt-Thread deshalb nicht.

Sobald das Objekt erstellt ist, löst der Worker im eigenen Kontext das Event rtctransform aus. Dessen Eigenschaft event.transformer ist ein RTCRtpScriptTransformer mit einem readable- und einem writable-Stream sowie den übergebenen options. Aktiv wird die Transformation erst, wenn du sie der Eigenschaft sender.transform bzw. receiver.transform zuweist.

Parameter

Name Typ Default Beschreibung
$worker Pflicht Worker Dedizierter Worker, in dem das Event rtctransform ausgelöst wird und der die Frames verarbeitet.
$options any undefined Beliebiger strukturiert klonbarer Wert, der im Worker als event.transformer.options ankommt, z. B. { operation: "encrypt" }.
$transfer Array<Transferable> [] Übertragbare Objekte wie ein MessagePort, deren Besitz an den Worker übergeht (wie bei postMessage()).

Rückgabewert

Typ
RTCRtpScriptTransform
Beschreibung
Ein neues RTCRtpScriptTransform-Objekt. Weise es RTCRtpSender.transform oder RTCRtpReceiver.transform zu.

Beispiele

Transformation für Sender und Empfänger anlegen

// main.js
const worker = new Worker('transform-worker.js');
const pc = new RTCPeerConnection();

const stream = await navigator.mediaDevices.getUserMedia({ video: true });
const [track] = stream.getVideoTracks();
const sender = pc.addTrack(track, stream);

// Ausgehende Frames verschlüsseln
sender.transform = new RTCRtpScriptTransform(worker, { operation: 'encrypt' });

// Eingehende Frames entschlüsseln
pc.addEventListener('track', ({ receiver }) => {
  receiver.transform = new RTCRtpScriptTransform(worker, { operation: 'decrypt' });
});

Worker: Frames per XOR verändern (Demo-Verschlüsselung)

// transform-worker.js
const KEY = 0x5a;

const xorFrame = (frame, controller) => {
  const data = new Uint8Array(frame.data);
  // Bei Video die ersten Bytes (Header) unverändert lassen
  const skip = frame.type === 'key' ? 10 : 3;
  for (let i = skip; i < data.length; i++) data[i] ^= KEY;
  frame.data = data.buffer;
  controller.enqueue(frame);
};

self.addEventListener('rtctransform', ({ transformer }) => {
  console.log('Operation:', transformer.options.operation);
  transformer.readable
    .pipeThrough(new TransformStream({ transform: xorFrame }))
    .pipeTo(transformer.writable);
});
Operation: encrypt Operation: decrypt

Schlüssel über einen MessagePort nachreichen

// main.js
const worker = new Worker('transform-worker.js');
const { port1, port2 } = new MessageChannel();

sender.transform = new RTCRtpScriptTransform(
  worker,
  { operation: 'encrypt', port: port2 },
  [port2] // Port an den Worker übertragen
);

// Später: Schlüsselwechsel
port1.postMessage({ type: 'rotate-key', keyId: 2 });

// transform-worker.js (Ausschnitt)
self.onrtctransform = ({ transformer }) => {
  transformer.options.port.onmessage = ({ data }) => {
    console.log('Neuer Schlüssel:', data.keyId);
  };
};
Neuer Schlüssel: 2

// Wichtig · Fallstricke

  • Browser-Unterstützung: Firefox und Safari unterstützen den Konstruktor, Chrome erst ab neueren Versionen. Ältere Chromium-Versionen kennen nur die nicht standardisierten Insertable Streams mit RTCRtpSender.createEncodedStreams() und encodedInsertableStreams: true in der RTCPeerConnection-Konfiguration. Prüfe die Unterstützung vorab: 'RTCRtpScriptTransform' in window.
  • Der Konstruktor steht nur im Fenster-Kontext zur Verfügung. Das Event rtctransform wird dagegen im Worker ausgelöst. Registriere den Listener deshalb im Worker-Skript, nicht im Haupt-Thread.
  • Jedes Frame muss mit controller.enqueue() weitergereicht werden, sonst stockt der Medienfluss. Übersprungene Frames führen bei Video zu Artefakten, bis der nächste Keyframe eintrifft. Mit transformer.sendKeyFrameRequest() bzw. generateKeyFrame() lässt sich ein Keyframe anfordern.
  • Codec-Header (z. B. VP8-Payload-Header) sollten unverschlüsselt bleiben, damit die SFU weiterhin korrekt weiterleiten kann.
  • Sicherheit: Das XOR-Beispiel ist keine echte Verschlüsselung. Für E2EE solltest du crypto.subtle (z. B. AES-GCM) mit sauberer Schlüsselverwaltung verwenden. Die Seite muss in einem sicheren Kontext (HTTPS) laufen.
  • Ein RTCRtpScriptTransform kann nur einem einzigen Sender oder Empfänger zugewiesen werden. Wird es ein zweites Mal zugewiesen, wird ein InvalidStateError ausgelöst.