Signatur
Beschreibung
Die Eigenschaft packetsDiscarded eines RTCInboundRtpStreamStats-Objekts (Statistiktyp "inbound-rtp") zählt alle RTP-Pakete, die zwar empfangen, aber vom Jitter-Puffer verworfen wurden. Das passiert, wenn ein Paket zu spät ankommt (seine Abspielzeit ist schon vorbei) oder zu früh (der Puffer ist voll bzw. das Paket liegt außerhalb des Pufferfensters).
Wichtig ist die Abgrenzung zu packetsLost: Verlorene Pakete sind nie angekommen, verworfene Pakete dagegen schon – sie werden in packetsReceived mitgezählt, aber nicht wiedergegeben. Ein steigender Wert von packetsDiscarded deutet daher weniger auf Paketverlust im Netz als auf starken Jitter (schwankende Laufzeiten) oder einen zu knapp bemessenen Jitter-Puffer hin.
Der Wert ist ein monoton wachsender Zähler seit Beginn des Streams. Für Qualitätsmetriken wie „verworfene Pakete pro Sekunde“ oder eine Verwurfsrate bildet man die Differenz zwischen zwei Abfragen von RTCPeerConnection.getStats() und setzt sie ins Verhältnis zur Differenz von packetsReceived.
Rückgabewert
undefined, wenn der Browser die Metrik nicht liefert.Beispiele
Verworfene Pakete aller eingehenden Streams auslesen
// pc ist eine bestehende, verbundene RTCPeerConnection
const logDiscarded = async (pc) => {
const stats = await pc.getStats();
stats.forEach((report) => {
if (report.type === 'inbound-rtp') {
console.log(
`${report.kind} (SSRC ${report.ssrc}): ` +
`${report.packetsDiscarded ?? 'n/a'} verworfen, ` +
`${report.packetsReceived} empfangen`
);
}
});
};
await logDiscarded(pc);
Verwurfsrate pro Intervall überwachen
const monitorDiscardRate = (pc, intervalMs = 2000) => {
const previous = new Map();
return setInterval(async () => {
const stats = await pc.getStats();
for (const r of stats.values()) {
if (r.type !== 'inbound-rtp' || r.packetsDiscarded === undefined) continue;
const prev = previous.get(r.id);
if (prev) {
const discarded = r.packetsDiscarded - prev.packetsDiscarded;
const received = r.packetsReceived - prev.packetsReceived;
const rate = received > 0 ? (discarded / received) * 100 : 0;
if (rate > 1) {
console.warn(`${r.kind}: ${rate.toFixed(2)} % verworfen – hoher Jitter?`);
}
}
previous.set(r.id, {
packetsDiscarded: r.packetsDiscarded,
packetsReceived: r.packetsReceived,
});
}
}, intervalMs);
};
const timer = monitorDiscardRate(pc);
// später: clearInterval(timer);
Verlust und Verwurf gegenüberstellen
const diagnose = async (receiver) => {
// Statistik nur für einen bestimmten RTCRtpReceiver
const stats = await receiver.getStats();
const inbound = [...stats.values()].find((r) => r.type === 'inbound-rtp');
if (!inbound) return 'Keine Daten';
const { packetsLost = 0, packetsDiscarded = 0, jitter = 0 } = inbound;
if (packetsDiscarded > packetsLost) {
return `Jitter-Problem (Jitter ${(jitter * 1000).toFixed(1)} ms)`;
}
return packetsLost > 0 ? 'Paketverlust im Netz' : 'Alles in Ordnung';
};
const [receiver] = pc.getReceivers();
console.log(await diagnose(receiver));
// Wichtig · Fallstricke
- Nicht mit
packetsLostverwechseln: Verworfene Pakete sind angekommen und inpacketsReceivedenthalten; verlorene Pakete sind nie angekommen. - Kumulativer Zähler: Aussagekräftig sind nur Differenzen zwischen zwei Messungen. Bei Neuverhandlung oder SSRC-Wechsel kann ein neues Statistikobjekt mit einer neuen
identstehen – Werte daher proidvergleichen. - Browser-Unterstützung: Chromium-Browser liefern den Wert zuverlässig; in Firefox und Safari kann er fehlen oder dauerhaft
0sein. Immer aufundefinedprüfen (z. B. mit??). - Bei Video hängt die Zählung stark von der Implementierung des Jitter-Puffers ab; Werte verschiedener Browser sind nur bedingt vergleichbar.
getStats()ist asynchron und nicht kostenlos – Abfrageintervalle unter ca. 1 Sekunde vermeiden.