Signatur
Beschreibung
Die Eigenschaft framesPerSecond des Wörterbuchs RTCInboundRtpStreamStats enthält die Anzahl der Frames, die in der letzten Sekunde decodiert wurden. Sie beschreibt also die tatsächlich erreichte Bildrate beim Empfänger und nicht die Bildrate, die der Sender anstrebt.
Den Wert erhalten Sie über RTCPeerConnection.getStats() oder RTCRtpReceiver.getStats(). Im zurückgegebenen RTCStatsReport suchen Sie Einträge mit type === "inbound-rtp" und kind === "video". Die Eigenschaft gibt es nur bei Videostreams, bei Audio-Streams fehlt sie.
In der Praxis nutzen Sie framesPerSecond für Qualitätsanzeigen in Videokonferenzen, zur Erkennung von Rucklern (z. B. bei Überlastung der CPU oder Paketverlust) und für Telemetrie. Wenn Sie ihn zusammen mit framesDecoded, framesDropped und frameWidth/frameHeight auswerten, sehen Sie, wie gut die Wiedergabe tatsächlich läuft.
Rückgabewert
undefined, wenn es sich nicht um einen Videostream handelt oder noch keine Frames decodiert wurden.Beispiele
Aktuelle Empfangs-Bildrate auslesen
// pc ist eine bestehende, verbundene RTCPeerConnection
const logFps = async (pc) => {
const report = await pc.getStats();
report.forEach((stats) => {
if (stats.type === 'inbound-rtp' && stats.kind === 'video') {
console.log(`Empfangene FPS: ${stats.framesPerSecond ?? 'n/a'}`);
}
});
};
await logFps(pc);
Ruckeln erkennen und Warnung anzeigen
const MIN_FPS = 15;
const monitorReceiver = (receiver, onLowFps) => {
const timer = setInterval(async () => {
const report = await receiver.getStats();
for (const stats of report.values()) {
if (stats.type !== 'inbound-rtp' || stats.kind !== 'video') continue;
const fps = stats.framesPerSecond;
if (typeof fps === 'number' && fps < MIN_FPS) {
onLowFps(fps, stats.framesDropped ?? 0);
}
}
}, 2000);
return () => clearInterval(timer);
};
const [videoReceiver] = pc.getReceivers().filter((r) => r.track.kind === 'video');
const stop = monitorReceiver(videoReceiver, (fps, dropped) => {
console.warn(`Niedrige Bildrate: ${fps.toFixed(1)} FPS, verworfen: ${dropped}`);
});
// später: stop();
Eigene Berechnung aus framesDecoded als Rückfallebene
let last = null;
const computeFps = async (pc) => {
const report = await pc.getStats();
for (const s of report.values()) {
if (s.type !== 'inbound-rtp' || s.kind !== 'video') continue;
if (typeof s.framesPerSecond === 'number') return s.framesPerSecond;
// Fallback: Differenz von framesDecoded über die Zeit (timestamp in ms)
if (last) {
const fps = ((s.framesDecoded - last.framesDecoded) * 1000) / (s.timestamp - last.timestamp);
last = s;
return fps;
}
last = s;
}
return undefined;
};
// Wichtig · Fallstricke
- Nur Video: Bei Audio-Einträgen (
kind === "audio") gibt es die Eigenschaft nicht. Prüfen Sie immer aufundefined. - Decodiert statt empfangen oder angezeigt: Der Wert zählt decodierte Frames. Die Anzeige kann trotzdem stocken, zum Beispiel wenn das Rendern zu lange dauert. Für die angezeigten Frames gibt es
framesRenderedbzw.HTMLVideoElement.getVideoPlaybackQuality(). - Kurzes Zeitfenster: Der Wert bezieht sich auf die letzte Sekunde und schwankt deshalb stark. Für Anzeigen sollten Sie ihn glätten (z. B. gleitender Mittelwert).
- Browser-Unterschiede: Ältere Browser-Versionen (insbesondere Firefox und Safari) haben die Eigenschaft erst spät eingeführt. Früher stand sie teilweise nur in den veralteten
track-Statistiken. Als Rückfallebene können Sie die Bildrate aus der Differenz vonframesDecodedundtimestampberechnen. getStats()kostet Rechenzeit. Rufen Sie es nicht öfter als etwa einmal pro Sekunde auf.