Audio Output and Sessions

Audio Output and Session Control

Two small APIs decide where a page's sound goes and how it mixes with the rest of the device. HTMLMediaElement.setSinkId(deviceId) moves an element's playback to a chosen speaker or headset, and AudioContext.setSinkId() (Chrome 110 1 ) does the same for a Web Audio graph (Web Audio), firing sinkchange when the route changes. IDs come from enumerateDevices(), but a page never granted microphone access sees one anonymous audiooutput entry with an empty ID and label, so ask for a stream first. Headless Chrome 152 printed:

Listing audio outputs and routing an element to one of themJavaScript
const all = await navigator.mediaDevices.enumerateDevices();
const outs = all.filter((d) => d.kind === 'audiooutput');
outs.forEach((d) => console.log(d.deviceId.slice(0, 14), `"${d.label}"`));
const audio = document.createElement('audio');
await audio.setSinkId(outs[0].deviceId);      // NotAllowedError if speaker-selection is blocked
Output
default "Default - Speakers (2- High Definition Audio Device)"
8e1b8565ca064a "Digital Output (2- High Definition Audio Device)"

setSinkId() is Chrome 49, Firefox 116 555 and Safari 18.4 10 , desktop only — Chrome for Android cannot switch outputs — and the speaker-selection permissions policy can block it (Permissions Policy). Firefox alone offers selectAudioOutput(), a native picker that grants one device; elsewhere you build the menu yourself.

The Audio Session API handles mixing: navigator.audioSession.type set to playback pauses other apps' media, transient plays a notification over them, transient-solo interrupts them for a voice prompt, ambient mixes freely and obeys the mute switch, and play-and-record covers calls. Safari 16.4 and later only, so treat it as an enhancement alongside Media Session (Media Session).