v144 · webrtc · demo
Multi-Source Switcher
Enumerate every camera on the device and switch the live stream source mid-call — no page reload, no permission prompt loop. This is the real-time device-switching use case that a future <usermedia> element would handle declaratively.
Origin trial / flag
The native
<usermedia> element is behind chrome://flags/#enable-experimental-web-platform-features in Chrome 144.
This demo uses navigator.mediaDevices.getUserMedia() + enumerateDevices() so
device switching works in every browser. The <usermedia> support badge below
shows whether the element is registered in your current build.
<usermedia> element:
checking…
click “start camera” to begin
available cameras
no cameras enumerated yet — click “start camera” first (permission required for device labels)
active track settings
| resolution | — |
| frameRate | — |
| facingMode | — |
| deviceId | — |
| displayedAt | — |
the API
// 1. enumerate video inputs (requires permission for labels)
const devices = await navigator.mediaDevices.enumerateDevices();
const cameras = devices.filter(d => d.kind === 'videoinput');
// 2. switch to a specific device
async function switchTo(deviceId) {
if (currentStream) currentStream.getTracks().forEach(t => t.stop());
currentStream = await navigator.mediaDevices.getUserMedia({
video: {
deviceId: { exact: deviceId },
width: { ideal: 1280 },
height: { ideal: 720 }
}
});
videoEl.srcObject = currentStream;
}
// 3. inspect track settings after stream is live
video.onloadedmetadata = () => {
const track = currentStream.getVideoTracks()[0];
const s = track.getSettings();
console.log(s.width, s.height, s.frameRate, s.facingMode, s.deviceId);
};
// 4. react to device changes (plug/unplug)
navigator.mediaDevices.addEventListener('devicechange', enumerate);
// Future declarative form (<usermedia> element):
// <usermedia kind="video" deviceid="abc123">Switch camera</usermedia>
how it works
The first getUserMedia call grants permission and unlocks device labels. After that, enumerateDevices() returns human-readable names instead of empty strings. Switching cameras re-calls getUserMedia with deviceId: { exact: id } — the constraint tells the browser exactly which physical device to open. The old stream is stopped first to release the hardware lock. The devicechange event fires when cameras are plugged in or out, triggering a fresh enumeration.
see also
- <usermedia> Element — basic declarative capture
- Microphone Meter — audio level analysis
- Permission UX Compare — getUserMedia vs <usermedia>
- ChromeStatus entry