Signatur
Beschreibung
Mit setSinkId() leitest du die gesamte Ausgabe eines AudioContext auf ein bestimmtes Audiogerät um. Standardmäßig spielt ein AudioContext über das Standardgerät des Systems ab. Mit dieser Methode kann eine Web-App, etwa ein Videokonferenz-Tool, eine DAW oder ein Spiel, dem Nutzer eine eigene Auswahl für die Audioausgabe anbieten.
Als Argument übergibst du entweder die deviceId eines Ausgabegeräts, das du über navigator.mediaDevices.enumerateDevices() mit kind === "audiooutput" ermittelt hast, oder einen leeren String "" für das Standardgerät. Eine Sonderform ist das Objekt { type: "none" }: Der Kontext verarbeitet das Audio dann weiter, gibt aber nichts an ein Gerät aus. Das ist praktisch für Analysen oder Aufnahmen ohne hörbare Wiedergabe.
Die Methode gibt ein Promise zurück. Es wird erfüllt, sobald der Wechsel abgeschlossen ist. Danach enthält AudioContext.sinkId den neuen Wert, und am Kontext wird das Ereignis sinkchange ausgelöst. Das Gerät kannst du auch schon beim Erzeugen festlegen, über die Option sinkId im Konstruktor new AudioContext({ sinkId }).
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $sinkId Pflicht | string | { type: "none" } | Die deviceId eines Audio-Ausgabegeräts aus enumerateDevices(), "" für das Standardgerät des Systems oder { type: "none" }, wenn das Audio verarbeitet, aber nicht hörbar ausgegeben werden soll. |
Rückgabewert
Promise, das nach dem erfolgreichen Gerätewechsel mit undefined erfüllt wird. Es wird mit einer DOMException abgelehnt: NotFoundError, wenn die ID zu keinem Gerät passt; NotAllowedError, wenn die Berechtigung fehlt oder die Permissions-Policy speaker-selection den Zugriff verbietet; InvalidAccessError, wenn der Zugriff auf das Gerät fehlschlägt.Beispiele
Ausgabegeräte auflisten und das erste externe Gerät wählen
const ctx = new AudioContext();
const switchToFirstOutput = async () => {
// Ohne Mikrofon-Freigabe liefern manche Browser keine Gerätenamen
await navigator.mediaDevices.getUserMedia({ audio: true });
const devices = await navigator.mediaDevices.enumerateDevices();
const outputs = devices.filter((d) => d.kind === 'audiooutput');
console.log(outputs.map((d) => d.label));
const target = outputs.find((d) => d.deviceId !== 'default');
if (target) {
await ctx.setSinkId(target.deviceId);
console.log('Neue Ausgabe:', ctx.sinkId);
}
};
switchToFirstOutput().catch(console.error);
Auswahlmenü für die Audioausgabe mit Fehlerbehandlung
const ctx = new AudioContext();
const select = document.querySelector('#output-select');
const fillSelect = async () => {
const devices = await navigator.mediaDevices.enumerateDevices();
select.replaceChildren(
...devices
.filter((d) => d.kind === 'audiooutput')
.map((d) => new Option(d.label || 'Unbenanntes Gerät', d.deviceId))
);
};
select.addEventListener('change', async () => {
if (!('setSinkId' in AudioContext.prototype)) {
alert('Gerätewahl wird von diesem Browser nicht unterstützt.');
return;
}
try {
await ctx.setSinkId(select.value);
} catch (err) {
if (err.name === 'NotFoundError') console.warn('Gerät nicht mehr vorhanden');
else if (err.name === 'NotAllowedError') console.warn('Keine Berechtigung');
else console.error(err);
}
});
// Liste aktualisieren, wenn Geräte an- oder abgesteckt werden
navigator.mediaDevices.addEventListener('devicechange', fillSelect);
fillSelect();
Stumm verarbeiten mit { type: "none" } und sinkchange abfangen
const ctx = new AudioContext();
ctx.addEventListener('sinkchange', () => {
// sinkId ist jetzt ein AudioSinkInfo-Objekt
console.log('Sink geändert:', typeof ctx.sinkId === 'object' ? ctx.sinkId.type : ctx.sinkId);
});
const analyser = ctx.createAnalyser();
const osc = ctx.createOscillator();
osc.connect(analyser).connect(ctx.destination);
osc.start();
// Audio weiter berechnen, aber nicht hörbar ausgeben
await ctx.setSinkId({ type: 'none' });
// Später zurück zum Standardgerät
await ctx.setSinkId('');
// Wichtig · Fallstricke
- Browser-Unterstützung: Chromium-Browser (Chrome, Edge, Opera) ab Version 110. Safari unterstützt die Methode nicht, Firefox nur experimentell. Prüfe die Verfügbarkeit daher immer vorher, etwa mit
'setSinkId' in AudioContext.prototype, und biete sonst eine Rückfalllösung an. - Sicherer Kontext und Berechtigungen: Die Methode funktioniert nur über HTTPS. In iframes muss die Permissions-Policy
speaker-selectionerlaubt sein, z. B. mit<iframe allow=\"speaker-selection\">. Sonst wird das Promise mitNotAllowedErrorabgelehnt. - Gerätenamen und IDs:
enumerateDevices()liefertlabelund oft auch sinnvolle IDs erst, wenn der Nutzer zuvor den Mikrofonzugriff (getUserMedia) erlaubt hat. Die IDs gelten pro Ursprung und können sich ändern, etwa nach dem Löschen von Cookies. Speichere sie also nicht dauerhaft, ohne sie beim nächsten Besuch erneut zu prüfen. - Abgesteckte Geräte: Wird das gewählte Gerät entfernt, schaltet der Browser meist auf das Standardgerät zurück. Beobachte deshalb
devicechangeundsinkchange, damit die Oberfläche aktuell bleibt. - Latenz: Ein Gerätewechsel kann das Audio kurz unterbrechen. Wechsle das Gerät möglichst nicht während kritischer Wiedergabe.
- Nicht verwechseln: Für
<audio>- und<video>-Elemente gibt es die eigene MethodeHTMLMediaElement.setSinkId(). Sie wird breiter unterstützt, auch von Firefox und Safari.AudioContext.setSinkId()betrifft dagegen nur Web-Audio-Graphen.