Signatur
Beschreibung
Die Methode generateKeyFrame() steht im Worker-Kontext eines RTCRtpScriptTransformer zur Verfügung. Sie veranlasst den Video-Encoder des zugehörigen RTCRtpSender, ein Schlüsselbild (auch I-Frame oder Intra-Frame) zu erzeugen. Ein Schlüsselbild enthält alle Informationen, die zum Dekodieren des Bildes nötig sind, und hängt nicht von vorherigen Frames ab.
Gebraucht wird die Methode vor allem bei Ende-zu-Ende-Verschlüsselung (E2EE) mit Encoded Transforms: Nach einem Schlüsselwechsel sollte der erste mit dem neuen Schlüssel verschlüsselte Frame ein Schlüsselbild sein. So kann der Empfänger ab diesem Frame dekodieren, ohne auf alte, mit dem vorherigen Schlüssel verschlüsselte Delta-Frames angewiesen zu sein. Weitere Einsatzfälle sind das Zurücksetzen des Bildstroms nach Paketverlust oder wenn neue Teilnehmende einer Konferenz beitreten.
Die Methode funktioniert nur auf der Senderseite und nur bei Video. Wird Simulcast verwendet, lässt sich über den optionalen Parameter rid gezielt ein einzelner Encoding-Layer ansprechen; ohne rid erzeugen alle Encoder ein Schlüsselbild. Auf der Empfängerseite verwendest du stattdessen sendKeyFrameRequest(), um beim Gegenüber ein Schlüsselbild anzufordern.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $rid | string | Optionale RTP-Stream-ID (Restriction Identifier) eines Simulcast-Encodings, z. B. "h" oder "low". Muss der RID-Syntax entsprechen (alphanumerisch). Fehlt der Wert, wird für alle Encodings des Senders ein Schlüsselbild angefordert. |
Rückgabewert
Promise, das erfüllt wird, sobald das angeforderte Schlüsselbild erzeugt wurde bzw. in den Stream des Transformers eingereiht wird. Wird abgelehnt mit InvalidStateError (kein Video-Encoder aktiv oder Transformer ist empfangsseitig), NotFoundError (kein passender Encoder, z. B. weil der Sender inaktiv oder der Track beendet ist, oder unbekannte rid) bzw. TypeError (ungültige rid-Syntax).Beispiele
Hauptthread: Sender-Transform mit Worker einrichten
// main.js
const worker = new Worker('e2ee-worker.js');
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
const pc = new RTCPeerConnection();
const [track] = stream.getVideoTracks();
const sender = pc.addTrack(track, stream);
// Transform an den Sender hängen; die Optionen landen im Worker als transformer.options
sender.transform = new RTCRtpScriptTransform(worker, { side: 'send' });
// Später: Schlüsselwechsel auslösen
const rotateKey = () => worker.postMessage({ type: 'rotateKey', key: crypto.getRandomValues(new Uint8Array(16)) });
setInterval(rotateKey, 60_000);
Worker: nach Schlüsselwechsel ein Schlüsselbild erzwingen
// e2ee-worker.js
let currentKey = null;
let transformer = null;
self.onrtctransform = (event) => {
transformer = event.transformer;
if (transformer.options.side !== 'send') return;
const xor = new TransformStream({
transform(frame, controller) {
if (currentKey) {
const data = new Uint8Array(frame.data);
// Demo-"Verschlüsselung" ab Byte 10 (Header bleibt lesbar)
for (let i = 10; i < data.length; i++) data[i] ^= currentKey[i % currentKey.length];
frame.data = data.buffer;
}
controller.enqueue(frame);
}
});
transformer.readable.pipeThrough(xor).pipeTo(transformer.writable);
};
self.onmessage = async ({ data }) => {
if (data.type !== 'rotateKey' || !transformer) return;
currentKey = data.key;
try {
await transformer.generateKeyFrame();
console.log('Schlüsselbild mit neuem Schlüssel angefordert');
} catch (err) {
console.error(`${err.name}: ${err.message}`);
}
};
Simulcast: nur für einen Layer ein Schlüsselbild anfordern
// Im Worker, transformer stammt aus dem rtctransform-Event
const requestKeyFrame = async (transformer, rid) => {
try {
await transformer.generateKeyFrame(rid);
console.log(`Schlüsselbild für Layer "${rid}" erzeugt`);
} catch (err) {
if (err.name === 'NotFoundError') {
console.warn(`Kein aktiver Encoder für rid "${rid}"`);
} else {
throw err;
}
}
};
await requestKeyFrame(transformer, 'h');
// Wichtig · Fallstricke
- Nur im Worker:
RTCRtpScriptTransformer-Instanzen gibt es ausschließlich imrtctransform-Event eines Dedicated Workers. Im Hauptthread lässt sich die Methode nicht aufrufen. Du steuerst sie perpostMessage()an. - Nur sendeseitig und nur Video: Hängt der Transformer an einem
RTCRtpReceiveroder an einem Audio-Track, wird das Promise mitInvalidStateErrorabgelehnt. Auf der Empfängerseite nutzt dusendKeyFrameRequest(). - Timing: Das Promise sagt nichts über die Zustellung beim Empfänger aus. Setze bei E2EE den neuen Schlüssel spätestens dann ein, wenn der Key Frame durch den Transform-Stream läuft. Sonst kann der Empfänger für kurze Zeit nicht dekodieren.
- Performance: Schlüsselbilder sind deutlich größer als Delta-Frames. Häufige Aufrufe erhöhen die Bitrate und können zu Qualitätseinbrüchen oder Stau führen. Rufe die Methode also nur gezielt auf, etwa bei einem Schlüsselwechsel.
- Kompatibilität: Firefox und Safari unterstützen
RTCRtpScriptTransform. Chromium-basierte Browser nutzen bislang meist die ältere, nicht standardisierte APIcreateEncodedStreams()ohne diese Methode. Prüfe daher vorher mit'RTCRtpScriptTransform' in window, ob die API verfügbar ist.