useUserMedia
Browser & deviceCamera and microphone streams — getUserMedia lifecycle, device switching, torch, and a teardown you can rely on.
Install
$ npm install @usefy/use-user-mediaQuick start
import { useUserMedia } from "@usefy/use-user-media";
function CameraPreview() {
const camera = useUserMedia({ facingMode: "environment" });
if (camera.status === "unsupported") return <p>No camera here.</p>;
if (camera.status === "denied") return <p>{camera.error?.message}</p>;
return camera.stream ? (
<video
ref={(element) => {
if (element) element.srcObject = camera.stream;
}}
autoPlay
playsInline
muted
/>
) : (
<button onClick={camera.start}>Start camera</button>
);
}API reference
useUserMedia(options?)
Options
| Option | Type | Default | Description |
|---|---|---|---|
constraints | MediaStreamConstraints | { video: true } | What to request |
autoStart | boolean | false | Acquire on mount |
facingMode | "user" | "environment" | — | Preferred camera; merged as a preference, not exact |
deviceId | string | — | Open one specific device (as exact) |
onStream | (stream) => void | — | Called whenever a new stream becomes available |
onError | (error: UserMediaError) => void | — | Called when acquisition fails |
Changing facingMode or deviceId while a stream is live re-acquires automatically — the usual way to build a "flip camera" button.
Returns
| Field | Type | Description |
|---|---|---|
stream | MediaStream | null | The live stream |
status | UserMediaStatus | idle · prompting · granted · denied · unsupported · error |
error | UserMediaError | null | Cleared by a successful start() |
isSupported | boolean | Whether this environment can open a stream at all |
start() | () => Promise<MediaStream | null> | Request (or re-request) a stream |
stop() | () => void | Stop every track. Safe to call repeatedly |
devices | MediaDeviceInfo[] | Video inputs — empty until permission is granted once |
activeDeviceId | string | null | The device the current stream came from |
selectDevice(id) | (id) => Promise<MediaStream | null> | Open a specific device |
switchDevice() | () => Promise<MediaStream | null> | Cycle to the next camera |
isTorchSupported | boolean | Whether the active camera reports a torch |
torch | boolean | Current torch state |
setTorch(on) | (on) => Promise<boolean> | Resolves false if the camera refused |
UserMediaError
{ name: "UserMediaError", reason, message, cause } where reason is one of denied · not-found · in-use · over-constrained · unsupported · unknown.
Helpers
isUserMediaSupported(), isEnumerationSupported(), stopStream(), supportsTorch(), activeDeviceIdOf(), withVideoPreferences(), toUserMediaError().
Go deeper
This page is the quick reference. For every example, prop, and edge case, read the full README — or open Storybook to change props live.