Start · Sprachen · JavaScript · Referenz · RTCInboundRtpStreamStats.jitterBufferDelay

RTCInboundRtpStreamStats.jitterBufferDelay

Eigenschaft

Gesamtzeit in Sekunden, die alle ausgegebenen Audio-Samples bzw. vollständigen Video-Frames eines eingehenden RTP-Streams im Jitter-Puffer verbracht haben.

seit JavaScript WebRTC Statistics (W3C); Chrome/Edge, Firefox und Kategorie: webapi

Signatur

RTCInboundRtpStreamStats.jitterBufferDelay

Beschreibung

Die Eigenschaft jitterBufferDelay eines RTCInboundRtpStreamStats-Objekts (Typ "inbound-rtp") ist ein fortlaufend steigender Zähler vom Typ number in Sekunden. Für jedes Audio-Sample bzw. jeden vollständigen Video-Frame, der den Jitter-Puffer verlässt, wird die Zeit zwischen dem Eintreffen des ersten zugehörigen RTP-Pakets und der Ausgabe aus dem Puffer (Weitergabe an Decoder bzw. Wiedergabe) aufaddiert.

Der Jitter-Puffer gleicht schwankende Paketlaufzeiten im Netz aus, indem er Daten kurz zurückhält. Das sorgt für flüssige Wiedergabe, kostet aber Latenz. Mit jitterBufferDelay lässt sich messen, wie viel zusätzliche Verzögerung dadurch auf der Empfängerseite entsteht – nützlich für Qualitäts-Dashboards, Latenzanalysen und das Erkennen instabiler Netzverbindungen.

Da der Wert kumuliert ist, sagt er allein wenig aus. Die durchschnittliche Pufferverzögerung erhält man, indem man ihn durch jitterBufferEmittedCount teilt. Für die Verzögerung in einem bestimmten Zeitraum bildet man die Differenzen beider Zähler zwischen zwei getStats()-Abfragen.

Rückgabewert

Typ
number
Beschreibung
Kumulierte Verweildauer aller ausgegebenen Samples/Frames im Jitter-Puffer in Sekunden (Gleitkommazahl). Kann undefined sein, wenn der Browser den Wert nicht liefert.

Beispiele

Durchschnittliche Jitter-Puffer-Verzögerung auslesen

// pc ist eine verbundene RTCPeerConnection
const logJitterBuffer = async (pc) => {
  const stats = await pc.getStats();
  stats.forEach((report) => {
    if (report.type !== 'inbound-rtp') return;
    const { kind, jitterBufferDelay, jitterBufferEmittedCount } = report;
    if (!jitterBufferEmittedCount) return;
    const avgMs = (jitterBufferDelay / jitterBufferEmittedCount) * 1000;
    console.log(`${kind}: Ø ${avgMs.toFixed(1)} ms im Jitter-Puffer`);
  });
};

await logJitterBuffer(pc);
audio: Ø 42.3 ms im Jitter-Puffer video: Ø 58.7 ms im Jitter-Puffer

Aktuelle Verzögerung per Intervall-Differenz messen

// Mittelwert nur über die letzten 2 Sekunden statt seit Verbindungsbeginn
const previous = new Map();

const sampleJitter = async (pc) => {
  const stats = await pc.getStats();
  for (const report of stats.values()) {
    if (report.type !== 'inbound-rtp') continue;
    const prev = previous.get(report.id);
    if (prev) {
      const deltaDelay = report.jitterBufferDelay - prev.jitterBufferDelay;
      const deltaCount = report.jitterBufferEmittedCount - prev.jitterBufferEmittedCount;
      if (deltaCount > 0) {
        const ms = (deltaDelay / deltaCount) * 1000;
        console.log(`${report.kind} (aktuell): ${ms.toFixed(1)} ms`);
      }
    }
    previous.set(report.id, {
      jitterBufferDelay: report.jitterBufferDelay,
      jitterBufferEmittedCount: report.jitterBufferEmittedCount,
    });
  }
};

const timer = setInterval(() => sampleJitter(pc), 2000);
// Später: clearInterval(timer);
audio (aktuell): 38.9 ms video (aktuell): 71.2 ms

Warnung bei hoher Puffer-Latenz für einen Empfänger

const checkReceiver = async (receiver, limitMs = 150) => {
  const stats = await receiver.getStats();
  const inbound = [...stats.values()].find((r) => r.type === 'inbound-rtp');
  if (!inbound?.jitterBufferEmittedCount) return;

  const avgMs = (inbound.jitterBufferDelay / inbound.jitterBufferEmittedCount) * 1000;
  if (avgMs > limitMs) {
    console.warn(`Hohe Puffer-Latenz (${Math.round(avgMs)} ms) – Netz instabil?`);
  }
};

const [audioReceiver] = pc.getReceivers().filter((r) => r.track.kind === 'audio');
await checkReceiver(audioReceiver);
Hohe Puffer-Latenz (184 ms) – Netz instabil?

// Wichtig · Fallstricke

  • Einheit Sekunden: Der Wert ist in Sekunden angegeben, nicht in Millisekunden – für Anzeigen mit 1000 multiplizieren.
  • Kumulativer Zähler: Der Wert wächst über die gesamte Lebensdauer des Streams. Ohne Division durch jitterBufferEmittedCount (oder Differenzbildung zwischen Abfragen) ist er nicht als Latenz interpretierbar.
  • Division durch null vermeiden: Direkt nach dem Verbindungsaufbau ist jitterBufferEmittedCount oft 0.
  • Audio vs. Video: Bei Audio wird pro Sample gezählt (nicht pro Paket), bei Video pro vollständigem Frame. Werte beider Medienarten sind daher nicht direkt vergleichbar.
  • Nicht die Gesamtlatenz: Netzlaufzeit (siehe roundTripTime im remote-inbound-rtp-Bericht), Dekodierung und Rendering sind nicht enthalten.
  • Kompatibilität: Von Chromium-Browsern, Firefox und Safari unterstützt; ältere Versionen liefern den Wert teils nur für Audio oder gar nicht. Immer auf undefined prüfen. Bei RTCPeerConnection.getStats() gibt es den Bericht nur, wenn tatsächlich Daten empfangen werden.