demo · v136
Multi-track Sink Switcher
A mixing-desk metaphor for setPreferredSinkId(): one click on a frame-wide sink choice routes every audio element on the page to the chosen output device. Each track also exposes its per-element setSinkId() so you can see when a per-element override beats the frame default.
Note:
navigator.mediaDevices.setPreferredSinkId is not detected. The per-element setSinkId() path still works in Chrome on desktop. Make sure microphone/camera permission has been granted at least once — sink labels are blank until then.
state: not initialised
what the demo is testing
- Calling
navigator.mediaDevices.setPreferredSinkId(id)sets a frame-wide default that flows to every audio element with nosinkIdset. - Calling
audio.setSinkId(id)directly still wins for that specific element. - Reading
audio.sinkIdafter either call shows what's actually playing. - Setting the frame default to
''falls back to the user agent default.
the code
// 1. Get device IDs (requires a prior getUserMedia grant to see labels).
const devs = await navigator.mediaDevices.enumerateDevices();
const sinks = devs.filter(d => d.kind === 'audiooutput');
// 2. Set the frame default. Applies to every <audio>/<video> and AudioContext
// in this top-level frame AND its child iframes.
await navigator.mediaDevices.setPreferredSinkId(sinks[1].deviceId);
// 3. Per-element override still beats the frame default.
await audio.setSinkId(sinks[2].deviceId);
console.log(audio.sinkId); // sinks[2].deviceId
see also
- setPreferredSinkId — the headline persistence demo
- Iframe inherits sink — cross-origin frame inheritance
- setPreferredSinkId feature index
- ChromeStatus entry
- Audio Output Devices API spec