Start · Sprachen · JavaScript · Referenz · RTCOutboundRtpStreamStats.nackCount

RTCOutboundRtpStreamStats.nackCount

Eigenschaft

Ganzzahl, die angibt, wie oft der zugehörige <code>RTCRtpSender</code> ein NACK-Paket (Negative Acknowledgement) vom entfernten Empfänger erhalten hat.

seit JavaScript Baseline: Chrome, Edge, Firefox, Safari (WebRTC-St Kategorie: webapi

Signatur

RTCOutboundRtpStreamStats.nackCount

Beschreibung

Die Eigenschaft nackCount eines RTCOutboundRtpStreamStats-Objekts zählt, wie viele NACK-Pakete (Negative Acknowledgements, RTCP-Feedback nach RFC 4585) der Sender vom entfernten Empfänger bekommen hat. Mit einem NACK meldet der Empfänger, dass ein oder mehrere RTP-Pakete verloren gegangen sind, und fordert sie erneut an.

Der Wert ist ein kumulativer Zähler ab Beginn des Streams. Er steigt nur, er wird also nicht zurückgesetzt. Aussagekräftig wird er, wenn man die Differenz zwischen zwei Abfragen von RTCPeerConnection.getStats() bildet: Daraus ergibt sich eine NACK-Rate pro Sekunde, ein guter Hinweis auf Paketverlust auf dem Weg zum Empfänger.

Wichtig: Ein NACK-Paket kann mehrere verlorene Sequenznummern enthalten. nackCount zählt die NACK-Pakete, nicht die angeforderten RTP-Pakete. Um zu sehen, wie viel tatsächlich neu gesendet wurde, nimmt man retransmittedPacketsSent und retransmittedBytesSent dazu. Auf der Empfängerseite gibt es das Gegenstück RTCInboundRtpStreamStats.nackCount, also die Zahl der gesendeten NACKs.

Rückgabewert

Typ
number
Beschreibung
Nicht-negative Ganzzahl (unsigned long): Gesamtzahl der vom Sender empfangenen NACK-Pakete. Kann undefined sein, wenn der Browser den Wert nicht liefert oder NACK nicht ausgehandelt wurde.

Beispiele

NACK-Zähler aller ausgehenden Streams auslesen

// pc ist eine verbundene RTCPeerConnection
const logNacks = async (pc) => {
  const stats = await pc.getStats();
  stats.forEach((report) => {
    if (report.type === 'outbound-rtp') {
      console.log(`${report.kind} (SSRC ${report.ssrc}): ${report.nackCount ?? 'k. A.'} NACKs`);
    }
  });
};

await logNacks(pc);
video (SSRC 1234567890): 17 NACKs audio (SSRC 987654321): 0 NACKs

NACK-Rate pro Sekunde überwachen

const monitorNackRate = (pc, intervalMs = 2000) => {
  const previous = new Map();

  return setInterval(async () => {
    const stats = await pc.getStats();
    for (const report of stats.values()) {
      if (report.type !== 'outbound-rtp' || report.nackCount === undefined) continue;

      const prev = previous.get(report.id);
      if (prev) {
        const seconds = (report.timestamp - prev.timestamp) / 1000;
        const rate = (report.nackCount - prev.nackCount) / seconds;
        if (rate > 5) {
          console.warn(`Hoher Paketverlust bei ${report.kind}: ${rate.toFixed(1)} NACK/s`);
        }
      }
      previous.set(report.id, { nackCount: report.nackCount, timestamp: report.timestamp });
    }
  }, intervalMs);
};

const timer = monitorNackRate(pc);
// später: clearInterval(timer);
Hoher Paketverlust bei video: 7.5 NACK/s

NACKs zu Neuübertragungen ins Verhältnis setzen

const sender = pc.getSenders().find((s) => s.track?.kind === 'video');
const stats = await sender.getStats();

for (const report of stats.values()) {
  if (report.type === 'outbound-rtp') {
    const { nackCount = 0, retransmittedPacketsSent = 0, packetsSent = 0 } = report;
    console.log({
      nackCount,
      retransmittedPacketsSent,
      retransmitAnteil: packetsSent ? `${((retransmittedPacketsSent / packetsSent) * 100).toFixed(2)} %` : '0 %'
    });
  }
}
{ nackCount: 42, retransmittedPacketsSent: 88, retransmitAnteil: '0.35 %' }

// Wichtig · Fallstricke

  • Kumulativer Zähler: Der absolute Wert sagt allein wenig. Für Qualitätsmetriken immer Differenzen über die Zeit bilden und dafür timestamp verwenden.
  • Pakete, nicht Verluste: Ein NACK kann mehrere verlorene Pakete melden. nackCount ist daher kein direktes Maß für den Paketverlust. Für den Verlust aus Empfängersicht gibt es RTCRemoteInboundRtpStreamStats.packetsLost bzw. fractionLost.
  • Aushandlung: NACKs gibt es nur, wenn im SDP a=rtcp-fb:… nack ausgehandelt wurde. Bei Video ist das üblich, bei Audio (Opus) meist nicht. Dort bleibt der Wert oft bei 0 oder fehlt ganz.
  • Kompatibilität: Chromium-Browser liefern den Wert zuverlässig. Firefox und Safari unterstützen ihn ebenfalls, aber je nach Version nicht für alle Codecs. Deshalb mit ?? 0 oder einer undefined-Prüfung absichern.
  • Bei Simulcast gibt es pro Schicht (rid) einen eigenen outbound-rtp-Bericht mit einem eigenen nackCount.