Signatur
Beschreibung
Die Eigenschaft underrunDuration der Schnittstelle AudioPlaybackStats gibt die Gesamtdauer aller Underrun-Ereignisse in Sekunden an. Gezählt wird ab dem Zeitpunkt, an dem der zugehörige AudioContext erstellt wurde. Ein Underrun entsteht, wenn der Audio-Graph nicht rechtzeitig genug Samples für das Ausgabegerät liefert. Der Browser setzt dann Stille ein, und man hört ein Knacksen, Stottern oder kurze Aussetzer.
Das AudioPlaybackStats-Objekt erhält man über audioContext.playbackStats. Zusammen mit underrunEvents (Anzahl der Aussetzer) und totalDuration (gesamte Wiedergabedauer) lässt sich die Wiedergabequalität in Zahlen fassen. Ein Beispiel ist der Anteil der Zeit, in der die Ausgabe gestört war. Das hilft vor allem bei Echtzeit-Anwendungen wie Web-Synthesizern, Spielen, VoIP- oder Streaming-Clients, deren AudioWorklet-Verarbeitung zu viel Rechenzeit braucht.
Typische Einsatzgebiete:
- Telemetrie: Audio-Aussetzer bei echten Nutzern erfassen und an das Backend melden.
- Adaptive Qualität: Bei steigenden Underruns die Rechenlast senken, z. B. durch weniger Stimmen, einfachere Effekte oder eine größere
latencyHint. - Fehlersuche: Zu aufwendige Verarbeitung in
AudioWorkletProcessor.process()aufspüren.
Rückgabewert
0, wenn noch kein Aussetzer aufgetreten ist.Beispiele
Underrun-Dauer auslesen (mit Feature-Erkennung)
const ctx = new AudioContext();
if ('playbackStats' in ctx) {
const stats = ctx.playbackStats;
console.log(`Aussetzer gesamt: ${stats.underrunDuration.toFixed(3)} s`);
console.log(`Anzahl Underruns: ${stats.underrunEvents}`);
} else {
console.log('AudioPlaybackStats wird nicht unterstützt.');
}
Anteil gestörter Wiedergabe laufend überwachen
const ctx = new AudioContext();
const osc = new OscillatorNode(ctx, { frequency: 440 });
osc.connect(ctx.destination);
osc.start();
const timer = setInterval(() => {
const { underrunDuration, totalDuration } = ctx.playbackStats;
if (totalDuration === 0) return;
const ratio = underrunDuration / totalDuration;
console.log(`Gestörter Anteil: ${(ratio * 100).toFixed(2)} %`);
if (ratio > 0.01) {
console.warn('Mehr als 1 % Aussetzer – Rechenlast reduzieren!');
}
}, 2000);
// Später aufräumen:
// clearInterval(timer); await ctx.close();
Qualitätsbericht beim Verlassen der Seite senden
const ctx = new AudioContext({ latencyHint: 'interactive' });
const sendAudioReport = () => {
if (!('playbackStats' in ctx)) return;
const s = ctx.playbackStats;
const report = {
underrunDuration: s.underrunDuration,
underrunEvents: s.underrunEvents,
totalDuration: s.totalDuration,
averageLatency: s.averageLatency
};
navigator.sendBeacon('/api/audio-telemetry', JSON.stringify(report));
};
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'hidden') sendAudioReport();
});
// Wichtig · Fallstricke
- Experimentell:
AudioContext.playbackStatsundAudioPlaybackStatsgibt es bisher nur in Chromium-basierten Browsern. Firefox und Safari unterstützen sie nicht. Vor der Nutzung immer mit'playbackStats' in ctxprüfen. - Einheit: Der Wert ist in Sekunden angegeben, nicht in Millisekunden oder Samples.
- Kumulativ: Der Wert zählt seit dem Start des Kontexts immer weiter und wird nicht automatisch zurückgesetzt. Wer Zeitfenster auswerten will, muss die Differenz zwischen zwei Messungen selbst berechnen.
resetLatency()setzt nur die Latenzwerte zurück, nicht die Underrun-Werte. - Datenschutz: Um Fingerprinting zu erschweren, aktualisieren Browser die Statistik vermutlich nur in groben Abständen. Sehr häufiges Abfragen, etwa pro Animation-Frame, bringt deshalb keine genaueren Werte.
- Solange der Kontext im Zustand
suspendedist (z. B. vor einer Nutzerinteraktion wegen der Autoplay-Regeln), laufen keine Audiodaten. Es können also auch keine Underruns entstehen. - Die Eigenschaft ist schreibgeschützt. Eine Zuweisung wird ignoriert und löst im Strict Mode einen
TypeErroraus.