Signatur
Beschreibung
getStats() fragt die Statistiken ab, die zu genau einem RTCRtpReceiver einer RTCPeerConnection gehören. Das zurückgegebene Promise wird mit einem RTCStatsReport erfüllt. Das ist eine Map-ähnliche Struktur, deren Einträge Objekte mit den Feldern id, type und timestamp sowie typspezifischen Kennzahlen enthalten.
Im Unterschied zu RTCPeerConnection.getStats() ist der Bericht auf den Empfänger gefiltert. Er enthält vor allem Einträge vom Typ inbound-rtp (empfangene Pakete und Bytes, packetsLost, jitter, framesDecoded, framesPerSecond usw.). Dazu kommen die referenzierten Objekte wie codec, remote-outbound-rtp, transport und candidate-pair.
Typische Einsatzzwecke sind Qualitätsanzeigen in Videokonferenzen, die Erkennung von Paketverlust oder Einbrüchen der Bitrate, adaptive Anpassungen der Benutzeroberfläche und das Sammeln von Telemetriedaten. Da die meisten Zähler kumulativ sind, berechnet man Raten wie die Bitrate aus der Differenz zweier Abfragen und deren timestamp-Werten.
Rückgabewert
RTCStatsReport erfüllt wird. Dieser enthält die Statistik-Objekte des Empfängers und die von ihnen referenzierten Objekte. Er lässt sich mit forEach(), for...of, get(id) oder values() auswerten.Beispiele
Inbound-RTP-Statistiken eines Empfängers ausgeben
const pc = new RTCPeerConnection();
pc.addEventListener('track', async ({ receiver, track }) => {
// Etwas warten, bis Pakete eingetroffen sind
await new Promise((r) => setTimeout(r, 3000));
const report = await receiver.getStats();
for (const stat of report.values()) {
if (stat.type === 'inbound-rtp') {
console.log(`${track.kind}: ${stat.packetsReceived} Pakete, ${stat.packetsLost} verloren, Jitter ${stat.jitter}s`);
}
}
});
Eingehende Bitrate periodisch berechnen
const monitorBitrate = (receiver, intervalMs = 1000) => {
let last = null;
return setInterval(async () => {
const report = await receiver.getStats();
const inbound = [...report.values()].find((s) => s.type === 'inbound-rtp');
if (!inbound) return;
if (last) {
const bytes = inbound.bytesReceived - last.bytesReceived;
const seconds = (inbound.timestamp - last.timestamp) / 1000;
const kbps = ((bytes * 8) / seconds / 1000).toFixed(1);
console.log(`Bitrate: ${kbps} kbit/s`);
}
last = inbound;
}, intervalMs);
};
// Nutzung: const timer = monitorBitrate(pc.getReceivers()[0]);
// Beenden: clearInterval(timer);
Codec und Videoauflösung ermitteln
const describeVideo = async (receiver) => {
const report = await receiver.getStats();
const inbound = [...report.values()].find(
(s) => s.type === 'inbound-rtp' && s.kind === 'video'
);
if (!inbound) return null;
// codecId verweist auf einen anderen Eintrag im selben Bericht
const codec = inbound.codecId ? report.get(inbound.codecId) : undefined;
return {
codec: codec?.mimeType ?? 'unbekannt',
aufloesung: `${inbound.frameWidth}x${inbound.frameHeight}`,
fps: inbound.framesPerSecond,
};
};
const videoReceiver = pc.getReceivers().find((r) => r.track.kind === 'video');
console.log(await describeVideo(videoReceiver));
// Wichtig · Fallstricke
- Kumulative Zähler: Werte wie
bytesReceivedoderpacketsLostsummieren sich seit Beginn des Streams auf. Für Raten musst du zwei Abfragen vergleichen und die Differenz dertimestamp-Werte verwenden (Angabe in Millisekunden). - Feldverfügbarkeit: Welche Felder vorhanden sind, unterscheidet sich zwischen den Browsern. Beispielsweise meldet Firefox nicht alle Video-Kennzahlen, und ältere Chrome-Versionen hatten eine nicht standardkonforme Legacy-Form von
getStats()mit Callback. Prüfe Felder deshalb immer aufundefined. - Leerer Bericht: Solange noch keine RTP-Pakete eingetroffen sind, zum Beispiel direkt nach dem
track-Ereignis, fehlt oft der Eintraginbound-rtp. - Performance: Ein Abfrageintervall von etwa 1 Sekunde reicht meist aus. Häufigere Abfragen verursachen unnötige CPU-Last.
- Datenschutz: Die Berichte können über referenzierte
candidate-pair- oderlocal-candidate-Einträge IP-Adressen enthalten. Filtere diese heraus, bevor du Telemetriedaten an einen Server sendest. - Nachdem die Verbindung mit
pc.close()geschlossen wurde, liefert der Aufruf nur noch eingeschränkte oder keine Daten mehr.