Start · Sprachen · JavaScript · Referenz · RTCOutboundRtpStreamStats.bytesSent

RTCOutboundRtpStreamStats.bytesSent

Eigenschaft

Gibt die Gesamtzahl der Nutzlast-Bytes an, die über diesen ausgehenden RTP-Stream (eine SSRC) bisher gesendet wurden. Header und Padding zählen nicht mit.

seit JavaScript Baseline: Chrome 80+, Firefox 69+, Safari 11+ (in Kategorie: webapi

Signatur

RTCOutboundRtpStreamStats.bytesSent

Beschreibung

Die schreibgeschützte Eigenschaft bytesSent ist Teil der Statistikobjekte vom Typ "outbound-rtp". Diese Objekte liefert RTCPeerConnection.getStats() bzw. RTCRtpSender.getStats(). Der Wert ist ein Zähler, der nur wächst: Er gibt an, wie viele Bytes an RTP-Nutzlast für die zugehörige SSRC seit Beginn der Übertragung gesendet wurden. Gezählt wird wie beim „sender's octet count“ aus RFC 3550, Abschnitt 6.4.1. RTP-Header und Padding sind also nicht enthalten. Erneut übertragene Pakete (Retransmissions) zählt die Spezifikation dagegen mit.

Anders als die MDN-Kurzbeschreibung vermuten lässt, geht es hier nicht um einen RTCDataChannel. Die Eigenschaft bezieht sich auf einen ausgehenden Audio- oder Videostream (RTP). Für Datenkanäle gibt es die Statistikobjekte vom Typ "data-channel", die ebenfalls eine eigene Eigenschaft bytesSent haben.

Praktisch nutzt man bytesSent vor allem, um die tatsächliche Sende-Bitrate zu berechnen. Dazu fragt man die Statistik in regelmäßigen Abständen ab, bildet die Differenz zweier Messwerte und teilt sie durch die Differenz der timestamp-Werte. So lassen sich Bandbreitenanpassung, Simulcast-Schichten oder Netzwerkprobleme überwachen und in Dashboards darstellen.

Rückgabewert

Typ
number
Beschreibung
Nicht-negative ganze Zahl (unsigned long long): die Summe aller bisher für diese SSRC gesendeten Nutzlast-Bytes.

Beispiele

Gesendete Bytes aller ausgehenden Streams ausgeben

const logBytesSent = async (pc) => {
  const report = await pc.getStats();
  report.forEach((stats) => {
    if (stats.type === 'outbound-rtp') {
      console.log(`${stats.kind} (SSRC ${stats.ssrc}): ${stats.bytesSent} Bytes gesendet`);
    }
  });
};

// pc ist eine verbundene RTCPeerConnection
await logBytesSent(pc);
audio (SSRC 1234567890): 482113 Bytes gesendet video (SSRC 987654321): 12893440 Bytes gesendet

Sende-Bitrate pro Sekunde berechnen

const monitorBitrate = (sender, intervalMs = 1000) => {
  let last = null;

  return setInterval(async () => {
    const report = await sender.getStats();
    for (const stats of report.values()) {
      if (stats.type !== 'outbound-rtp') continue;

      if (last) {
        const bytes = stats.bytesSent - last.bytesSent;
        const seconds = (stats.timestamp - last.timestamp) / 1000;
        const kbps = ((bytes * 8) / seconds / 1000).toFixed(1);
        console.log(`Aktuelle Bitrate: ${kbps} kbit/s`);
      }
      last = { bytesSent: stats.bytesSent, timestamp: stats.timestamp };
    }
  }, intervalMs);
};

const [videoSender] = pc.getSenders().filter((s) => s.track?.kind === 'video');
const timer = monitorBitrate(videoSender);
// später: clearInterval(timer);
Aktuelle Bitrate: 1487.3 kbit/s Aktuelle Bitrate: 1502.9 kbit/s

Nutzlast, Header und Retransmissions vergleichen

const report = await pc.getStats();
for (const s of report.values()) {
  if (s.type === 'outbound-rtp' && s.kind === 'video') {
    const total = s.bytesSent + (s.headerBytesSent ?? 0);
    console.log({
      rid: s.rid ?? '(kein Simulcast)',
      nutzlast: s.bytesSent,
      header: s.headerBytesSent,
      retransmittiert: s.retransmittedBytesSent,
      gesamt: total
    });
  }
}
{ rid: 'h', nutzlast: 9120034, header: 312480, retransmittiert: 20480, gesamt: 9432514 }

// Wichtig · Fallstricke

  • Nur Nutzlast: RTP-Header und Padding sind in bytesSent nicht enthalten. Die Header-Bytes stehen in headerBytesSent. Wer den tatsächlichen Verbrauch auf der Leitung abschätzen will, muss beide Werte addieren. Auch dann fehlen noch der Overhead von UDP, IP und SRTP.
  • Retransmissions: Laut Spezifikation sind erneut gesendete Bytes enthalten. Die Umsetzung kann je nach Browser abweichen, besonders wenn RTX über eine eigene SSRC läuft. Zur Kontrolle eignet sich retransmittedBytesSent.
  • Kein Datenkanal: Für RTCDataChannel gibt es Statistiken vom Typ "data-channel", nicht "outbound-rtp".
  • Simulcast: Bei Simulcast gibt es ein eigenes outbound-rtp-Objekt pro Schicht (unterscheidbar über rid). Die Gesamt-Bitrate ist die Summe aller Schichten.
  • Zähler statt Rate: Der Wert ist kumulativ. Eine Bitrate ergibt sich nur aus der Differenz zweier Messungen, geteilt durch die Differenz der timestamp-Werte. Den Zeitstempel aus dem Statistikobjekt verwenden, nicht Date.now().
  • Kompatibilität: Wird von allen modernen Browsern unterstützt. Ältere Browser (vor allem ältere Safari-Versionen) lieferten zum Teil abweichende Statistiktypen. Vor dem Zugriff also den type prüfen.