Start · Sprachen · JavaScript · Referenz · RTCOutboundRtpStreamStats.targetBitrate

RTCOutboundRtpStreamStats.targetBitrate

Eigenschaft

Gibt die aktuelle Ziel-Bitrate des Encoders für einen ausgehenden RTP-Stream in Bit pro Sekunde (bps) an.

seit JavaScript Chrome 86+, Firefox 138+ (teilweise), Safari 15.4+ Kategorie: webapi

Signatur

RTCOutboundRtpStreamStats.targetBitrate

Beschreibung

Die Eigenschaft targetBitrate des Wörterbuchs RTCOutboundRtpStreamStats enthält die Bitrate, die der Codec des ausgehenden Streams gerade anstrebt. Die Angabe erfolgt in Bit pro Sekunde als Gleitkommazahl. Dieser Wert ist ein Sollwert. Er beschreibt also, auf welches Datenvolumen der Encoder hinarbeitet, und nicht, wie viele Daten tatsächlich gesendet werden.

Den Wert bestimmen die Staukontrolle des Browsers (z. B. GCC bzw. Transport-CC), die verfügbare Bandbreite und Vorgaben wie maxBitrate aus RTCRtpSender.setParameters(). Deshalb schwankt targetBitrate während einer Verbindung: Bei Paketverlust oder wenig Bandbreite sinkt der Wert, bei guter Verbindung steigt er.

Nützlich ist die Eigenschaft für Qualitätsanzeigen, Diagnose-Dashboards und Tests für adaptives Streaming. Wer die Ziel-Bitrate mit der tatsächlich gesendeten Bitrate vergleicht, erkennt, ob der Encoder sein Ziel erreicht. Die tatsächliche Bitrate berechnet man aus der Differenz von bytesSent zwischen zwei Messungen. Den Wert erhält man über RTCPeerConnection.getStats() oder RTCRtpSender.getStats(), und zwar an Einträgen mit type === "outbound-rtp".

Rückgabewert

Typ
number | undefined
Beschreibung
Die aktuelle Ziel-Bitrate des Encoders in Bit pro Sekunde (Gleitkommazahl). Ist undefined, wenn der Browser den Wert nicht liefert.

Beispiele

Ziel-Bitrate aller ausgehenden Streams auslesen

// pc ist eine verbundene RTCPeerConnection
const logTargetBitrates = async (pc) => {
  const report = await pc.getStats();
  report.forEach((stats) => {
    if (stats.type === 'outbound-rtp' && stats.targetBitrate !== undefined) {
      console.log(`${stats.kind}: ${(stats.targetBitrate / 1000).toFixed(0)} kbit/s`);
    }
  });
};

await logTargetBitrates(pc);
video: 2500 kbit/s audio: 32 kbit/s

Ziel-Bitrate mit tatsächlicher Senderate vergleichen

const monitorSender = (sender, intervalMs = 1000) => {
  let lastBytes = 0;
  let lastTimestamp = 0;

  return setInterval(async () => {
    const report = await sender.getStats();
    for (const stats of report.values()) {
      if (stats.type !== 'outbound-rtp') continue;

      if (lastTimestamp) {
        // timestamp ist in Millisekunden
        const seconds = (stats.timestamp - lastTimestamp) / 1000;
        const actual = ((stats.bytesSent - lastBytes) * 8) / seconds;
        const target = stats.targetBitrate ?? NaN;
        console.log(
          `Ziel: ${Math.round(target / 1000)} kbit/s, ` +
          `Ist: ${Math.round(actual / 1000)} kbit/s`
        );
      }
      lastBytes = stats.bytesSent;
      lastTimestamp = stats.timestamp;
    }
  }, intervalMs);
};

const [videoSender] = pc.getSenders().filter((s) => s.track?.kind === 'video');
const timer = monitorSender(videoSender);
// später: clearInterval(timer);
Ziel: 1800 kbit/s, Ist: 1742 kbit/s

Wirkung von maxBitrate auf targetBitrate prüfen

const limitVideoBitrate = async (sender, maxBitrate) => {
  const params = sender.getParameters();
  if (!params.encodings?.length) params.encodings = [{}];
  params.encodings[0].maxBitrate = maxBitrate;
  await sender.setParameters(params);

  // Dem Encoder etwas Zeit zur Anpassung geben
  await new Promise((resolve) => setTimeout(resolve, 3000));

  const report = await sender.getStats();
  const outbound = [...report.values()].find((s) => s.type === 'outbound-rtp');
  console.log('Neue Ziel-Bitrate:', outbound?.targetBitrate);
};

await limitVideoBitrate(videoSender, 500_000);
Neue Ziel-Bitrate: 500000

// Wichtig · Fallstricke

  • Einheit: Der Wert wird in Bit pro Sekunde angegeben, nicht in Byte. Wer ihn mit bytesSent vergleichen will, muss die Bytes mit 8 multiplizieren.
  • Sollwert, kein Messwert: targetBitrate sagt nichts darüber, was tatsächlich übertragen wird. Die tatsächliche Senderate liegt oft etwas darunter, etwa bei statischen Bildinhalten, oder schwankt kurzzeitig darüber.
  • Simulcast/SVC: Bei Simulcast gibt es für jede Encoding-Schicht einen eigenen outbound-rtp-Eintrag mit eigener targetBitrate. Die einzelnen Schichten unterscheidet man über rid.
  • Kompatibilität: Chromium-Browser und Safari unterstützen die Eigenschaft. In Firefox ist die Unterstützung eingeschränkt oder neu. Vor der Nutzung sollte man deshalb immer auf undefined prüfen, z. B. mit ??.
  • Nach dem Verbindungsaufbau: Direkt nach dem Verbindungsaufbau ist der Wert meist niedrig. Er steigt erst, wenn die Bandbreitenschätzung hochläuft. Einzelmessungen am Anfang sind daher wenig aussagekräftig.