Signatur
Beschreibung
Die schreibgeschützte Eigenschaft nackCount gehört zum Wörterbuch RTCInboundRtpStreamStats. Sie ist eine positive ganze Zahl und zählt, wie oft der lokale Empfänger ein NACK-Paket (RTCP Generic NACK, RFC 4585) an den entfernten Sender geschickt hat. Damit fordert er verloren gegangene RTP-Pakete erneut an.
Der Wert steigt nur an und wird nie zurückgesetzt. Ein NACK-Paket kann den Verlust mehrerer RTP-Pakete auf einmal melden. nackCount sagt also nichts darüber aus, wie viele Pakete fehlten, sondern nur, wie viele Anfragen verschickt wurden. Die Zahl der tatsächlich verlorenen Pakete steht in packetsLost.
In der Praxis nutzt man nackCount, um die Qualität einer Verbindung zu überwachen. Steigt der Wert schnell, deutet das auf Paketverluste im Netz hin. Oft folgen dann Bildfehler, Einfrieren oder zusätzliche Anfragen nach Keyframes (pliCount, firCount). Den Wert bekommt man über RTCPeerConnection.getStats() oder RTCRtpReceiver.getStats(). Dort sucht man die Einträge mit type === "inbound-rtp".
Rückgabewert
undefined, wenn der Browser den Wert nicht meldet.Beispiele
nackCount aller eingehenden Streams auslesen
// pc ist eine bestehende, verbundene RTCPeerConnection
const logNackCounts = async (pc) => {
const report = await pc.getStats();
report.forEach((stats) => {
if (stats.type === 'inbound-rtp') {
console.log(`${stats.kind} (SSRC ${stats.ssrc}): ${stats.nackCount ?? 'n/a'} NACKs`);
}
});
};
await logNackCounts(pc);
NACK-Rate pro Sekunde für einen Video-Receiver überwachen
const monitorNackRate = (receiver, intervalMs = 2000) => {
let lastCount = null;
let lastTs = null;
return setInterval(async () => {
const report = await receiver.getStats();
for (const stats of report.values()) {
if (stats.type !== 'inbound-rtp' || stats.nackCount === undefined) continue;
if (lastCount !== null) {
const seconds = (stats.timestamp - lastTs) / 1000;
const rate = (stats.nackCount - lastCount) / seconds;
console.log(`NACK-Rate: ${rate.toFixed(2)}/s`);
if (rate > 5) console.warn('Hoher Paketverlust – Netzqualität prüfen!');
}
lastCount = stats.nackCount;
lastTs = stats.timestamp;
}
}, intervalMs);
};
const videoReceiver = pc.getReceivers().find((r) => r.track?.kind === 'video');
const timerId = monitorNackRate(videoReceiver);
// später: clearInterval(timerId);
NACKs mit verlorenen Paketen vergleichen
const summarizeLoss = async (pc) => {
const report = await pc.getStats();
const summary = [];
for (const s of report.values()) {
if (s.type === 'inbound-rtp' && s.kind === 'video') {
summary.push({
ssrc: s.ssrc,
packetsReceived: s.packetsReceived,
packetsLost: s.packetsLost,
nackCount: s.nackCount,
pliCount: s.pliCount
});
}
}
console.table(summary);
return summary;
};
await summarizeLoss(pc);
// Wichtig · Fallstricke
- Kumulativer Zähler:
nackCountzählt vom Beginn des Streams an. Für eine aussagekräftige Rate nimmt man die Differenz zweier Messungen und teilt sie durch die Differenz dertimestamp-Werte. - Nicht gleich Paketverlust: Ein NACK kann mehrere Pakete betreffen, und manche Verluste lösen gar kein NACK aus. Das passiert zum Beispiel, wenn NACK nicht ausgehandelt wurde oder das Paket ohnehin zu spät käme.
nackCountundpacketsLoststimmen daher meist nicht überein. - Abhängig von der Aushandlung: NACKs werden nur verschickt, wenn im SDP
a=rtcp-fb:… nackausgehandelt wurde. Bei Audio ist das meist nicht der Fall, deshalb bleibt der Wert dort oft bei0. - Browser-Unterstützung: Aktuelle Chromium-Browser, Firefox und Safari melden die Eigenschaft. Ältere Versionen führten sie teils nur im veralteten Typ
"track"oder gar nicht. Deshalb vor der Nutzung aufundefinedprüfen. - Die ausgehende Seite meldet den gleichen Wert als
RTCOutboundRtpStreamStats.nackCount, dort gezählt als empfangene NACKs.