Start · Sprachen · JavaScript · Referenz · RTCInboundRtpStreamStats.qpSum

RTCInboundRtpStreamStats.qpSum

Eigenschaft

Summe der Quantisierungsparameter (QP) aller Bilder, die dieser eingehende Video-RTP-Stream bisher dekodiert hat. Geteilt durch <code>framesDecoded</code> ergibt sich ein Maß für die Bildqualität.

seit JavaScript Chrome 80+, Firefox 66+, Safari 14.1+ (nur Video-S Kategorie: webapi

Signatur

RTCInboundRtpStreamStats.qpSum

Beschreibung

Die schreibgeschützte Eigenschaft qpSum des Wörterbuchs RTCInboundRtpStreamStats enthält die aufsummierten Quantization Parameter (QP) aller Bilder, die der Empfänger für diesen eingehenden Videostream bisher dekodiert hat. Der QP legt fest, wie stark der Encoder das Bild komprimiert hat: Ein höherer QP bedeutet mehr Kompression und damit geringere Bildqualität, ein niedrigerer QP bedeutet mehr Details.

Ein einzelner Wert von qpSum sagt allein wenig aus. Aussagekräftig wird er erst im Verhältnis zur Anzahl der dekodierten Bilder: qpSum / framesDecoded ergibt den durchschnittlichen QP über die gesamte Sitzung. Für die Überwachung in Echtzeit berechnet man besser das Delta zwischen zwei Messungen, also (qpSum₂ − qpSum₁) / (framesDecoded₂ − framesDecoded₁). So bekommt man den durchschnittlichen QP im letzten Messintervall.

Das ist nützlich für Qualitäts-Dashboards, adaptive Oberflächen (z. B. ein Hinweis bei schlechter Verbindung) und für die Fehlersuche, wenn Bandbreite knapp ist. Die Eigenschaft gibt es nur bei Streams mit kind === "video". Bei Audio-Streams fehlt sie.

Rückgabewert

Typ
number | undefined
Beschreibung
Eine nicht negative Ganzzahl (unsigned long long): die Summe der QP-Werte aller dekodierten Bilder. Der Wert ist undefined, wenn der Stream kein Video ist oder der Browser bzw. Codec keinen QP meldet.

Beispiele

Durchschnittlichen QP eines eingehenden Videostreams auslesen

// pc ist eine bestehende, verbundene RTCPeerConnection
const logAverageQp = async (pc) => {
  const stats = await pc.getStats();
  stats.forEach((report) => {
    if (report.type === 'inbound-rtp' && report.kind === 'video' && report.qpSum !== undefined) {
      const avgQp = report.framesDecoded > 0 ? report.qpSum / report.framesDecoded : 0;
      console.log(`Durchschnittlicher QP: ${avgQp.toFixed(1)}`);
    }
  });
};

await logAverageQp(pc);
Durchschnittlicher QP: 27.4

QP pro Messintervall überwachen (Delta-Berechnung)

let previous = null;

const monitorQp = (pc, intervalMs = 2000) => setInterval(async () => {
  const stats = await pc.getStats();
  for (const report of stats.values()) {
    if (report.type !== 'inbound-rtp' || report.kind !== 'video') continue;
    if (previous && report.framesDecoded > previous.framesDecoded) {
      const qpDelta = report.qpSum - previous.qpSum;
      const framesDelta = report.framesDecoded - previous.framesDecoded;
      console.log(`QP im Intervall: ${(qpDelta / framesDelta).toFixed(1)}`);
    }
    previous = { qpSum: report.qpSum, framesDecoded: report.framesDecoded };
  }
}, intervalMs);

const timer = monitorQp(pc);
// Später: clearInterval(timer);
QP im Intervall: 24.8 QP im Intervall: 31.2

Warnung in der Oberfläche bei schlechter Bildqualität

const QP_THRESHOLD = 35; // grober Richtwert für VP8/H.264

const checkQuality = async (receiver) => {
  const stats = await receiver.getStats();
  const inbound = [...stats.values()].find(
    (r) => r.type === 'inbound-rtp' && r.kind === 'video'
  );
  if (!inbound?.qpSum || !inbound.framesDecoded) return;
  const avgQp = inbound.qpSum / inbound.framesDecoded;
  document.querySelector('#quality-hint').hidden = avgQp < QP_THRESHOLD;
};

const [videoReceiver] = pc.getReceivers().filter((r) => r.track.kind === 'video');
await checkQuality(videoReceiver);

// Wichtig · Fallstricke

  • Codecabhängige Skala: Die QP-Wertebereiche hängen vom Codec ab. VP8 und VP9 nutzen 0–127, H.264 nutzt 0–51, AV1 nutzt 0–255. Vergleiche und Schwellenwerte sind deshalb nur innerhalb desselben Codecs sinnvoll. Den verwendeten Codec findest du über codecId im zugehörigen RTCCodecStats.
  • Kumulativer Zähler: qpSum wächst über die ganze Sitzung. Für aktuelle Werte immer Differenzen zwischen zwei Messungen bilden. Nach einer Neuverhandlung oder einem neuen SSRC kann der Zähler wieder bei 0 beginnen.
  • Nur Video: Bei Audio-Streams ist der Wert undefined. Vor dem Rechnen immer prüfen, ob er vorhanden ist, sonst entsteht NaN.
  • Browserunterstützung: Chromium-Browser, Firefox und Safari unterstützen die Eigenschaft. Ob tatsächlich ein Wert gemeldet wird, kann aber vom Hardware-Decoder abhängen.
  • Auf der Senderseite gibt es das Gegenstück RTCOutboundRtpStreamStats.qpSum, das sich auf die kodierten Bilder bezieht.