Start · Sprachen · JavaScript · Referenz · RTCIceCandidatePairStats.bytesSent

RTCIceCandidatePairStats.bytesSent

Eigenschaft

Gibt die Gesamtzahl der Nutzdatenbytes an, die bisher über die Verbindung des ICE-Kandidatenpaars gesendet wurden.

seit JavaScript Baseline: Chrome, Edge, Firefox, Safari (WebRTC-St Kategorie: webapi

Signatur

RTCIceCandidatePairStats.bytesSent

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

Typ
number
Beschreibung
Ganzzahl (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`);
Gesendet: 184532 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);
Upload: 1245.6 kbit/s

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);
Tabelle mit id, state, nominated, bytesSent, bytesReceived je Kandidatenpaar

// Wichtig · Fallstricke

  • Kumulativer Zähler: bytesSent ist keine Rate. Für die Bitrate braucht man zwei Messungen und rechnet mit der Differenz von timestamp (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 id gleich geblieben ist.
  • Browser-Unterschiede: selectedCandidatePairId auf RTCTransportStats fehlte in Firefox lange. Über nominated und state kommt man trotzdem ans aktive Paar. Das veraltete Feld selected gibt 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.bytesSent die Zahlen.
  • Nicht zu oft abfragen: getStats() ist asynchron und kostet Rechenzeit. Ein Intervall von etwa 1 s reicht meist.