Signatur
Beschreibung
Die schreibgeschützte Eigenschaft keyFramesEncoded eines RTCOutboundRtpStreamStats-Objekts zählt, wie viele Schlüsselbilder (auch I-Frames oder IDR-Frames genannt) der Encoder für diesen ausgehenden Stream erzeugt hat. Schlüsselbilder lassen sich ohne vorherige Bilder dekodieren und sind deshalb deutlich größer als Delta-Frames.
Den Wert erhalten Sie über RTCPeerConnection.getStats() oder RTCRtpSender.getStats(): Suchen Sie im zurückgegebenen RTCStatsReport nach Einträgen mit type === "outbound-rtp" und kind === "video". Der Zähler ist kumulativ und wächst seit Beginn des Streams stetig.
Nützlich ist die Kennzahl vor allem zur Diagnose: Steigt sie ungewöhnlich schnell, deutet das auf häufige Key-Frame-Anforderungen der Gegenseite hin (PLI/FIR, siehe pliCount und firCount), meist ausgelöst durch Paketverluste. Setzt man sie ins Verhältnis zu framesEncoded, erhält man den Anteil der Schlüsselbilder – ein hoher Anteil kostet Bandbreite und senkt die Bildqualität.
Rückgabewert
unsigned long) mit der kumulierten Anzahl erfolgreich kodierter Schlüsselbilder. Bei Audio-Streams oder fehlender Browser-Unterstützung ist die Eigenschaft nicht vorhanden (undefined).Beispiele
Kodierte Schlüsselbilder eines Senders auslesen
// pc ist eine bestehende RTCPeerConnection mit Video-Track
const logKeyFrames = async (pc) => {
const report = await pc.getStats();
report.forEach((stats) => {
if (stats.type === "outbound-rtp" && stats.kind === "video") {
console.log(`SSRC ${stats.ssrc}: ${stats.keyFramesEncoded} Key Frames von ${stats.framesEncoded} Frames`);
}
});
};
await logKeyFrames(pc);
Key-Frame-Rate pro Sekunde überwachen
const sender = pc.getSenders().find((s) => s.track?.kind === "video");
let previous = null;
setInterval(async () => {
const report = await sender.getStats();
for (const stats of report.values()) {
if (stats.type !== "outbound-rtp") continue;
if (previous) {
const seconds = (stats.timestamp - previous.timestamp) / 1000;
const rate = (stats.keyFramesEncoded - previous.keyFramesEncoded) / seconds;
if (rate > 0.5) {
console.warn(`Viele Key Frames: ${rate.toFixed(2)}/s (PLI: ${stats.pliCount}, FIR: ${stats.firCount})`);
}
}
previous = stats;
}
}, 2000);
Anteil der Schlüsselbilder berechnen (mit Fallback)
const keyFrameRatio = (stats) => {
const { keyFramesEncoded, framesEncoded } = stats;
if (keyFramesEncoded === undefined || !framesEncoded) return null;
return keyFramesEncoded / framesEncoded;
};
const report = await pc.getStats();
const outbound = [...report.values()].find(
(s) => s.type === "outbound-rtp" && s.kind === "video"
);
const ratio = outbound ? keyFrameRatio(outbound) : null;
console.log(ratio === null ? "Nicht verfügbar" : `${(ratio * 100).toFixed(1)} % Key Frames`);
// Wichtig · Fallstricke
- Nur für Video-Streams definiert; bei
kind === \"audio\"fehlt die Eigenschaft. - Der Wert ist kumulativ. Für Raten immer die Differenz zweier Messungen durch die Differenz der
timestamp-Werte teilen. - Bei Simulcast gibt es pro Schicht (
rid) einen eigenenoutbound-rtp-Eintrag mit eigenem Zähler – für eine Gesamtzahl summieren. - Wird ein Track per
replaceTrack()gewechselt oder der Encoder neu gestartet, erzeugt er typischerweise ein zusätzliches Schlüsselbild. - Browser-Unterstützung: Chromium und Safari schon lange, Firefox erst in neueren Versionen – vor der Nutzung auf
undefinedprüfen.