@solid-primitives/mediastream
Reactive primitives for working with MediaStream — microphones, cameras, and screen capture.
Installation
npm install @solid-primitives/mediastream
# or
yarn add @solid-primitives/mediastream
# or
pnpm add @solid-primitives/mediastream
Primitives
createStream
Creates a reactive accessor for a MediaStream from a camera or microphone.
const [stream, { mute, stop }] = createStream(streamSource);
Parameters
streamSource—MediaDeviceInfo | MediaStreamConstraints | Accessor<...> | FalsyValue
Returns
stream()—Accessor<MediaStream | undefined>— the current stream (undefined while loading or stopped)mute(muted?)— mutes the stream; passfalseto unmutestop()— stops the stream immediately
The stream stops automatically when the reactive owner is disposed. Wrap in <Loading> to handle the loading state:
import { Loading } from "@solidjs/web";
const [stream] = createStream({ video: true });
<Loading fallback={<p>Requesting camera...</p>}>
<video
ref={el =>
createEffect(stream, s => {
el.srcObject = s ?? null;
})
}
autoplay
/>
</Loading>;
createScreen
Creates a reactive accessor for a display capture stream (screen, window, or browser tab).
const [stream, { mute, stop }] = createScreen(screenSource);
Parameters
screenSource—DisplayMediaStreamConstraints | undefined | Accessor<DisplayMediaStreamConstraints | undefined>
Same controls as createStream but uses getDisplayMedia instead of getUserMedia. The stream stops automatically when the reactive owner is disposed.
const [stream] = createScreen({ video: true });
<Loading fallback={<p>Requesting screen capture...</p>}>
<video
ref={el =>
createEffect(stream, s => {
el.srcObject = s ?? null;
})
}
autoplay
/>
</Loading>;
createAmplitudeStream
Creates a reactive signal with the RMS amplitude (0–100) from a microphone device.
const [amplitude, { stream, stop }] = createAmplitudeStream(streamSource?);
Parameters
streamSource?— same ascreateStream(optional)
Returns
amplitude()—Accessor<number>— value between 0 and 100stream—Accessor<MediaStream | undefined>— the underlying streamstop()— stops the amplitude measurement and underlying stream
const [audioConstraints, setAudioConstraints] = createSignal<MediaStreamConstraints>();
const [level] = createAmplitudeStream(audioConstraints);
<Show
when={audioConstraints()}
fallback={<button onClick={() => setAudioConstraints({ audio: true })}>Start</button>}
>
<meter min="0" max="100" value={level()} />
</Show>;
createAmplitudeFromStream
Creates an amplitude signal from an existing stream accessor.
const [amplitude, stop] = createAmplitudeFromStream(stream);
Parameters
stream—MaybeAccessor<MediaStream | undefined>
Returns
amplitude()—Accessor<number>— value between 0 and 100stop()— stops the amplitude measurement
The measurement stops automatically when the reactive owner is disposed.
createMediaPermissionRequest
Requests media permissions from the user by briefly opening then immediately stopping a stream.
createMediaPermissionRequest(source?);
Parameters
source?—'audio' | 'video' | MediaStreamConstraints— defaults to both audio and video
Returns a Promise<void> that resolves when permission is granted, and rejects if the user denies permission or navigator.mediaDevices.getUserMedia fails for any other reason — forwarding the rejection directly from getUserMedia.
// Request both microphone and camera permissions
await createMediaPermissionRequest();
// Request only microphone permission
await createMediaPermissionRequest("audio");
Use createPermission from @solid-primitives/permission to reactively observe the resulting permission state.
Breaking Changes from @solid-primitives/stream
This package replaces @solid-primitives/stream with full Solid.js v2 compatibility.
createStream/createScreen: return type changed from[Resource<MediaStream>, ResourceActions & { stop, mute }]to[Accessor<MediaStream | undefined>, { stop, mute }]. Themutateandrefetchcontrols are removed; reactivity is driven by the source accessor directly.createAmplitudeStream: return type simplified — second element is now{ stream, stop }(nomutate/refetch).isServer: now imported from@solidjs/webinternally.- Async loading state: use
<Loading>from@solidjs/webinstead of inspectingstream.loading. - Error handling: wrap in
<Errored>from@solidjs/webinstead of inspectingstream.error.
Changelog
See CHANGELOG.md