Signatur
Beschreibung
Die schreibgeschützte Eigenschaft framesReceived des Wörterbuchs RTCInboundRtpStreamStats ist ein Zähler: Sie gibt an, wie viele vollständige Frames seit Beginn dieses eingehenden RTP-Streams angekommen sind. Ein Frame zählt, sobald alle zugehörigen RTP-Pakete da sind. Ob er dekodiert oder angezeigt wurde, spielt dafür keine Rolle.
Die Eigenschaft gibt es nur bei Video-Streams (kind === "video"). An die Werte kommst du über RTCPeerConnection.getStats() oder RTCRtpReceiver.getStats(). Im zurückgegebenen RTCStatsReport filterst du die Einträge mit type === "inbound-rtp".
In der Praxis vergleichst du framesReceived vor allem mit framesDecoded, framesDropped und framesPerSecond. So erkennst du, ob Probleme im Netzwerk entstehen (es kommen weniger Frames an) oder beim Empfänger (Frames kommen an, werden aber nicht dekodiert oder verworfen). Liest du den Zähler in regelmäßigen Abständen aus, ergibt die Differenz zweier Messungen geteilt durch die Zeitdifferenz die tatsächliche Empfangsrate.
Rückgabewert
undefined.Beispiele
Empfangene Frames eines Video-Receivers auslesen
// pc ist eine bestehende, verbundene RTCPeerConnection
const logFramesReceived = async (pc) => {
const report = await pc.getStats();
report.forEach((stats) => {
if (stats.type === "inbound-rtp" && stats.kind === "video") {
console.log(`SSRC ${stats.ssrc}: ${stats.framesReceived} Frames empfangen`);
}
});
};
await logFramesReceived(pc);
Tatsächliche Empfangsrate (fps) berechnen
const monitorReceiveRate = (receiver, intervalMs = 1000) => {
let last = null;
return setInterval(async () => {
const report = await receiver.getStats();
for (const stats of report.values()) {
if (stats.type !== "inbound-rtp") continue;
if (last) {
const frames = stats.framesReceived - last.framesReceived;
const seconds = (stats.timestamp - last.timestamp) / 1000;
console.log(`Empfang: ${(frames / seconds).toFixed(1)} fps`);
}
last = stats;
}
}, intervalMs);
};
const [videoReceiver] = pc.getReceivers().filter((r) => r.track.kind === "video");
const timer = monitorReceiveRate(videoReceiver);
// später: clearInterval(timer);
Netzwerk- vs. Decoder-Probleme unterscheiden
const diagnoseVideo = async (pc) => {
const report = await pc.getStats();
for (const s of report.values()) {
if (s.type !== "inbound-rtp" || s.kind !== "video") continue;
const notDecoded = s.framesReceived - (s.framesDecoded ?? 0);
console.log({
empfangen: s.framesReceived,
dekodiert: s.framesDecoded,
verworfen: s.framesDropped,
nichtDekodiert: notDecoded
});
}
};
await diagnoseVideo(pc);
// Wichtig · Fallstricke
- Nur Video: Bei Audio-Einträgen vom Typ
inbound-rtpfehlt die Eigenschaft. Filtere deshalb immer nachkind === "video"oder prüfe den Wert aufundefined. - Kumulativer Zähler: Der Wert ist die Summe über die gesamte Lebensdauer des Streams, keine Rate. Für fps brauchst du zwei Messungen und deren
timestamp-Differenz. - Empfangen ist nicht angezeigt:
framesReceivedsagt nichts darüber aus, ob ein Frame dekodiert oder gerendert wurde. Dafür gibt esframesDecoded,framesDroppedundframesRendered(nicht in allen Browsern verfügbar). - Neuer Stream, neuer Zähler: Ändert sich die SSRC, etwa nach einer Neuverhandlung, entsteht ein neuer
inbound-rtp-Eintrag und der Zähler beginnt wieder bei 0. Ordne Messungen deshalb überidoderssrczu. - Kompatibilität: Von Chromium-Browsern, Firefox und Safari unterstützt. Welche weiteren Statistik-Felder verfügbar sind, unterscheidet sich zwischen den Browsern. Prüfe sie daher vor der Nutzung.