Signatur
Beschreibung
Die schreibgeschützte Eigenschaft totalAudioEnergy gehört zum Wörterbuch RTCAudioSourceStats. Das ist der Statistikeintrag vom Typ "media-source" mit kind === "audio", der eine lokal erfasste Audioquelle beschreibt, etwa ein Mikrofon-Track, der über einen RTCRtpSender gesendet wird. Den Eintrag bekommst du über RTCPeerConnection.getStats() oder RTCRtpSender.getStats().
Der Wert wird fortlaufend aufsummiert: Für jedes Audio-Sample wird der Pegel (audioLevel, linear zwischen 0,0 und 1,0) quadriert, mit der Dauer des Samples in Sekunden multipliziert und zur Summe addiert. So bekommst du ein Maß für die Energie, das von der Messzeit abhängt und nicht nur einen einzelnen Momentwert.
Richtig nützlich wird die Eigenschaft zusammen mit totalSamplesDuration. Aus den Unterschieden zwischen zwei Messungen berechnest du den mittleren Pegel für genau dieses Intervall: Math.sqrt(ΔtotalAudioEnergy / ΔtotalSamplesDuration). Das ist deutlich stabiler als ein einzelner audioLevel-Wert und eignet sich für Pegelanzeigen, zum Erkennen von Stille („Ist das Mikrofon stummgeschaltet?“) oder für Qualitätsmetriken.
Rückgabewert
audioLevel² × Sample-Dauer in Sekunden). Der Wert steigt monoton an und beginnt bei 0. Unterstützt der Browser die Eigenschaft nicht, ist sie undefined.Beispiele
totalAudioEnergy der Mikrofonquelle auslesen
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const pc = new RTCPeerConnection();
const [track] = stream.getAudioTracks();
const sender = pc.addTrack(track, stream);
// Kurz warten, damit Samples verarbeitet werden
await new Promise((r) => setTimeout(r, 2000));
const report = await sender.getStats();
report.forEach((stats) => {
if (stats.type === 'media-source' && stats.kind === 'audio') {
console.log('Gesamtenergie:', stats.totalAudioEnergy);
console.log('Sample-Dauer (s):', stats.totalSamplesDuration);
}
});
Mittleren Pegel pro Intervall berechnen
const getAudioSource = async (sender) => {
const report = await sender.getStats();
for (const stats of report.values()) {
if (stats.type === 'media-source' && stats.kind === 'audio') return stats;
}
return null;
};
const monitorLevel = (sender, intervalMs = 1000) => {
let last = null;
return setInterval(async () => {
const current = await getAudioSource(sender);
if (!current || current.totalAudioEnergy === undefined) return;
if (last) {
const dEnergy = current.totalAudioEnergy - last.totalAudioEnergy;
const dDuration = current.totalSamplesDuration - last.totalSamplesDuration;
if (dDuration > 0) {
const avgLevel = Math.sqrt(dEnergy / dDuration);
const dBov = avgLevel > 0 ? 20 * Math.log10(avgLevel) : -Infinity;
console.log(`Ø Pegel: ${avgLevel.toFixed(3)} (${dBov.toFixed(1)} dBov)`);
}
}
last = current;
}, intervalMs);
};
// const timer = monitorLevel(sender);
Stille bzw. stummes Mikrofon erkennen
const SILENCE_THRESHOLD = 0.01; // ca. -40 dBov
let prev = null;
const checkSilence = async (pc) => {
const report = await pc.getStats();
const src = [...report.values()].find(
(s) => s.type === 'media-source' && s.kind === 'audio'
);
if (!src) return;
if (prev) {
const dE = src.totalAudioEnergy - prev.totalAudioEnergy;
const dT = src.totalSamplesDuration - prev.totalSamplesDuration;
const level = dT > 0 ? Math.sqrt(dE / dT) : 0;
if (level < SILENCE_THRESHOLD) {
console.warn('Kein Audiosignal – ist das Mikrofon stummgeschaltet?');
}
}
prev = src;
};
// setInterval(() => checkSilence(pc), 3000);
// Wichtig · Fallstricke
- Nur Differenzen sind aussagekräftig: Der absolute Wert wächst mit der Zeit immer weiter. Vergleiche deshalb zwei Messungen und teile durch die Differenz von
totalSamplesDuration. - Nicht mit
audioLevelverwechseln:audioLevelist ein Momentwert zwischen 0 und 1,totalAudioEnergyist eine Summe von quadrierten Pegeln, gewichtet mit der Zeit. Um wieder einen Pegel zu bekommen, musst du die Quadratwurzel ziehen. - Lokale Quelle: Der Wert beschreibt das Audio vor der Kodierung, also die Quelle selbst. Ist der Track mit
track.enabled = falsedeaktiviert, werden Stille-Samples gezählt: Die Energie bleibt dann nahezu gleich,totalSamplesDurationsteigt aber weiter. Für empfangenes Audio gibt es eine eigenetotalAudioEnergyinRTCInboundRtpStreamStats. - Browser-Kompatibilität: Wird in Chromium-Browsern und Safari unterstützt. In Firefox fehlen die Audio-Felder der
media-source-Statistik teilweise. Prüfe deshalb immer aufundefined. - Performance:
getStats()ist asynchron und nicht kostenlos. Ein Abfrageintervall von 250 ms bis 1 s reicht für Pegelanzeigen in der Regel aus.