Signatur
Beschreibung
Das Ereignis sinkchange meldet, dass ein AudioContext seine Ausgabe jetzt über ein anderes Gerät abspielt. In der Regel folgt es auf einen erfolgreichen Aufruf von AudioContext.prototype.setSinkId(). Den Listener registrierst du mit addEventListener("sinkchange", handler) oder über die Eigenschaft onsinkchange.
Das Ereignis ist ein einfaches Event ohne eigene Zusatzdaten. Das neue Ziel liest du im Handler direkt aus audioContext.sinkId aus. Der Wert ist entweder ein string mit der Geräte-ID, ein leerer String für das Standardgerät oder ein AudioSinkInfo-Objekt mit type: "none", wenn die Ausgabe stumm geschaltet ist, aber weiter verarbeitet wird.
Typische Anwendungsfälle:
- Die Oberfläche aktualisieren, zum Beispiel die aktuelle Auswahl in einem Ausgabegeräte-Menü anzeigen.
- Die Geräteauswahl des Nutzers speichern.
- Einstellungen wie Latenz oder Pegel an das neue Gerät anpassen.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Der Ereignisname "sinkchange". |
|
| $handler Pflicht | (event: Event) => void | Callback, das beim Gerätewechsel aufgerufen wird. Es erhält ein einfaches Event. Das neue Gerät liest du über event.target.sinkId aus. |
|
| $options | boolean | AddEventListenerOptions | false | Optionen wie once oder signal, mit denen du den Listener später wieder entfernen kannst. |
Rückgabewert
addEventListener gibt nichts zurück. Der Handler erhält ein Event-Objekt.Beispiele
Gerätewechsel mit addEventListener protokollieren
const ctx = new AudioContext();
ctx.addEventListener("sinkchange", () => {
const sink = ctx.sinkId;
if (typeof sink === "object") {
console.log(`Ausgabe stumm (type: ${sink.type})`);
} else if (sink === "") {
console.log("Ausgabe: Standardgerät");
} else {
console.log(`Neues Ausgabegerät: ${sink}`);
}
});
// Ausgabe stumm schalten, die Verarbeitung läuft weiter
await ctx.setSinkId({ type: "none" });
Geräteauswahl mit onsinkchange und Speichern der Wahl
const ctx = new AudioContext();
const select = document.querySelector("#ausgabe");
// Geräteliste füllen (Labels sind erst nach einer Berechtigung sichtbar)
const devices = await navigator.mediaDevices.enumerateDevices();
for (const d of devices.filter((d) => d.kind === "audiooutput")) {
select.append(new Option(d.label || d.deviceId, d.deviceId));
}
select.addEventListener("change", async () => {
try {
await ctx.setSinkId(select.value);
} catch (err) {
console.error("Wechsel fehlgeschlagen:", err.name);
}
});
ctx.onsinkchange = () => {
localStorage.setItem("audioSink", ctx.sinkId);
console.log("Gespeichert:", ctx.sinkId || "(Standard)");
};
Listener per AbortSignal entfernen
const ctx = new AudioContext();
const controller = new AbortController();
const onSinkChange = () => console.log("Sink:", ctx.sinkId);
ctx.addEventListener("sinkchange", onSinkChange, { signal: controller.signal });
// Später, z. B. beim Schließen des Players:
controller.abort(); // entfernt den Listener
// Alternativ: ctx.removeEventListener("sinkchange", onSinkChange);
await ctx.close();
// Wichtig · Fallstricke
- Browser-Unterstützung: Chromium-basierte Browser unterstützen das Ereignis ab Version 110, Firefox ab Version 150. Safari unterstützt es nicht. Prüfe deshalb vorher mit
"setSinkId" in AudioContext.prototype, ob die Funktion vorhanden ist. - Erfolg und Fehler unterscheiden: Das Ereignis wird nur bei einem erfolgreichen Wechsel ausgelöst. Schlägt
setSinkId()fehl (z. B. mitNotFoundErroroderNotAllowedError), wird das Promise abgelehnt und keinsinkchangeausgelöst. - Kein Ereignis ohne echten Wechsel: Setzt du dieselbe
sinkIderneut, wird in der Regel kein Ereignis ausgelöst. - Nur in sicheren Kontexten: Die Funktion ist nur über HTTPS verfügbar. Für Geräte-IDs von
enumerateDevices()braucht es je nach Browser eine Medien-Berechtigung. Außerdem kann die Permissions Policyspeaker-selectionden Zugriff einschränken. - Typ von
sinkId:sinkIdkann ein String oder ein Objekt sein. Prüfe daher mittypeof, bevor du den Wert speicherst oder vergleichst. - Ein
AudioContextim Zustand"suspended"kann das Gerät wechseln. Die Wiedergabe startet trotzdem erst nachresume().