Start · Sprachen · JavaScript · Referenz · AudioContext.setSinkId()

AudioContext.setSinkId()

Methode

Legt asynchron das Audio-Ausgabegerät (z. B. Kopfhörer oder externe Lautsprecher) fest, über das ein <code>AudioContext</code> seinen Ton ausgibt.

seit JavaScript Chrome/Edge 110+; nicht in Safari; Firefox nur exp Kategorie: webapi

Signatur

AudioContext.prototype.setSinkId(sinkId)

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

Typ
Promise<undefined>
Beschreibung
Ein 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);
["Standard – Lautsprecher", "Kopfhörer (USB)"] Neue Ausgabe: 3f2a…e91

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('');
Sink geändert: none Sink geändert:

// 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-selection erlaubt sein, z. B. mit <iframe allow=\"speaker-selection\">. Sonst wird das Promise mit NotAllowedError abgelehnt.
  • Gerätenamen und IDs: enumerateDevices() liefert label und 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 devicechange und sinkchange, 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 Methode HTMLMediaElement.setSinkId(). Sie wird breiter unterstützt, auch von Firefox und Safari. AudioContext.setSinkId() betrifft dagegen nur Web-Audio-Graphen.