demo · v133
WebAudio + media element routing
A WebAudio oscillator, a sample player, and an HTML <audio> sharing one preferred sink. Switch sinks once and every audio renderer in the document follows — without rebuilding the graph or per-element setSinkId.
setPreferredSinkId on navigator.mediaDevices. Chrome 133+ required.1 · WebAudio oscillator
2 · sample player (decoded buffer)
3 · HTML <audio> element
All three sources are routed through the document-wide preferred sink. No per-source plumbing required.
why a document-level preference matters
Before setPreferredSinkId, every audio renderer had to be addressed individually: each <audio> got a setSinkId, each AudioContext needed to be constructed with { sinkId } (or its sink replaced via AudioContext.setSinkId). Adding a new renderer halfway through a session meant remembering to apply the right sink. navigator.mediaDevices.setPreferredSinkId(id) now sets the default for the whole document — cross-origin iframes included — so renderers can be created without thinking about routing, and switching devices is one call away.
const sinkId = await chooseDevice();
await navigator.mediaDevices.setPreferredSinkId(sinkId);
// these all inherit the preference, no per-renderer wiring:
new AudioContext();
new Audio(url).play();
document.querySelector("iframe").src = "/embedded-player";