Start · Sprachen · JavaScript · Referenz · RTCStatsReport.values()

RTCStatsReport.values()

Methode

Gibt einen neuen Iterator zurück, der alle Statistik-Objekte eines <code>RTCStatsReport</code> in Einfügereihenfolge liefert.

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

Signatur

RTCStatsReport.prototype.values()

Beschreibung

RTCStatsReport ist ein schreibgeschütztes, Map-ähnliches Objekt. Die Schlüssel sind Statistik-IDs (Strings), die Werte sind Statistik-Wörterbücher wie RTCInboundRtpStreamStats, RTCOutboundRtpStreamStats, RTCIceCandidatePairStats oder RTCTransportStats. Die Methode values() liefert einen Iterator, der diese Statistik-Objekte einzeln in Einfügereihenfolge zurückgibt.

Das ist praktisch, wenn die IDs egal sind und man nur alle Statistiken durchlaufen will, etwa um nach dem Feld type zu filtern ("inbound-rtp", "candidate-pair" usw.) und daraus Bitrate, Paketverlust, Jitter oder Round-Trip-Zeit zu berechnen.

Einen Bericht bekommt man asynchron über RTCPeerConnection.getStats(), RTCRtpSender.getStats() oder RTCRtpReceiver.getStats(). Der Iterator selbst ist ebenfalls iterierbar. Er funktioniert also mit for...of, mit dem Spread-Operator und mit Array.from().

Rückgabewert

Typ
Iterator<object>
Beschreibung
Ein neuer Iterator, der jedes Statistik-Objekt des Berichts in Einfügereihenfolge liefert. Jedes Objekt hat mindestens die Felder id, type und timestamp.

Beispiele

Alle Statistik-Typen eines Berichts auflisten

const pc = new RTCPeerConnection();
pc.createDataChannel('chat');
await pc.setLocalDescription(await pc.createOffer());

const report = await pc.getStats();
for (const stats of report.values()) {
  console.log(`${stats.type} (${stats.id})`);
}
peer-connection (P) data-channel (D1) ... (hängt vom Verbindungszustand und vom Browser ab)

Paketverlust und Jitter eingehender Streams auswerten

const logInboundQuality = async (pc) => {
  const report = await pc.getStats();
  const inbound = [...report.values()].filter((s) => s.type === 'inbound-rtp');

  for (const s of inbound) {
    const total = s.packetsReceived + s.packetsLost;
    const lossPct = total > 0 ? (s.packetsLost / total) * 100 : 0;
    console.log(`${s.kind}: Verlust ${lossPct.toFixed(2)} %, Jitter ${(s.jitter * 1000).toFixed(1)} ms`);
  }
};

// alle 2 Sekunden ausführen
setInterval(() => logInboundQuality(pc), 2000);
audio: Verlust 0.12 %, Jitter 3.4 ms video: Verlust 0.85 %, Jitter 12.0 ms

Round-Trip-Zeit des aktiven Kandidatenpaars ermitteln

const getRtt = async (pc) => {
  const report = await pc.getStats();
  const pair = Array.from(report.values()).find(
    (s) => s.type === 'candidate-pair' && s.nominated && s.state === 'succeeded'
  );
  return pair?.currentRoundTripTime ?? null; // in Sekunden
};

const rtt = await getRtt(pc);
console.log(rtt !== null ? `RTT: ${(rtt * 1000).toFixed(0)} ms` : 'Keine aktive Verbindung');
RTT: 42 ms

Ausgehende Bitrate aus zwei Messungen berechnen

const bytesSent = async (sender) => {
  const report = await sender.getStats();
  let sum = 0;
  for (const s of report.values()) {
    if (s.type === 'outbound-rtp') sum += s.bytesSent;
  }
  return sum;
};

const [sender] = pc.getSenders();
const before = await bytesSent(sender);
await new Promise((r) => setTimeout(r, 1000));
const after = await bytesSent(sender);
console.log(`Bitrate: ${((after - before) * 8 / 1000).toFixed(0)} kbit/s`);
Bitrate: 1450 kbit/s

// Wichtig · Fallstricke

  • Einmal-Iterator: Ein Iterator ist nach einem vollständigen Durchlauf verbraucht. Für einen weiteren Durchlauf report.values() erneut aufrufen oder das Ergebnis vorher mit [...report.values()] in ein Array kopieren.
  • Momentaufnahme: Ein RTCStatsReport wird nicht automatisch aktualisiert. Für frische Werte muss getStats() erneut aufgerufen werden. Raten wie die Bitrate ergeben sich erst aus der Differenz zweier Berichte, geteilt durch die Differenz ihrer timestamp-Werte.
  • Browser-Unterschiede: Welche Statistik-Typen und Felder vorhanden sind, unterscheidet sich zwischen Chrome, Firefox und Safari. Einige Felder wie trackIdentifier oder die veralteten track-/stream-Statistiken fehlen je nach Browser. Felder deshalb immer defensiv abfragen, z. B. mit ?. und ??.
  • Kein Array: Der Iterator hat keine Methoden wie filter oder map. Man wandelt ihn vorher mit Array.from() oder Spread um. In neueren Engines gibt es dafür auch Iterator-Hilfsmethoden wie report.values().filter(...), die aber noch nicht überall verfügbar sind.
  • Datenschutz: ICE-Kandidaten-Statistiken können IP-Adressen enthalten. Beim Senden an Analyse-Server auf Datenschutz achten.