Signatur
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
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);
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);
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
codecIdim zugehörigenRTCCodecStats. - Kumulativer Zähler:
qpSumwä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 entstehtNaN. - 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.