All hooks / Browser APIs
useMediaRecorder
Records a MediaStream (microphone, camera, or screen) into a file. Pair it with useUserMedia for the stream.
Picks a format the browser can actually record: Chrome and Firefox record WebM, Safari records MP4, so a hardcoded audio/webm fails in Safari. stop() resolves with the finished Blob once the recorder has delivered its last chunk. Recording stops on unmount and when stream changes; the stream itself is left running, so stop its tracks yourself (useUserMedia does that on unmount).
Import
import { useMediaRecorder } from '@vincent.ri/react-tils'
// or only this hook
import { useMediaRecorder } from '@vincent.ri/react-tils/useMediaRecorder'Usage
const [on, setOn] = useState(false)
const { stream } = useUserMedia({ audio: true }, { enabled: on })
const recorder = useMediaRecorder(stream)
const finish = async () => {
const blob = await recorder.stop()
if (blob) await transcribe(new File([blob], 'note', { type: blob.type }))
setOn(false)
}
return recorder.recording
? <button onClick={finish}>Stop</button>
: <button onClick={() => (stream ? recorder.start() : setOn(true))}>{stream ? 'Record' : 'Allow microphone'}</button>Live demo
Record a few seconds from your microphone, then play it back.
When to use it
Voice notes, voice input for an AI chat (record, then send to a transcription API), recording a video message, or a screen recording.
When not to
You want live speech-to-text in the browser; that is the Web Speech API. To only show a camera or microphone preview, use useUserMedia alone.
API
function useMediaRecorder(stream: MediaStream | null, options?: MediaRecorderOptions): MediaRecorderState| Parameter | Description |
|---|---|
stream | The stream to record, or null until it's ready. |
options | mimeTypes: formats to try, in order. Optional. |
Returns { supported, recording, mimeType, blob, error, start, stop }.
Types
export type MediaRecorderOptions = {
/** Formats to try, in order; the first one the browser can record is used. Default: Opus in WebM, then MP4 (Safari), then Ogg, for audio; VP9/VP8 WebM, then MP4, for video. */
mimeTypes?: string[];
};
export type MediaRecorderState = {
/** `false` on the server, during hydration, and in browsers without `MediaRecorder`. */
supported: boolean;
recording: boolean;
/** The format actually recorded, e.g. `audio/webm;codecs=opus` or `audio/mp4`. Use it for the file extension and upload. */
mimeType: string | null;
/** The last finished recording. */
blob: Blob | null;
error: Error | null;
/** Start recording `stream`. Does nothing while recording or without a stream. */
start: () => void;
/** Stop and resolve with the finished recording, including its last chunk. */
stop: () => Promise<Blob | null>;
};Browser support
| Uses | Chrome | Edge | Firefox | Safari | Chrome Android | Safari iOS |
|---|---|---|---|---|---|---|
| MediaRecorderWidely available | 47+ | 79+ | 25+ | 14.1+ | 47+ | 14+ |
- Browsers record different formats (Safari records MP4, others WebM); the hook picks one the browser supports and reports it as
mimeType.
First version with support, from MDN's compatibility data (web-features 3.42.0, @mdn/browser-compat-data 8.1.5).
Coming from another library?
Other libraries call this useRecorder, useAudioRecorder, react-media-recorder.