Start · Sprachen · JavaScript · Referenz · RTCOutboundRtpStreamStats.framesSent

RTCOutboundRtpStreamStats.framesSent

Eigenschaft

Gibt die Gesamtzahl der codierten Video-Frames an, die über die gesamte Lebensdauer dieses ausgehenden RTP-Streams gesendet wurden.

seit JavaScript Baseline 2024: Chrome, Edge, Firefox, Safari (nur Kategorie: webapi

Signatur

RTCOutboundRtpStreamStats.framesSent

Beschreibung

Die Eigenschaft framesSent des Wörterbuchs RTCOutboundRtpStreamStats ist ein fortlaufend steigender Zähler (vorzeichenlose Ganzzahl). Er gibt an, wie viele vollständig codierte Frames über diesen RTP-Stream verschickt wurden. Ein Frame gilt als gesendet, sobald alle zugehörigen RTP-Pakete übertragen wurden.

Die Eigenschaft gibt es nur bei Video-Streams (kind === "video"). Bei Audio-Streams ist sie nicht vorhanden. Den Wert erhält man über RTCPeerConnection.getStats() oder RTCRtpSender.getStats(). Im zurückgegebenen RTCStatsReport sucht man dafür Einträge mit type === "outbound-rtp".

Richtig nützlich wird framesSent, wenn man zwei Messungen vergleicht. Teilt man die Differenz zweier Abfragen durch die vergangene Zeit (timestamp in Millisekunden), erhält man die tatsächlich gesendete Bildrate. Zusammen mit framesEncoded lässt sich erkennen, ob codierte Frames verworfen werden, bevor sie das Netz erreichen. Zusammen mit framesPerSecond oder qualityLimitationReason lassen sich Engpässe bei CPU oder Bandbreite aufspüren.

Rückgabewert

Typ
number
Beschreibung
Vorzeichenlose Ganzzahl (unsigned long): die Gesamtzahl der bisher gesendeten codierten Frames dieses RTP-Streams. Bei Audio-Streams ist der Wert undefined.

Beispiele

Gesendete Frames aller Video-Streams auslesen

// pc ist eine bestehende RTCPeerConnection mit Video-Track
const logFramesSent = async (pc) => {
  const report = await pc.getStats();
  report.forEach((stats) => {
    if (stats.type === 'outbound-rtp' && stats.kind === 'video') {
      console.log(`SSRC ${stats.ssrc}: ${stats.framesSent} Frames gesendet`);
    }
  });
};

await logFramesSent(pc);
SSRC 3735928559: 1842 Frames gesendet

Tatsächliche Sende-Bildrate berechnen

// Bildrate aus der Differenz zweier Messungen berechnen
const sender = pc.getSenders().find((s) => s.track?.kind === 'video');
let previous = null;

const measureFps = async () => {
  const report = await sender.getStats();
  for (const stats of report.values()) {
    if (stats.type !== 'outbound-rtp') continue;
    if (previous) {
      const frames = stats.framesSent - previous.framesSent;
      const seconds = (stats.timestamp - previous.timestamp) / 1000;
      console.log(`Gesendet: ${(frames / seconds).toFixed(1)} fps`);
    }
    previous = stats;
  }
};

const timer = setInterval(measureFps, 1000);
// Später: clearInterval(timer);
Gesendet: 29.8 fps

Verlust zwischen Encoder und Versand erkennen

const checkEncoderGap = async (pc) => {
  const report = await pc.getStats();
  for (const s of report.values()) {
    if (s.type === 'outbound-rtp' && s.kind === 'video') {
      const gap = (s.framesEncoded ?? 0) - (s.framesSent ?? 0);
      console.log({
        rid: s.rid ?? '(kein Simulcast)',
        framesEncoded: s.framesEncoded,
        framesSent: s.framesSent,
        nichtGesendet: gap,
        limitierung: s.qualityLimitationReason
      });
    }
  }
};

await checkEncoderGap(pc);
{ rid: '(kein Simulcast)', framesEncoded: 1850, framesSent: 1842, nichtGesendet: 8, limitierung: 'bandwidth' }

// Wichtig · Fallstricke

  • Nur Video: Bei Audio-Streams gibt es framesSent nicht. Prüfen Sie daher immer kind === "video" oder fangen Sie undefined ab, zum Beispiel mit ?? 0.
  • Zähler, keine Rate: Der Wert steigt nur an. Für eine Bildrate braucht man zwei Messungen und muss die Differenz durch die Differenz der timestamp-Werte teilen. Die Abfrage-Abstände selbst sind nicht exakt.
  • Simulcast: Bei Simulcast oder SVC gibt es pro Ebene einen eigenen outbound-rtp-Eintrag mit eigenem Zähler. Diese Einträge unterscheiden sich über rid bzw. ssrc. Wer die Summe braucht, muss selbst addieren.
  • Keine Angabe über den Empfang: Gesendet heißt nicht empfangen. Verluste im Netz sieht man erst in den Statistiken der Gegenseite (remote-inbound-rtp, framesReceived und framesDecoded beim Empfänger).
  • Kompatibilität: Ältere Browser, vor allem Safari vor Version 15 und alte Firefox-Versionen, lieferten den Wert nicht oder nur im veralteten Eintrag vom Typ track. Robuster Code sollte deshalb prüfen, ob die Eigenschaft vorhanden ist.