Signatur
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
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);
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);
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);
// Wichtig · Fallstricke
- Nur für Audio: Bei
inbound-rtp-Einträgen mitkind === "video"fehlt die Eigenschaft. Prüfen Sie deshalb immerkindoder 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
totalSamplesDurationteilt. Wer nurtotalAudioEnergydurch 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 aufundefinedprüfen. - Performance:
getStats()ist asynchron und nicht kostenlos. Abfrageintervalle unter etwa 100 ms sind selten sinnvoll.