Devices
Listing devices
Section titled “Listing devices”const { getMediaDevices, audioInputDevices, videoInputDevices, audioOutputDevices } = useMediaStream();
useEffect(() => { getMediaDevices();}, [getMediaDevices]);getMediaDevices() returns the full list and also populates devices, plus three arrays split by
kind:
MediaDeviceInfo.kind |
|
|---|---|
audioInputDevices |
audioinput — microphones |
audioOutputDevices |
audiooutput — speakers |
videoInputDevices |
videoinput — cameras |
If you only need the microphone list, ask for audio alone so the camera never lights up:
useMediaStream({ mediaDeviceConstraints: { video: false } });What’s currently selected
Section titled “What’s currently selected”The selected* values read the live track’s settings, which is what the browser actually gave
you — not what you asked for:
const { selectedAudioTrackDeviceId, selectedVideoTrackDeviceId, selectedVideoTrackDeviceWidth, selectedVideoTrackDeviceHeight, selectedVideoTrackDeviceAspectRatio,} = useMediaStream();Ask for 1280×720 on a webcam that can’t do it and you’ll get something else — these tell you what.
They’re undefined while no stream is running.
Switching camera
Section titled “Switching camera”function CameraPicker() { const { videoInputDevices, selectedVideoTrackDeviceId, updateMediaDeviceConstraints } = useMediaStream();
return ( <select value={selectedVideoTrackDeviceId ?? ''} onChange={(e) => updateMediaDeviceConstraints({ constraints: { video: { deviceId: e.target.value } }, resetStream: true, }) } > {videoInputDevices.map((d) => ( <option key={d.deviceId} value={d.deviceId}> {d.label || d.deviceId} </option> ))} </select> );}resetStream: true is what makes the switch take effect: the current stream is released and a new
one acquired with the merged constraints. Without it the constraints are recorded but the live
stream keeps running on the old device, which is what you want if you’re setting up before
starting.
isStreaming is preserved across the swap, so a stream that was running stays running.
Front and back camera on mobile
Section titled “Front and back camera on mobile”Phones expose facingMode rather than useful device labels, so prefer it over deviceId:
updateMediaDeviceConstraints({ constraints: { video: { facingMode: 'environment' } }, // rear camera resetStream: true,});'user' is the selfie camera and the default.
Speakers
Section titled “Speakers”audioOutputDevices is listed for completeness, but output can’t be chosen through
getUserMedia — it isn’t an input. To route audio to a specific speaker, use
HTMLMediaElement.setSinkId()
on the element itself, passing the deviceId from this list.
Devices appearing and disappearing
Section titled “Devices appearing and disappearing”The arrays don’t refresh by themselves. To follow devices being plugged in or removed, listen to the browser event and re-run the query:
useEffect(() => { const onChange = () => getMediaDevices(); navigator.mediaDevices?.addEventListener('devicechange', onChange); return () => navigator.mediaDevices?.removeEventListener('devicechange', onChange);}, [getMediaDevices]);The three arrays keep a stable identity between renders, so using them as effect dependencies is safe and won’t loop.