# 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

```ts
import { useMediaRecorder } from '@vincent.ri/react-tils'
// or only this hook
import { useMediaRecorder } from '@vincent.ri/react-tils/useMediaRecorder'
```

## Usage

```ts
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>
```

## 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

```ts
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

```ts
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

Works in all modern browsers.

- Browsers record different formats (Safari records MP4, others WebM); the hook picks one the browser supports and reports it as `mimeType`.

## Coming from another library?

Other libraries call this `useRecorder`, `useAudioRecorder`, `react-media-recorder`.

---

698 B minified and brotlied
Source: https://github.com/vincentri/react-tils/blob/main/src/useMediaRecorder.ts
Docs page: https://vincentri.github.io/react-tils/hooks/useMediaRecorder/
Previous: [useUserMedia](https://vincentri.github.io/react-tils/hooks/useUserMedia.md)
Next: [useSpeechSynthesis](https://vincentri.github.io/react-tils/hooks/useSpeechSynthesis.md)
