useUserMedia
Reactive wrapper around the MediaDevices.getUserMedia() API. Provides start/stop/restart controls and exposes the media stream as an observable.
Access the camera via getUserMedia. Click Start to begin streaming.
import { const useUserMedia: (options?: DeepMaybeObservable<UseUserMediaOptions>) => UseUserMediaReturn
useUserMedia } from "@usels/web";
function function CameraFeed(): JSX.Element
CameraFeed() { const { const isSupported$: ReadonlyObservable<boolean>
isSupported$, const stream$: ReadonlyObservable<OpaqueObject<MediaStream> | null>
Current media stream
stream$, const enabled$: ReadonlyObservable<boolean>
Whether stream is currently active
enabled$, const start: () => Promise<MediaStream>
Start the media stream. Throws if getUserMedia fails.
start, const stop: () => void
Stop the media stream
stop } = function useUserMedia(options?: DeepMaybeObservable<UseUserMediaOptions>): UseUserMediaReturn
Framework-agnostic reactive wrapper around
MediaDevices.getUserMedia().
Exposes the active MediaStream as an observable with start() / stop() /
restart() controls. Constraints are read at each start() call, so
reactive updates take effect on the next stream acquisition. Cleanup
(stopping all tracks) is registered via onMount so it fires on unmount.
useUserMedia({ constraints: { audio: boolean; video: boolean;}
constraints: { audio: boolean
audio: false, video: boolean
video: true }, });
return ( <JSX.IntrinsicElements.div: DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>
div> <JSX.IntrinsicElements.p: DetailedHTMLProps<HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>
p>Supported: {const isSupported$: ReadonlyObservable<boolean>
isSupported$.ImmutableObservableBase<boolean>.get(trackingType?: TrackingType | GetOptions): {}
get() ? "Yes" : "No"}</JSX.IntrinsicElements.p: DetailedHTMLProps<HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>
p> <JSX.IntrinsicElements.p: DetailedHTMLProps<HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>
p>Streaming: {const enabled$: ReadonlyObservable<boolean>
Whether stream is currently active
enabled$.ImmutableObservableBase<boolean>.get(trackingType?: TrackingType | GetOptions): {}
get() ? "Yes" : "No"}</JSX.IntrinsicElements.p: DetailedHTMLProps<HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>
p> <JSX.IntrinsicElements.button: DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>
button DOMAttributes<HTMLButtonElement>.onClick?: MouseEventHandler<HTMLButtonElement> | undefined
onClick={() => const start: () => Promise<MediaStream>
Start the media stream. Throws if getUserMedia fails.
start()}>Start</JSX.IntrinsicElements.button: DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>
button> <JSX.IntrinsicElements.button: DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>
button DOMAttributes<HTMLButtonElement>.onClick?: MouseEventHandler<HTMLButtonElement> | undefined
onClick={() => const stop: () => void
Stop the media stream
stop()}>Stop</JSX.IntrinsicElements.button: DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>
button> </JSX.IntrinsicElements.div: DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>
div> );}import { createUserMedia } from "@usels/web";
function CameraFeed() { "use scope"; const { isSupported$, stream$, enabled$, start, stop } = createUserMedia({ constraints: { audio: false, video: true }, });
return ( <div> <p>Supported: {isSupported$.get() ? "Yes" : "No"}</p> <p>Streaming: {enabled$.get() ? "Yes" : "No"}</p> <button onClick={() => start()}>Start</button> <button onClick={() => stop()}>Stop</button> </div> );}Auto-start on mount
Section titled “Auto-start on mount”// @noErrorsimport { useUserMedia } from "@usels/web";
function AutoCamera() { const { stream$, stop } = useUserMedia({ constraints: { audio: false, video: true }, immediate: true, });
// Stream starts automatically on mount // Stops automatically on unmount return <button onClick={() => stop()}>Stop</button>;}Audio-only capture
Section titled “Audio-only capture”// @noErrorsimport { useUserMedia } from "@usels/web";
function Microphone() { const { stream$, start, stop, enabled$ } = useUserMedia({ constraints: { audio: true, video: false }, });
return ( <button onClick={() => (enabled$.get() ? stop() : start())}> {enabled$.get() ? "Stop Recording" : "Start Recording"} </button> );}Reactive options
Section titled “Reactive options”Options can be passed as plain values, per-field Observables, or a single Observable<UseUserMediaOptions>. constraints are read at each start() / restart() call.
import { observable } from "@usels/core";import { useUserMedia } from "@usels/web";
const constraints$ = observable<MediaStreamConstraints>({ audio: false, video: true });
const { start, restart } = useUserMedia({ constraints: constraints$ });
// Later: switch to audio+video reactivelyconstraints$.set({ audio: true, video: true });restart(); // uses updated constraintsoptions is DeepMaybeObservable. Each option field can be a plain value or an Observable. constraints are read at each start() / restart() call time. immediate is read at mount-time.
Parameters
Section titled “Parameters”| Parameter | Type | Description |
|---|---|---|
options | UseUserMediaOptions (optional) | - |
UseUserMediaOptions
Section titled “UseUserMediaOptions”Returns
Section titled “Returns”UseUserMediaReturn
| Name | Type | Description |
|---|---|---|
stream$ | ReadonlyObservable<OpaqueObject<MediaStream> | null> | Current media stream |
enabled$ | ReadonlyObservable<boolean> | Whether stream is currently active |
start | () => Promise<MediaStream> | Start the media stream. Throws if getUserMedia fails. |
stop | () => void | Stop the media stream |
restart | () => Promise<MediaStream> | Restart the media stream. Throws if getUserMedia fails. |
isSupported$ | ReadonlyObservable<boolean> | - |