Start · Sprachen · JavaScript · Referenz · RTCInboundRtpStreamStats.freezeCount

RTCInboundRtpStreamStats.freezeCount

Eigenschaft

Nur lesbarer Zähler, der angibt, wie oft das empfangene Video bisher eingefroren ist („Freeze“). Existiert nur bei eingehenden Video-Streams.

seit JavaScript WebRTC Statistics (W3C); Chromium-Browser, nicht i Kategorie: webapi

Signatur

RTCInboundRtpStreamStats.freezeCount

Beschreibung

Die Eigenschaft freezeCount des Dictionaries RTCInboundRtpStreamStats ist eine ganze Zahl, die angibt, wie oft der Empfänger bisher ein Einfrieren des Videos erlebt hat. Sie steht nur in Statistik-Objekten mit type === "inbound-rtp" und kind === "video" zur Verfügung. Bei Audio-Streams fehlt sie.

Laut Spezifikation gilt ein Frame als Freeze, wenn die Zeit zwischen zwei nacheinander gerenderten Frames mindestens Max(3 * avg_frame_duration_ms, avg_frame_duration_ms + 150) beträgt. Dabei ist avg_frame_duration_ms der Durchschnitt der Dauern der letzten 30 gerenderten Frames. Kurze Ruckler bei ansonsten flüssiger Wiedergabe werden also erkannt, während eine grundsätzlich niedrige Bildrate nicht als Freeze gilt.

Den Wert liest du über RTCPeerConnection.getStats() oder RTCRtpReceiver.getStats() aus. Er wächst über die gesamte Lebensdauer des Streams, fällt also nie. Für eine Überwachung der Qualität (etwa ein „Verbindung instabil“-Hinweis oder Telemetrie) bildest du deshalb die Differenz zwischen zwei Messungen. Zusammen mit totalFreezesDuration kannst du Häufigkeit und Gesamtdauer der Freezes auswerten.

Rückgabewert

Typ
number (unsigned long) | undefined
Beschreibung
Gesamtzahl der bisher erkannten Video-Freezes als nicht negative ganze Zahl. undefined, wenn der Stream kein Video ist oder der Browser die Eigenschaft nicht unterstützt.

Beispiele

Freezes aller eingehenden Video-Streams ausgeben

// pc ist eine bestehende, verbundene RTCPeerConnection
const logFreezes = async (pc) => {
  const report = await pc.getStats();
  report.forEach((stats) => {
    if (stats.type === 'inbound-rtp' && stats.kind === 'video') {
      console.log(`Stream ${stats.ssrc}: ${stats.freezeCount ?? 'n/a'} Freezes, ` +
        `${(stats.totalFreezesDuration ?? 0).toFixed(2)} s eingefroren`);
    }
  });
};

await logFreezes(pc);
Stream 12345678: 3 Freezes, 1.84 s eingefroren

Neue Freezes pro Intervall erkennen und Nutzer warnen

const watchFreezes = (receiver, onFreeze, intervalMs = 2000) => {
  let lastCount = null;
  const timer = setInterval(async () => {
    const report = await receiver.getStats();
    for (const stats of report.values()) {
      if (stats.type !== 'inbound-rtp' || stats.kind !== 'video') continue;
      const count = stats.freezeCount;
      if (count === undefined) return; // nicht unterstützt
      if (lastCount !== null && count > lastCount) {
        onFreeze(count - lastCount);
      }
      lastCount = count;
    }
  }, intervalMs);
  return () => clearInterval(timer); // Aufräumfunktion
};

const videoReceiver = pc.getReceivers().find((r) => r.track.kind === 'video');
const stop = watchFreezes(videoReceiver, (neu) => {
  console.warn(`${neu} neue(r) Freeze(s) – Verbindung instabil`);
});
// später: stop();
2 neue(r) Freeze(s) – Verbindung instabil

Freeze-Rate pro Minute für die Telemetrie berechnen

const freezeRate = async (pc) => {
  const report = await pc.getStats();
  const video = [...report.values()].find(
    (s) => s.type === 'inbound-rtp' && s.kind === 'video'
  );
  if (!video || video.freezeCount === undefined) return null;

  // Laufzeit grob über die Anzahl dekodierter Frames und die Bildrate schätzen
  const seconds = video.framesDecoded / (video.framesPerSecond || 30);
  const minutes = Math.max(seconds / 60, 1 / 60);
  return +(video.freezeCount / minutes).toFixed(2);
};

console.log('Freezes/Minute:', await freezeRate(pc));
Freezes/Minute: 0.75

// Wichtig · Fallstricke

  • Nur für Video: Bei Einträgen mit kind === "audio" fehlt die Eigenschaft. Prüfe immer zuerst type und kind.
  • Kumulativer Zähler: Der Wert wächst ständig. Für aktuelle Qualitätsaussagen brauchst du die Differenz zwischen zwei Messungen. Wird ein Stream neu ausgehandelt (neue SSRC), kann ein neues Statistik-Objekt entstehen, dessen Zähler wieder bei 0 beginnt.
  • Freeze ist nicht dasselbe wie eine Pause: Sehr lange Lücken (ab 5 Sekunden) zählt die Spezifikation als Pause (pauseCount/totalPausesDuration), zum Beispiel wenn der Sender das Video bewusst anhält.
  • Browser-Unterstützung: Chromium-basierte Browser unterstützen die Eigenschaft, Firefox und Safari aber nicht zuverlässig. Rechne mit undefined und nutze eine Absicherung wie ?? 0 oder eine Prüfung auf Unterstützung.
  • Leistung: getStats() ist asynchron und nicht kostenlos. Abfrage-Intervalle von 1–5 Sekunden reichen in der Regel.