Start · Sprachen · JavaScript · Referenz · RTCRtpScriptTransformer.writable

RTCRtpScriptTransformer.writable

Eigenschaft

Schreibgeschützte Eigenschaft, die einen <code>WritableStream</code> liefert, in den ein Worker transformierte kodierte Audio-/Videoframes zurück in die WebRTC-Pipeline schreibt.

seit JavaScript Baseline 2025 (Chrome 141+/ Edge, Firefox 117+, Sa Kategorie: webapi

Signatur

RTCRtpScriptTransformer.writable

Beschreibung

Die Eigenschaft writable eines RTCRtpScriptTransformer gibt einen WritableStream zurück. Er ist das Ziel für kodierte Medienframes (RTCEncodedVideoFrame oder RTCEncodedAudioFrame), nachdem Ihr Code im Worker sie verarbeitet hat. Beim Sender gehen die geschriebenen Frames an den Paketierer und dann ins Netz, beim Empfänger an den Decoder.

Der RTCRtpScriptTransformer existiert nur im Worker-Kontext. Er steht im Ereignis rtctransform als event.transformer bereit, sobald im Hauptthread ein RTCRtpScriptTransform einem RTCRtpSender.transform oder RTCRtpReceiver.transform zugewiesen wurde. Üblicherweise verbindet man readable über einen TransformStream mit writable: readable.pipeThrough(transform).pipeTo(writable).

Typische Einsatzfälle sind Ende-zu-Ende-Verschlüsselung (z. B. SFrame-ähnliche Verfahren), das Anhängen von Metadaten an Frames oder das gezielte Verwerfen von Frames. Ein Frame, der nicht in writable geschrieben wird, gilt als verworfen.

Rückgabewert

Typ
WritableStream<RTCEncodedVideoFrame | RTCEncodedAudioFrame>
Beschreibung
Ein WritableStream, der kodierte Frames annimmt und sie an die WebRTC-Pipeline (Paketierer bzw. Decoder) weiterreicht. Pro Transformer immer dieselbe Instanz.

Beispiele

Einfaches Durchreichen (Worker)

// worker.js
addEventListener('rtctransform', (event) => {
  const { readable, writable } = event.transformer;
  // Frames unverändert weiterleiten
  readable.pipeTo(writable).catch((err) => console.error('Pipe-Fehler:', err));
});

XOR-"Verschlüsselung" mit TransformStream

// Hauptthread
const worker = new Worker('worker.js');
const pc = new RTCPeerConnection();
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
const sender = pc.addTrack(stream.getVideoTracks()[0], stream);
sender.transform = new RTCRtpScriptTransform(worker, { key: 0x5a });

// worker.js
addEventListener('rtctransform', (event) => {
  const { readable, writable, options } = event.transformer;
  const xor = new TransformStream({
    transform(frame, controller) {
      const data = new Uint8Array(frame.data);
      for (let i = 0; i < data.length; i++) data[i] ^= options.key;
      frame.data = data.buffer;
      controller.enqueue(frame); // landet in writable
    }
  });
  readable.pipeThrough(xor).pipeTo(writable);
});

Direkt mit einem Writer schreiben und Frames verwerfen

// worker.js
addEventListener('rtctransform', async (event) => {
  const reader = event.transformer.readable.getReader();
  const writer = event.transformer.writable.getWriter();
  let count = 0;
  while (true) {
    const { value: frame, done } = await reader.read();
    if (done) break;
    count++;
    // Nur Audio-Frames mit Inhalt weitergeben
    if (frame.data.byteLength > 0) {
      await writer.write(frame);
    }
  }
  console.log(`Verarbeitet: ${count} Frames`);
});
Verarbeitet: 1234 Frames

// Wichtig · Fallstricke

  • Nur im Worker: RTCRtpScriptTransformer kann man nicht selbst erzeugen. Man erhält ihn ausschließlich über das Ereignis rtctransform im dedizierten Worker.
  • Sperre: Nach getWriter() oder pipeTo() ist der Stream gesperrt. Ein zweiter Writer oder eine zweite Pipe löst einen TypeError aus.
  • Frames nicht klonen und liegen lassen: Schreiben Sie nur Frames aus dem zugehörigen readable. Fremde oder schon geschriebene Frames können abgewiesen werden.
  • Verworfene Frames: Bei Video können fehlende Frames Artefakte erzeugen, bis ein Keyframe kommt. Beim Sender hilft dann generateKeyFrame(), beim Empfänger sendKeyFrameRequest().
  • Kompatibilität: Firefox und Safari unterstützen die Script-Transform-API seit Längerem. Chrome hatte lange nur die ältere, nicht standardisierte Variante createEncodedStreams() (Insertable Streams) und bietet RTCRtpScriptTransform erst seit neueren Versionen an. Prüfen Sie die Unterstützung per Feature-Erkennung: 'RTCRtpScriptTransform' in window.
  • Sicherheit: Eine XOR-Transformation ist keine echte Verschlüsselung. Für E2EE verwenden Sie crypto.subtle (z. B. AES-GCM) und lassen Header-Bytes unverschlüsselt, die der Paketierer benötigt.