Start · Sprachen · JavaScript · Referenz · RTCRtpScriptTransformer.readable

RTCRtpScriptTransformer.readable

Eigenschaft

Schreibgeschützte Eigenschaft, die einen <code>ReadableStream</code> liefert, aus dem ein Worker die kodierten Audio- oder Videoframes einer WebRTC-Verbindung liest.

seit JavaScript Baseline 2025: Chrome 141+ (neu), Firefox 117+, Sa Kategorie: webapi

Signatur

RTCRtpScriptTransformer.readable

Beschreibung

Die Eigenschaft readable eines RTCRtpScriptTransformer gibt einen ReadableStream zurück, der die kodierten Medienframes eines RTCRtpSender oder RTCRtpReceiver liefert. Die Frames sind Instanzen von RTCEncodedVideoFrame oder RTCEncodedAudioFrame.

Der Transformer existiert nur in einem Dedicated Worker. Er wird dort über das Ereignis rtctransform als event.transformer bereitgestellt, sobald im Hauptthread ein RTCRtpScriptTransform an sender.transform bzw. receiver.transform gebunden wird. Im Worker liest man die Frames aus readable, verändert sie (z. B. Ende-zu-Ende-Verschlüsselung, Metadaten einfügen, Analyse) und schreibt sie in transformer.writable zurück.

Üblicherweise leitet man readable mit pipeThrough() durch einen TransformStream und dann mit pipeTo() weiter an writable. Wer mehr Kontrolle braucht, kann auch direkt einen Reader verwenden (getReader()) oder mit for await...of über den Stream iterieren.

Rückgabewert

Typ
ReadableStream<RTCEncodedVideoFrame | RTCEncodedAudioFrame>
Beschreibung
Ein Stream der eingehenden kodierten Frames. Für jeden Transformer gibt es genau einen Stream, der immer dasselbe Objekt ist.

Beispiele

Hauptthread: Transform an einen Sender binden

// main.js
const worker = new Worker('worker.js');
const pc = new RTCPeerConnection();
const stream = await navigator.mediaDevices.getUserMedia({ video: true });

const [track] = stream.getVideoTracks();
const sender = pc.addTrack(track, stream);

// Löst im Worker das Ereignis 'rtctransform' aus
sender.transform = new RTCRtpScriptTransform(worker, { role: 'sender' });

Worker: Frames per pipeThrough verändern (einfache XOR-„Verschlüsselung“)

// worker.js
const key = 0x5a;

addEventListener('rtctransform', (event) => {
  const transformer = 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] ^= key;
      frame.data = data.buffer;
      controller.enqueue(frame);
    }
  });

  transformer.readable
    .pipeThrough(xor)
    .pipeTo(transformer.writable)
    .catch((err) => console.error('Pipeline abgebrochen:', err));
});

Worker: Frames mit for await...of zählen und durchreichen

// worker.js
addEventListener('rtctransform', async ({ transformer }) => {
  const writer = transformer.writable.getWriter();
  let count = 0;

  for await (const frame of transformer.readable) {
    count++;
    if (frame.type === 'key') {
      console.log(`Keyframe #${count}, ${frame.data.byteLength} Bytes`);
    }
    await writer.write(frame);
  }
});
Keyframe #1, 18342 Bytes

// Wichtig · Fallstricke

  • Nur im Worker: RTCRtpScriptTransformer gibt es ausschließlich im Kontext eines Dedicated Workers. Im Hauptthread kommt man nicht an readable.
  • Kompatibilität: Firefox und Safari unterstützen diese standardisierte API. Ältere Chrome-Versionen boten stattdessen die nicht standardisierte Variante RTCRtpSender.createEncodedStreams() an (dafür musste encodedInsertableStreams: true in der RTCPeerConnection gesetzt sein). Die Feature-Erkennung gelingt mit 'RTCRtpScriptTransform' in window.
  • Frames immer weiterreichen: Frames, die nicht in writable geschrieben werden, gehen verloren – das Video friert ein oder der Ton bricht ab. Bei Video-Frames sollte man auf keinen Fall die Header-Bytes des Codecs verändern, wenn der Empfänger die Transformation nicht rückgängig macht.
  • Sperre: Ein Stream kann immer nur einen Leser haben. Nach pipeThrough() oder getReader() ist readable.locked auf true gesetzt, und ein zweiter Zugriff wirft einen TypeError.
  • Performance: Die Transformation läuft für jeden Frame. Aufwendige Verarbeitung erhöht die Latenz. Wer Schlüssel verwendet, sollte die Web Crypto API nutzen und sie nicht in Schleifen neu erzeugen.