Start · Sprachen · JavaScript · Referenz · RTCInboundRtpStreamStats.totalAudioEnergy

RTCInboundRtpStreamStats.totalAudioEnergy

Eigenschaft

Die über die gesamte Lebensdauer des Statistik-Objekts aufsummierte Audioenergie eines empfangenen Audiotracks, als <code>number</code>.

seit JavaScript WebRTC Statistics API; Chromium, Firefox, Safari ( Kategorie: webapi

Signatur

RTCInboundRtpStreamStats.totalAudioEnergy

Beschreibung

Die Eigenschaft totalAudioEnergy eines RTCInboundRtpStreamStats-Objekts (Statistik-Typ "inbound-rtp") enthält die gesamte Audioenergie, die auf einem eingehenden Audio-RTP-Stream empfangen wurde. Für jedes empfangene Sample wird der normierte Pegel (Samplewert geteilt durch den höchstmöglichen Wert, also 0,0 bis 1,0) quadriert, mit der Dauer des Samples in Sekunden multipliziert und aufaddiert.

Einzeln ist der Wert kaum aussagekräftig, weil er nur wächst. Nützlich wird er, wenn man zwei Messungen vergleicht. Zusammen mit totalSamplesDuration lässt sich so der durchschnittliche Audiopegel über einen beliebigen Zeitraum berechnen: Math.sqrt(ΔtotalAudioEnergy / ΔtotalSamplesDuration). Das Ergebnis ist ein RMS-Pegel im Bereich 0 bis 1 und lässt sich direkt mit audioLevel vergleichen.

Typische Einsatzfälle sind Sprecher-Erkennung (wer spricht gerade?), Pegelanzeigen für entfernte Teilnehmende in Videokonferenzen und Qualitätsmonitoring, etwa um stumme oder sehr leise Streams zu erkennen. Anders als die Momentaufnahme audioLevel ergibt die Berechnung über totalAudioEnergy einen geglätteten Mittelwert, bei dem kein Sample verloren geht.

Rückgabewert

Typ
number | undefined
Beschreibung
Eine nicht negative Gleitkommazahl mit der aufsummierten Energie (Einheit: normierter Pegel² × Sekunden). Bei Video-Streams (kind === "video") ist der Wert undefined.

Beispiele

Gesamtenergie aller eingehenden Audio-Streams auslesen

// pc ist eine bestehende, verbundene RTCPeerConnection
const logAudioEnergy = async (pc) => {
  const report = await pc.getStats();
  report.forEach((stats) => {
    if (stats.type === 'inbound-rtp' && stats.kind === 'audio') {
      console.log(`SSRC ${stats.ssrc}: Energie = ${stats.totalAudioEnergy?.toFixed(4)}, ` +
        `Dauer = ${stats.totalSamplesDuration?.toFixed(1)} s`);
    }
  });
};

await logAudioEnergy(pc);
SSRC 1234567890: Energie = 0.8231, Dauer = 42.3 s

Durchschnittspegel pro Intervall berechnen (Pegelanzeige)

const lastValues = new Map(); // ssrc -> { energy, duration }

const sampleLevels = async (pc) => {
  const report = await pc.getStats();
  for (const stats of report.values()) {
    if (stats.type !== 'inbound-rtp' || stats.kind !== 'audio') continue;

    const prev = lastValues.get(stats.ssrc);
    lastValues.set(stats.ssrc, {
      energy: stats.totalAudioEnergy,
      duration: stats.totalSamplesDuration
    });
    if (!prev) continue; // erste Messung dient nur als Basis

    const dEnergy = stats.totalAudioEnergy - prev.energy;
    const dDuration = stats.totalSamplesDuration - prev.duration;
    if (dDuration <= 0) continue;

    const rms = Math.sqrt(dEnergy / dDuration);      // 0 … 1
    const dBov = rms > 0 ? 20 * Math.log10(rms) : -Infinity;
    console.log(`SSRC ${stats.ssrc}: Pegel ${rms.toFixed(3)} (${dBov.toFixed(1)} dBov)`);
  }
};

const timer = setInterval(() => sampleLevels(pc), 1000);
// später: clearInterval(timer);
SSRC 1234567890: Pegel 0.142 (-17.0 dBov)

Aktive Sprecher erkennen

const SPEAKING_THRESHOLD = 0.02; // RMS-Schwelle, empirisch anpassen
const previous = new Map();

const detectSpeakers = async (pc) => {
  const speaking = [];
  const report = await pc.getStats();
  report.forEach((s) => {
    if (s.type !== 'inbound-rtp' || s.kind !== 'audio') return;
    const p = previous.get(s.id);
    previous.set(s.id, s);
    if (!p) return;
    const dur = s.totalSamplesDuration - p.totalSamplesDuration;
    if (dur <= 0) return;
    const level = Math.sqrt((s.totalAudioEnergy - p.totalAudioEnergy) / dur);
    if (level > SPEAKING_THRESHOLD) speaking.push(s.trackIdentifier ?? s.id);
  });
  return speaking;
};

setInterval(async () => {
  console.log('Spricht gerade:', await detectSpeakers(pc));
}, 500);
Spricht gerade: [ 'a1b2c3d4-…' ]

// Wichtig · Fallstricke

  • Nur für Audio: Bei inbound-rtp-Einträgen mit kind === "video" fehlt die Eigenschaft. Prüfen Sie deshalb immer kind oder verwenden Sie optionale Verkettung (?.).
  • Kumulativ: Der Wert wächst nur. Aussagekräftig ist erst die Differenz zwischen zwei Messungen, die man durch die Differenz von totalSamplesDuration teilt. Wer nur totalAudioEnergy durch die Wanduhrzeit teilt, bekommt falsche Werte, sobald Pakete verloren gehen oder Stille unterdrückt wird (DTX).
  • Nicht in Dezibel: Die Wurzel aus dem Quotienten ergibt einen linearen RMS-Pegel. Für dBov rechnen Sie 20 * Math.log10(rms).
  • Nach dem Decoder: Der Pegel wird auf die dekodierte Ausgabe bezogen, vor der Lautstärke eines <audio>-Elements. Stummschalten im Player ändert den Wert also nicht.
  • Kompatibilität: Aktuelle Chromium-Browser, Firefox und Safari unterstützen die Eigenschaft. Ältere Versionen lieferten sie teils nur im veralteten "track"-Statistiktyp. Deshalb vor der Nutzung auf undefined prüfen.
  • Performance: getStats() ist asynchron und nicht kostenlos. Abfrageintervalle unter etwa 100 ms sind selten sinnvoll.