use-user-media
Manage the lifecycle of a media stream from any asynchronous source.
| Package | @vizejs/composable/use-user-media |
| Own the source | vize lib pull composable:use-user-media |
| Runtime exports | useMediaStream, useUserMedia |
| Gzip budget | 3328 B |
Minimal setup
Use a Vue 3.5+ project with Vue SFC compilation configured (see Vite+ integration).
vp install @vizejs/composable
Import the entry directly. Call lifecycle-bound utilities inside <script setup> so cleanup follows the component scope; consult the runtime contract for this entry's SSR and hydration behavior.
import { useMediaStream, useUserMedia } from "@vizejs/composable/use-user-media";
Try it
Preview the camera
Start the camera on request and show its stream before a call.
What to observe: Turn on camera asks for permission and shows the preview; Turn off camera stops every track.
Pass constraints for resolution or devices; devices lists the available inputs. Every example renders a neutral message until it mounts, so server and client markup match, and then explains what to do when the browser lacks the API.
Compare the initial and interacted states


Copy the example
Save this complete SFC in your Vue project. Its public imports and source are the same ones executed in the preview.
<script setup lang="ts">
import { computed, watchEffect, useTemplateRef } from "vue";
import { useMounted } from "@vizejs/composable/use-mounted";
import { useUserMedia } from "@vizejs/composable/use-user-media";
const mounted = useMounted();
const camera = useTemplateRef<HTMLVideoElement>("camera");
const { supported, stream, status, start, stop } = useUserMedia({ constraints: { video: true } });
const live = computed(() => stream.value !== undefined);
watchEffect(() => {
if (camera.value) camera.value.srcObject = (stream.value as MediaStream | undefined) ?? null;
});
</script>
<template>
<div class="composable-example">
<p>Show a camera preview before a video call starts.</p>
<div class="example-actions">
<button type="button" :disabled="!mounted || !supported || live" @click="() => start()">
Turn on camera
</button>
<button type="button" :disabled="!live" @click="() => stop()">Turn off camera</button>
</div>
<video ref="camera" autoplay muted playsinline aria-label="Camera preview"></video>
<output aria-live="polite">{{
!mounted
? "Checking browser support…"
: supported
? `Camera: ${status}`
: "Camera access is not available in this browser."
}}</output>
</div>
</template>
Runtime contract
| Utility | Category | Stability | SSR | Hydration | Cleanup | Targets | Host globals | Uses |
|---|---|---|---|---|---|---|---|---|
useMediaStream |
media | experimental | deterministic-fallback | stable | caller, reactive-scope | web, desktop | window |
tryOnScopeDispose |
useUserMedia |
media | experimental | deterministic-fallback | caller-managed | caller, reactive-scope | web, desktop | window |
useMediaStream |
API
useMediaStream
Manage the lifecycle of a media stream from any asynchronous source. This is the engine behind useUserMedia and useDisplayMedia, and can wrap any other stream producer (canvas capture, WebRTC). Acquisition failures are classified into MediaStreamErrorCodes; the stream returns to "idle" once all of its tracks ended (device unplugged, the user stopped screen sharing). Latest-wins: a stream that resolves after a newer request or a stop is stopped immediately. All tracks are stopped when the owning reactive scope stops. Server rendering: without a browser window a missing source keeps the status "idle" (no error), so server markup matches the first client render.
function useMediaStream<Constraints>( options: UseMediaStreamOptions<Constraints>, ): MediaStreamControls
const canvasStream = useMediaStream({
source: { request: async (fps: number) => canvas.captureStream(fps) },
constraints: 30,
});
useUserMedia
Access the camera and microphone with getUserMedia. Built on useMediaStream: reactive constraints (restarting an active stream when they change), enabled activation, classified failures such as "permission-denied", and latest-wins requests. With listDevices, devices follows devicechange. Tracks and listeners are released when the owning reactive scope stops. Server rendering: no device is touched; status is "idle", stream is undefined, and supported is false.
function useUserMedia(options: UseUserMediaOptions = {}): UserMediaControls
const camera = useUserMedia({ constraints: { video: true, audio: false } });
await camera.start();
video.srcObject = camera.stream.value;
Types
MediaStreamTrackLike
Minimal MediaStreamTrack.
| Member | Type | Description |
|---|---|---|
kind |
string |
"audio" or "video". |
readyState |
string |
"live" or "ended". |
stop |
() => void |
Stop the track and release its device. |
MediaStreamLike
Minimal MediaStream.
| Member | Type | Description |
|---|---|---|
getTracks |
() => readonly MediaStreamTrackLike[] |
Every track of the stream. |
MediaStreamSource
Anything that can asynchronously produce a media stream.
| Member | Type | Description |
|---|---|---|
request |
(constraints: Constraints) => Promise<MediaStreamLike> |
Acquire a stream; rejects with a DOMException on failure. |
MediaStreamFailure
Stream acquisition failure.
| Member | Type | Description |
|---|---|---|
code |
MediaStreamErrorCode |
Normalized reason. |
cause |
unknown |
Exact error thrown by the source, when one was thrown. |
UseMediaStreamOptions
Options for useMediaStream.
| Member | Type | Description |
|---|---|---|
source |
MaybeRefOrGetter<MediaStreamSource<Constraints> | null | undefined> |
Reactive stream source; null/undefined means unsupported. |
constraints |
MaybeRefOrGetter<Constraints> |
Reactive constraints passed to the source. |
enabled? |
MaybeRefOrGetter<boolean> |
Start while true, stop while false. |
autoSwitch? |
boolean |
Restart an active stream when the constraints change. |
MediaStreamControls
Reactive state and actions of a managed media stream.
| Member | Type | Description |
|---|---|---|
supported |
ComputedRef<boolean> |
Whether a stream source is available. |
stream |
Readonly<ShallowRef<MediaStreamLike | undefined>> |
The active stream, if any. |
status |
Readonly<Ref<MediaStreamStatus>> |
Lifecycle state. |
error |
Readonly<ShallowRef<MediaStreamFailure | undefined>> |
Most recent acquisition failure, cleared by the next request. |
start |
() => Promise<MediaStreamLike | undefined> |
Acquire a stream unless one is active. Overlapping calls resolve to the newest stream; superseded streams are stopped immediately. |
stop |
() => void |
Stop every track and release the stream. Repeated calls are safe. |
restart |
() => Promise<MediaStreamLike | undefined> |
Stop and acquire a fresh stream with the current constraints. |
MediaDeviceInfoLike
Minimal MediaDeviceInfo.
| Member | Type | Description |
|---|---|---|
deviceId |
string |
Device identifier. |
kind |
string |
"audioinput", "audiooutput", or "videoinput". |
label |
string |
Human-readable label (empty until permission is granted). |
groupId |
string |
Identifier shared by devices of one physical unit. |
UserMediaHost
Minimal MediaDevices consumed by useUserMedia.
| Member | Type | Description |
|---|---|---|
getUserMedia |
(constraints?: MediaStreamConstraints) => Promise<MediaStreamLike> |
Request camera/microphone access. |
enumerateDevices? |
() => Promise<readonly MediaDeviceInfoLike[]> |
List media devices. |
UseUserMediaOptions
Options for useUserMedia.
| Member | Type | Description |
|---|---|---|
constraints? |
MaybeRefOrGetter<MediaStreamConstraints> |
Reactive constraints for getUserMedia. |
enabled? |
MaybeRefOrGetter<boolean> |
Start while true, stop while false. |
autoSwitch? |
boolean |
Restart an active stream when the constraints change. |
listDevices? |
boolean |
Keep devices current via enumerateDevices and devicechange. |
host? |
MaybeRefOrGetter<UserMediaHost | null | undefined> |
MediaDevices capability for alternate runtimes and tests. |
UserMediaControls
Reactive state and actions returned by useUserMedia.
| Member | Type | Description |
|---|---|---|
supported |
ComputedRef<boolean> |
Whether a stream source is available. |
stream |
Readonly<ShallowRef<MediaStreamLike | undefined>> |
The active stream, if any. |
status |
Readonly<Ref<MediaStreamStatus>> |
Lifecycle state. |
error |
Readonly<ShallowRef<MediaStreamFailure | undefined>> |
Most recent acquisition failure, cleared by the next request. |
start |
() => Promise<MediaStreamLike | undefined> |
Acquire a stream unless one is active. Overlapping calls resolve to the newest stream; superseded streams are stopped immediately. |
stop |
() => void |
Stop every track and release the stream. Repeated calls are safe. |
restart |
() => Promise<MediaStreamLike | undefined> |
Stop and acquire a fresh stream with the current constraints. |
devices |
Readonly<ShallowRef<readonly MediaDeviceInfoLike[]>> |
Media devices, populated when listDevices is enabled. |
refreshDevices |
() => Promise<readonly MediaDeviceInfoLike[]> |
Re-enumerate media devices. |