Signatur
Beschreibung
Die schreibgeschützte Eigenschaft jitterBufferEmittedCount gehört zum Wörterbuch RTCInboundRtpStreamStats, also zu den Statistiken vom Typ "inbound-rtp", die RTCPeerConnection.getStats() liefert. Sie zählt, wie viele Audio-Samples (bei Audio-Streams) oder Videoframes (bei Video-Streams) den Jitter-Puffer seit Beginn des Streams verlassen haben und an die Wiedergabe bzw. den Decoder weitergegeben wurden.
Allein ist der Zähler wenig aussagekräftig. Seinen eigentlichen Nutzen hat er als Nenner für die kumulativen Verzögerungswerte jitterBufferDelay, jitterBufferTargetDelay und jitterBufferMinimumDelay, die jeweils in Sekunden aufsummiert werden. Teilt man jitterBufferDelay durch jitterBufferEmittedCount, erhält man die durchschnittliche Verweildauer eines Samples oder Frames im Puffer. Das ist ein wichtiger Wert für die Latenz, die Nutzer wahrnehmen.
Da beide Werte seit Beginn des Streams aufsummiert werden, bildet der Gesamtdurchschnitt kurzfristige Schwankungen kaum ab. Für ein Live-Monitoring sollte man deshalb zwei Messungen in einem Intervall vergleichen und die Differenzen beider Werte durcheinander teilen. So erhält man die durchschnittliche Pufferverzögerung genau für dieses Zeitfenster.
Rückgabewert
unsigned long long), die nur größer wird: die Gesamtzahl der Samples bzw. Frames, die den Jitter-Puffer verlassen haben. Kann undefined sein, wenn der Browser die Eigenschaft nicht unterstützt.Beispiele
Durchschnittliche Jitter-Puffer-Verzögerung berechnen
// pc ist eine verbundene RTCPeerConnection
const logJitterBufferDelay = async (pc) => {
const report = await pc.getStats();
report.forEach((stats) => {
if (stats.type !== 'inbound-rtp') return;
const { kind, jitterBufferDelay, jitterBufferEmittedCount } = stats;
if (!jitterBufferEmittedCount) return; // noch nichts ausgegeben oder nicht unterstützt
const avgMs = (jitterBufferDelay / jitterBufferEmittedCount) * 1000;
console.log(`${kind}: ${jitterBufferEmittedCount} ausgegeben, Ø ${avgMs.toFixed(1)} ms im Puffer`);
});
};
await logJitterBufferDelay(pc);
Live-Monitoring über Intervall-Differenzen
const previous = new Map();
const sampleJitterBuffer = async (pc) => {
const report = await pc.getStats();
for (const stats of report.values()) {
if (stats.type !== 'inbound-rtp' || stats.jitterBufferEmittedCount === undefined) continue;
const prev = previous.get(stats.id);
if (prev) {
const deltaCount = stats.jitterBufferEmittedCount - prev.count;
const deltaDelay = stats.jitterBufferDelay - prev.delay;
if (deltaCount > 0) {
const ms = (deltaDelay / deltaCount) * 1000;
console.log(`${stats.kind} (letzte Sekunde): Ø ${ms.toFixed(1)} ms`);
}
}
previous.set(stats.id, {
count: stats.jitterBufferEmittedCount,
delay: stats.jitterBufferDelay,
});
}
};
const timer = setInterval(() => sampleJitterBuffer(pc), 1000);
// Später: clearInterval(timer);
Ziel- und tatsächliche Verzögerung vergleichen
const compareTargetDelay = async (receiver) => {
// Statistiken nur für einen bestimmten RTCRtpReceiver abfragen
const report = await receiver.getStats();
const inbound = [...report.values()].find((s) => s.type === 'inbound-rtp');
if (!inbound?.jitterBufferEmittedCount) return null;
const n = inbound.jitterBufferEmittedCount;
return {
actualMs: Math.round((inbound.jitterBufferDelay / n) * 1000),
targetMs: Math.round(((inbound.jitterBufferTargetDelay ?? 0) / n) * 1000),
};
};
const [audioReceiver] = pc.getReceivers().filter((r) => r.track.kind === 'audio');
console.log(await compareTargetDelay(audioReceiver));
// Wichtig · Fallstricke
- Einheiten unterscheiden: Bei Audio werden einzelne Samples gezählt, nicht Pakete oder Frames. Bei 48 kHz steigt der Wert deshalb um etwa 48.000 pro Sekunde. Bei Video steigt er pro Frame. Audio- und Video-Werte darf man daher nicht direkt miteinander vergleichen.
- Nicht durch 0 teilen: Direkt nach dem Verbindungsaufbau kann der Wert
0sein. Vor jeder Division darauf prüfen. - Kumulativer Zähler: Der Durchschnitt über die gesamte Laufzeit verdeckt kurzfristige Latenzspitzen. Für Dashboards besser mit Differenzen zwischen zwei Messungen arbeiten.
- Die Werte
jitterBufferDelay,jitterBufferTargetDelayundjitterBufferMinimumDelaywerden auf dieselben Samples bzw. Frames bezogen und immer gemeinsam mit diesem Zähler ausgewertet. - Kompatibilität: Chromium-basierte Browser unterstützen die Eigenschaft schon länger. In Firefox und Safari ist sie neuer, und die dortige Unterstützung habe ich nicht im Einzelnen überprüft. Vor dem Einsatz Kompatibilitätstabellen wie MDN oder caniuse prüfen und im Code auf
undefinedtesten. Die Eigenschaft wird nur für Einträge mittype === "inbound-rtp"geliefert.