Signatur
Beschreibung
Die Eigenschaft framesEncoded gehört zum Wörterbuch RTCOutboundRtpStreamStats. Das ist der Statistikeintrag mit type === "outbound-rtp", den RTCPeerConnection.getStats() oder RTCRtpSender.getStats() liefert. Sie gibt als ganze Zahl an, wie viele Frames der Encoder für diese Medienquelle insgesamt erfolgreich kodiert hat. Der Wert steigt monoton an, solange die Verbindung besteht.
Die Eigenschaft gibt es nur bei Videostreams. Bei Audio-Einträgen (kind === "audio") ist sie nicht vorhanden. Bei Simulcast hat jede Schicht (jede SSRC bzw. rid) einen eigenen outbound-rtp-Eintrag mit einem eigenen Zähler.
Sinnvoll ist der Wert vor allem als Differenz zwischen zwei Messungen. Teilt man den Zuwachs von framesEncoded durch den Zeitabstand der timestamp-Werte, erhält man die tatsächliche Kodier-Bildrate. Zusammen mit totalEncodeTime ergibt sich die durchschnittliche Kodierzeit pro Frame, zusammen mit framesSent sieht man, ob kodierte Frames nicht verschickt wurden. So lassen sich CPU-Engpässe, Bandbreitenbegrenzung und Einbrüche der Bildrate erkennen.
Rückgabewert
undefined.Beispiele
Kodierte Frames einmalig auslesen
// pc ist eine verbundene RTCPeerConnection mit Videospur
const logFramesEncoded = async (pc) => {
const stats = await pc.getStats();
stats.forEach((report) => {
if (report.type === 'outbound-rtp' && report.kind === 'video') {
console.log(`SSRC ${report.ssrc}: ${report.framesEncoded} Frames kodiert`);
}
});
};
await logFramesEncoded(pc);
Tatsächliche Kodier-Bildrate (fps) berechnen
const sender = pc.getSenders().find((s) => s.track?.kind === 'video');
let previous = null;
const measureFps = async () => {
const stats = await sender.getStats();
for (const report of stats.values()) {
if (report.type !== 'outbound-rtp') continue;
if (previous) {
const frames = report.framesEncoded - previous.framesEncoded;
const seconds = (report.timestamp - previous.timestamp) / 1000;
console.log(`Kodier-FPS: ${(frames / seconds).toFixed(1)}`);
}
previous = report;
}
};
const timer = setInterval(measureFps, 1000);
// später: clearInterval(timer);
Durchschnittliche Kodierzeit pro Frame und Engpass-Analyse
const analyzeEncoder = async (pc) => {
const stats = await pc.getStats();
for (const r of stats.values()) {
if (r.type !== 'outbound-rtp' || r.kind !== 'video' || !r.framesEncoded) continue;
const avgMs = (r.totalEncodeTime / r.framesEncoded) * 1000;
console.log(`Ø Kodierzeit: ${avgMs.toFixed(2)} ms/Frame`);
console.log(`Nicht gesendet: ${r.framesEncoded - (r.framesSent ?? r.framesEncoded)}`);
if (r.qualityLimitationReason && r.qualityLimitationReason !== 'none') {
console.warn(`Qualität begrenzt durch: ${r.qualityLimitationReason}`);
}
}
};
await analyzeEncoder(pc);
// Wichtig · Fallstricke
- Nur Video: Bei Audio-Streams fehlt die Eigenschaft. Filtern Sie deshalb immer nach
kind === "video"oder prüfen Sie aufundefined, sonst erhalten SieNaNin Berechnungen. - Kumulativ: Der Absolutwert sagt wenig aus. Werten Sie Differenzen zwischen zwei Messungen aus und teilen Sie durch die Differenz der
timestamp-Werte in Millisekunden. - Zurücksetzen: Wird die Spur mit
replaceTrack()ersetzt, der Codec neu ausgehandelt oder eine Simulcast-Schicht deaktiviert, kann ein neuer Eintrag mit neueridentstehen. Ordnen Sie Messungen deshalb über dieidzu und nicht über die Reihenfolge. - Simulcast/SVC: Jede Schicht zählt separat. Für eine Gesamtzahl müssen die Einträge summiert werden.
- Kompatibilität: Wird von Chromium-Browsern, Firefox und Safari unterstützt. Ältere Implementierungen lieferten den Wert teilweise im veralteten
track-Statistiktyp. Prüfen Sie bei älteren Browsern auf das Vorhandensein der Eigenschaft. - Wenn
getStats()sehr oft aufgerufen wird (deutlich häufiger als einmal pro Sekunde), kostet das CPU-Zeit und bringt kaum zusätzliche Aussagekraft.