Start · Sprachen · JavaScript · Referenz · RTCRtpReceiver.getStats()

RTCRtpReceiver.getStats()

Methode

Liefert asynchron einen <code>RTCStatsReport</code> mit Statistiken über den eingehenden Medienstrom dieses <code>RTCRtpReceiver</code>.

seit JavaScript Baseline: alle modernen Browser (Chrome 67+, Firef Kategorie: webapi

Signatur

RTCRtpReceiver.prototype.getStats()

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

Typ
Promise<RTCStatsReport>
Beschreibung
Ein Promise, das mit einem 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`);
    }
  }
});
video: 812 Pakete, 3 verloren, Jitter 0.004s

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);
Bitrate: 1240.6 kbit/s

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));
{ codec: 'video/VP8', aufloesung: '1280x720', fps: 30 }

// Wichtig · Fallstricke

  • Kumulative Zähler: Werte wie bytesReceived oder packetsLost summieren sich seit Beginn des Streams auf. Für Raten musst du zwei Abfragen vergleichen und die Differenz der timestamp-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 auf undefined.
  • Leerer Bericht: Solange noch keine RTP-Pakete eingetroffen sind, zum Beispiel direkt nach dem track-Ereignis, fehlt oft der Eintrag inbound-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- oder local-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.