Signatur
Beschreibung
Die Eigenschaft bytesSent gehört zum Wörterbuch RTCIceCandidatePairStats. Solche Statistikobjekte liefert RTCPeerConnection.getStats() in einem RTCStatsReport. Man erkennt sie am Eintrag type === "candidate-pair". Der Wert ist ein fortlaufender Zähler. Er gibt an, wie viele Bytes Nutzdaten seit Beginn über dieses Kandidatenpaar (lokaler + entfernter Kandidat) gesendet wurden.
Gezählt werden nur Nutzdaten. Header wie IP, UDP oder TCP und Padding zählen nicht mit, ebenso wenig Pakete zur ICE-Konnektivitätsprüfung (STUN). RTP-, RTCP- und SCTP-Daten (Datenkanäle), die über das Paar laufen, fließen in den Wert ein.
Typische Einsatzzwecke: aktuelle Sende-Bitrate berechnen, Verbindungsqualität überwachen, Verbrauch protokollieren oder ein Diagnose-Dashboard bauen. Die Rate bekommt man, indem man zwei Messungen vergleicht: Differenz von bytesSent geteilt durch die Differenz von timestamp.
Meist interessiert nur das aktive Paar. Man findet es über RTCTransportStats.selectedCandidatePairId oder über nominated zusammen mit state === "succeeded".
Rückgabewert
unsigned long long): die bisher über dieses Kandidatenpaar gesendeten Nutzdatenbytes. Kann undefined sein, wenn der Browser den Wert nicht liefert.Beispiele
Gesendete Bytes des aktiven Kandidatenpaars auslesen
const getSelectedPair = async (pc) => {
const stats = await pc.getStats();
let pair;
stats.forEach((report) => {
if (report.type === 'transport' && report.selectedCandidatePairId) {
pair = stats.get(report.selectedCandidatePairId);
}
});
// Fallback, z. B. für Firefox: nominiertes, erfolgreiches Paar
if (!pair) {
stats.forEach((report) => {
if (report.type === 'candidate-pair' && report.nominated && report.state === 'succeeded') {
pair = report;
}
});
}
return pair;
};
const pair = await getSelectedPair(peerConnection);
console.log(`Gesendet: ${pair?.bytesSent ?? 0} Bytes`);
Sende-Bitrate periodisch berechnen
let last = null;
const timer = setInterval(async () => {
const stats = await peerConnection.getStats();
stats.forEach((r) => {
if (r.type !== 'candidate-pair' || !r.nominated || r.state !== 'succeeded') return;
if (last && last.id === r.id) {
const bytes = r.bytesSent - last.bytesSent;
const ms = r.timestamp - last.timestamp;
const kbps = ((bytes * 8) / ms).toFixed(1); // Bit pro ms = kbit/s
console.log(`Upload: ${kbps} kbit/s`);
}
last = { id: r.id, bytesSent: r.bytesSent, timestamp: r.timestamp };
});
}, 1000);
// Später: clearInterval(timer);
Alle Kandidatenpaare mit Datenvolumen tabellarisch ausgeben
const stats = await peerConnection.getStats();
const rows = [];
stats.forEach((r) => {
if (r.type === 'candidate-pair') {
rows.push({
id: r.id,
state: r.state,
nominated: r.nominated,
bytesSent: r.bytesSent ?? 0,
bytesReceived: r.bytesReceived ?? 0
});
}
});
console.table(rows);
// Wichtig · Fallstricke
- Kumulativer Zähler:
bytesSentist keine Rate. Für die Bitrate braucht man zwei Messungen und rechnet mit der Differenz vontimestamp(Millisekunden). - Nur Nutzdaten: IP-, UDP- und TCP-Header sowie STUN-Prüfpakete werden nicht mitgezählt. Die tatsächliche Netzlast ist daher höher.
- Paarwechsel: Bei ICE-Restart oder Netzwechsel (z. B. WLAN → Mobilfunk) kann ein anderes Paar aktiv werden. Dessen Zähler startet bei 0. Prüfe deshalb vor dem Vergleich, ob die
idgleich geblieben ist. - Browser-Unterschiede:
selectedCandidatePairIdaufRTCTransportStatsfehlte in Firefox lange. Übernominatedundstatekommt man trotzdem ans aktive Paar. Das veraltete Feldselectedgibt es nur in Firefox, es ist nicht standardisiert. - Bei Bündelung (BUNDLE) teilen sich alle Medienspuren einen Transport. Der Wert umfasst dann Audio, Video und Datenkanäle zusammen. Pro Spur liefert
RTCOutboundRtpStreamStats.bytesSentdie Zahlen. - Nicht zu oft abfragen:
getStats()ist asynchron und kostet Rechenzeit. Ein Intervall von etwa 1 s reicht meist.