react-media-manager
v0.1.1
Published
Production-ready React hooks for managing media devices.
Maintainers
Readme
react-media-manager
Production-ready React hooks for cameras, microphones, speakers, permissions, device changes, and recording. The package is SSR-safe, tree-shakeable, TypeScript-first, and built for React 18+ applications across Next.js, Vite, CRA, Remix, and plain React setups.
Features
- Camera, microphone, and speaker device enumeration
- Stream lifecycle management with start, stop, pause, resume, mute, and unmute flows
- Permission querying and permission request helpers
- Automatic device-change detection
- Audio output switching through
setSinkIdwhen supported - Optional media recording hook
- Human-readable normalized media errors
- TypeScript declarations for all public hooks and device models
Installation
npm install react-media-managerPeer dependencies:
react >= 18react-dom >= 18
Quick Start
import { useCamera } from 'react-media-manager';
export function CameraPreview() {
const { cameras, currentCamera, stream, isActive, error, start, stop, switchCamera } = useCamera();
return (
<div>
<button onClick={() => void start()} disabled={isActive}>
Start camera
</button>
<button onClick={stop} disabled={!isActive}>
Stop camera
</button>
<select
value={currentCamera?.deviceId ?? ''}
onChange={(event) => void switchCamera(event.target.value)}
>
{cameras.map((camera) => (
<option key={camera.deviceId} value={camera.deviceId}>
{camera.label || camera.deviceId}
</option>
))}
</select>
{stream && <video autoPlay muted playsInline ref={(node) => node && (node.srcObject = stream)} />}
{error && <p>{error.message}</p>}
</div>
);
}API Overview
useCamera(options?)
Returns camera devices, the active stream, camera status, permission state, and camera controls.
const {
cameras,
currentCamera,
stream,
isActive,
isLoading,
isPaused,
permission,
status,
error,
start,
stop,
pause,
resume,
switchCamera,
refreshDevices,
refresh,
destroy,
} = useCamera();useMicrophone(options?)
Returns microphone devices, audio stream state, mute state, and live volume level monitoring when supported.
useSpeaker(target)
Returns output devices and a switchSpeaker helper for HTMLMediaElement.setSinkId capable browsers.
usePermissions()
Returns live camera and microphone permission state plus requestCamera, requestMicrophone, and requestAll helpers.
useMediaDevices(options?)
Returns grouped device lists and a refresh method.
useDeviceChange()
Returns refreshed devices plus changeCount and lastChangeAt each time navigator.mediaDevices.devicechange fires.
useMediaRecorder()
Returns recorder lifecycle helpers, chunk data, final Blob, object URL, and download support.
MediaProvider
Provides shared defaults:
<MediaProvider
value={{
autoRefreshOnDeviceChange: true,
cameraConstraints: { width: 1280, height: 720 },
microphoneConstraints: { echoCancellation: true },
monitorMicrophoneVolume: true,
}}
>
<App />
</MediaProvider>TypeScript
Public types include:
CameraDeviceMicrophoneDeviceSpeakerDeviceMediaPermissionStateMediaErrorMediaConstraints
Browser Support
- Chrome: supported
- Edge: supported
- Firefox: supported, with browser-specific output-device limitations
- Safari: supported for core camera and microphone hooks, with limited output-device support
- Brave: supported
The library degrades gracefully when MediaDevices, Permissions, MediaRecorder, or setSinkId are not available.
Errors
Errors are normalized into a consistent shape:
type MediaError = {
code:
| 'abort'
| 'browser-not-supported'
| 'device-in-use'
| 'device-not-found'
| 'invalid-state'
| 'not-allowed'
| 'not-readable'
| 'overconstrained'
| 'permission-denied'
| 'permission-query-failed'
| 'recorder-not-supported'
| 'speaker-not-supported'
| 'unknown';
message: string;
cause?: unknown;
name?: string;
};Development
npm install
npm run build
npm testCurrent local validation:
- Build: passes with
tsup - Tests: 16 passing
- Coverage: 90.87% statements, 90.87% lines, 91.2% functions
Examples and Docs
- JavaScript example:
examples/js-example/App.jsx - TypeScript example:
examples/ts-example/App.tsx - Next.js example notes:
docs/nextjs.md - Troubleshooting and FAQ:
docs/troubleshooting.md
