Signatur
Beschreibung
Die Eigenschaft packetsSent des Wörterbuchs RTCOutboundRtpStreamStats enthält einen nicht negativen, monoton steigenden Zähler. Er gibt an, wie viele RTP-Pakete der lokale RTCRtpSender für diese SSRC seit Beginn der Übertragung gesendet hat. Erneut übertragene Pakete (etwa nach NACK oder über RTX) werden mitgezählt.
Du erhältst den Wert über RTCPeerConnection.getStats() oder RTCRtpSender.getStats(). Er steht in den Berichten mit type === "outbound-rtp". Ein einzelner Wert sagt wenig aus. Nützlich wird er erst, wenn du zwei Messungen vergleichst: Aus der Differenz zweier Abfragen und dem Unterschied ihrer timestamp-Werte berechnest du die Paketrate (Pakete pro Sekunde).
Typische Einsatzzwecke sind Qualitäts-Dashboards, das Erkennen eingefrorener Sender (der Zähler steigt nicht mehr) und die Berechnung der Verlustrate. Dafür setzt du den Wert ins Verhältnis zu packetsLost aus dem passenden remote-inbound-rtp-Bericht. Zusammen mit retransmittedPacketsSent kannst du außerdem den Anteil erneuter Übertragungen bestimmen.
Rückgabewert
Beispiele
Gesendete Pakete aller ausgehenden Streams auslesen
const logPacketsSent = async (pc) => {
const report = await pc.getStats();
report.forEach((stats) => {
if (stats.type === 'outbound-rtp') {
console.log(`${stats.kind} (SSRC ${stats.ssrc}): ${stats.packetsSent} Pakete gesendet`);
}
});
};
// Aufruf mit einer bestehenden, verbundenen RTCPeerConnection
await logPacketsSent(peerConnection);
Paketrate pro Sekunde berechnen
const sender = peerConnection.getSenders().find((s) => s.track?.kind === 'video');
let previous = null;
const sample = async () => {
const report = await sender.getStats();
for (const stats of report.values()) {
if (stats.type !== 'outbound-rtp') continue;
if (previous) {
const seconds = (stats.timestamp - previous.timestamp) / 1000;
const rate = (stats.packetsSent - previous.packetsSent) / seconds;
console.log(`Video: ${rate.toFixed(1)} Pakete/s`);
}
previous = stats;
}
};
const timer = setInterval(sample, 1000);
Eingefrorenen Sender und Verlustrate erkennen
const checkHealth = async (pc, last = new Map()) => {
const report = await pc.getStats();
for (const stats of report.values()) {
if (stats.type !== 'outbound-rtp') continue;
const before = last.get(stats.id);
if (before !== undefined && stats.packetsSent === before) {
console.warn(`Stream ${stats.id} sendet keine Pakete mehr!`);
}
last.set(stats.id, stats.packetsSent);
// Verlustrate über den zugehörigen remote-inbound-rtp-Bericht
const remote = report.get(stats.remoteId);
if (remote && stats.packetsSent > 0) {
const loss = (remote.packetsLost / stats.packetsSent) * 100;
console.log(`Verlust ${stats.kind}: ${loss.toFixed(2)} %`);
}
}
return last;
};
let state = await checkHealth(peerConnection);
setInterval(async () => { state = await checkHealth(peerConnection, state); }, 2000);
// Wichtig · Fallstricke
- Kumulativer Zähler: Der Wert zählt ab dem Start des Streams immer weiter hoch. Für Raten musst du Differenzen bilden und durch die Differenz der
timestamp-Werte (in Millisekunden) teilen. - Erneute Übertragungen sind enthalten: Wenn du nur neue Nutzdaten zählen willst, ziehe
retransmittedPacketsSentab, sofern der Browser diesen Wert liefert. - Simulcast: Bei Simulcast gibt es pro Ebene (
rid) einen eigenenoutbound-rtp-Bericht. Für die Gesamtmenge summierst du die Werte aller Ebenen. - Zurückgesetzte Werte: Wird ein Track ersetzt oder die Verbindung neu ausgehandelt, kann ein neuer Bericht mit neuer
identstehen. Vergleiche Messungen deshalb nur über dieselbeid. - Kompatibilität: Alle modernen Browser (Chrome, Edge, Firefox, Safari) unterstützen die Eigenschaft. Ältere Browser lieferten Statistiken zum Teil im veralteten, callbackbasierten
getStats()-Format mit anderen Feldnamen. Prüfe vorab mittypeof stats.packetsSent === 'number', ob der Wert vorhanden ist.