Signatur
Beschreibung
Die Eigenschaft retransmittedPacketsSent eines RTCOutboundRtpStreamStats-Objekts ist ein Zähler (nicht negative Ganzzahl). Er gibt an, wie viele Pakete der Sender für diesen RTP-Stream seit Beginn der Verbindung erneut übertragen hat. Solche Neuübertragungen entstehen meist als Antwort auf NACK-Meldungen (Negative Acknowledgement) der Gegenseite, wenn dort Pakete verloren gegangen sind.
Neu übertragene Pakete laufen entweder über einen eigenen RTX-Stream (siehe rtxSsrc) oder über dieselbe SSRC. In beiden Fällen werden sie diesem Stream zugerechnet. Außerdem sind sie auch in packetsSent enthalten. Das Verhältnis retransmittedPacketsSent / packetsSent zeigt also, welcher Anteil des gesendeten Verkehrs aus Neuübertragungen besteht.
Den Wert erhältst du über RTCPeerConnection.getStats() oder RTCRtpSender.getStats(), indem du Einträge mit type === "outbound-rtp" auswählst. Er eignet sich gut für Qualitätsmonitoring: Steigen die Neuübertragungen, ist das Netz verlustbehaftet oder überlastet. Die Anwendung kann dann zum Beispiel Bitrate oder Auflösung senken.
Rückgabewert
unsigned long long). Der Wert steigt nur an. Er ist undefined, wenn keine Neuübertragung ausgehandelt wurde oder der Browser das Feld nicht liefert.Beispiele
Neuübertragungen aller ausgehenden Streams auslesen
// pc ist eine bestehende, verbundene RTCPeerConnection
const logRetransmissions = async (pc) => {
const stats = await pc.getStats();
stats.forEach((report) => {
if (report.type === 'outbound-rtp') {
console.log(
`${report.kind} (SSRC ${report.ssrc}): ` +
`${report.retransmittedPacketsSent ?? 'n/a'} von ${report.packetsSent} Paketen neu gesendet`
);
}
});
};
await logRetransmissions(pc);
Neuübertragungsrate pro Intervall überwachen
// Differenz zwischen zwei Messungen: Wie viel Prozent war zuletzt Neuübertragung?
const monitorRetransmissionRate = (sender, intervalMs = 2000) => {
let prev = null;
return setInterval(async () => {
const stats = await sender.getStats();
for (const r of stats.values()) {
if (r.type !== 'outbound-rtp' || r.retransmittedPacketsSent === undefined) continue;
if (prev) {
const sent = r.packetsSent - prev.packetsSent;
const resent = r.retransmittedPacketsSent - prev.retransmittedPacketsSent;
const rate = sent > 0 ? (resent / sent) * 100 : 0;
console.log(`Neuübertragungsrate: ${rate.toFixed(2)} %`);
if (rate > 5) console.warn('Hohe Neuübertragungsrate – Bitrate reduzieren?');
}
prev = { packetsSent: r.packetsSent, retransmittedPacketsSent: r.retransmittedPacketsSent };
}
}, intervalMs);
};
const [videoSender] = pc.getSenders().filter((s) => s.track?.kind === 'video');
const timer = monitorRetransmissionRate(videoSender);
// später: clearInterval(timer);
Mit NACKs der Gegenseite und Bytes vergleichen
const stats = await pc.getStats();
const outbound = [...stats.values()].find(
(r) => r.type === 'outbound-rtp' && r.kind === 'video'
);
if (outbound) {
const { nackCount = 0, retransmittedPacketsSent = 0, retransmittedBytesSent = 0 } = outbound;
console.log(`Empfangene NACKs: ${nackCount}`);
console.log(`Neu gesendete Pakete: ${retransmittedPacketsSent}`);
console.log(`Neu gesendete Bytes: ${retransmittedBytesSent}`);
}
// Wichtig · Fallstricke
- Kumulativer Zähler: Der Wert zählt seit Beginn des Streams immer weiter. Aussagen über die aktuelle Netzqualität bekommst du nur über die Differenz zwischen zwei Messungen.
- In
packetsSententhalten: Neu übertragene Pakete werden auch inpacketsSentgezählt. Wer „Nutzpakete“ berechnen will, muss sie abziehen. - Nicht immer vorhanden: Das Feld fehlt, wenn keine Neuübertragung ausgehandelt wurde (kein NACK/RTX im SDP). Das betrifft vor allem Audio-Streams, bei denen Browser üblicherweise keine Neuübertragungen nutzen. Prüfe den Wert deshalb immer auf
undefined. - Browser-Unterstützung: Chromium-basierte Browser (Chrome, Edge) liefern den Wert zuverlässig. Firefox und Safari unterstützen ihn gar nicht oder nur teilweise. Prüfe das Feld deshalb zur Laufzeit, statt es vorauszusetzen.
- Bei Simulcast gibt es pro Ebene (
rid) einen eigenenoutbound-rtp-Eintrag mit eigenem Zähler. Für einen Gesamtwert musst du die Werte aufsummieren.