# Audio Recorder

Enable audio recording on `MessageInput` to record voice messages:

```tsx
<MessageInput audioRecordingEnabled />
```

Once enabled, `MessageInput` renders `StartRecordingAudioButton`.

![Message composer with the recording button](@chat-sdk/react/v13/_assets/audio-recorder-start-recording-button.png)

## Best Practices

- Request microphone access only when users opt in to recording.
- Use MP3 encoding when file size or bandwidth is a concern.
- Keep recording UI minimal so users can start/stop quickly.
- Consider `asyncMessagesMultiSendEnabled` for multi-attachment workflows.
- Handle permission-denied states with clear recovery guidance.

You can replace `StartRecordingAudioButton` via `Channel` context:

```tsx
<Channel StartRecordingAudioButton={CustomComponent}>
```

Clicking the recording button swaps the composer UI for the `AudioRecorder` UI.

![AudioRecorder UI with recording in progress](@chat-sdk/react/v13/_assets/audio-recorder-recording.png)

You can replace the default `AudioRecorder` via `Channel` context:

```tsx
<Channel AudioRecorder={CustomComponent}>
```

## Browser permissions

Microphone permission changes are observed. If permission is `'denied'` when the user starts recording, the `RecordingPermissionDeniedNotification` dialog is shown.

![RecordingPermissionDeniedNotification rendered when microphone permission is denied](@chat-sdk/react/v13/_assets/audio-recorder-permission-denied-notification.png)

You can customize that dialog via `Channel` context:

```tsx
<Channel RecordingPermissionDeniedNotification={CustomComponent}>
```

## Custom encoding

By default, recordings are encoded as `audio/wav`. To reduce size, you can use the MP3 encoder based on [`lamejs`](https://github.com/gideonstele/lamejs):

1. Install `@breezystack/lamejs` (a peer dependency of `stream-chat-react`).

```shell
npm install @breezystack/lamejs
```

```shell
yarn add @breezystack/lamejs
```

2. Import the MP3 encoder as a plugin:

```tsx
import { useMemo } from "react";
import { MessageInput } from "stream-chat-react";
import { encodeToMp3 } from "stream-chat-react/mp3-encoder";

const Component = () => {
  /**
   See why memoizing props matters:
   - https://www.epicreact.dev/memoization-and-react
   - https://react.dev/reference/react/useMemo
  */
  const audioRecordingConfig = useMemo(
    () => ({ transcoderConfig: { encoder: encodeToMp3 } }),
    [],
  );
  return <MessageInput focus audioRecordingConfig={audioRecordingConfig} />;
};
```

## Audio recorder states

`AudioRecorder` switches between these states:

**1. Recording state**

The recording can be paused or stopped.

![AudioRecorder UI in recording state](@chat-sdk/react/v13/_assets/audio-recorder-recording.png)

**2. Paused state**

The recording can be stopped or resumed.

![AudioRecorder UI paused state](@chat-sdk/react/v13/_assets/audio-recorder-paused.png)

**3. Stopped state**

The recording can be played back before it is sent.

![AudioRecorder UI stopped state](@chat-sdk/react/v13/_assets/audio-recorder-stopped.png)

At any time, the user can cancel and return to the composer via the bin icon.

## The message sending behavior

The recording uploads when recording is completed (stop + confirm).

Sending behavior for the recording attachment is controlled by `asyncMessagesMultiSendEnabled` on `MessageInput`.

```tsx
<MessageInput asyncMessagesMultiSendEnabled audioRecordingEnabled />
```

Behavior by `asyncMessagesMultiSendEnabled`:

| `asyncMessagesMultiSendEnabled` value | Impact                                                                                              |
| ------------------------------------- | --------------------------------------------------------------------------------------------------- |
| `false` (default)                     | Sends immediately after upload; submits a no-text message with a single voice recording attachment. |
| `true`                                | Sends when the user clicks `SendMessage`.                                                           |

<admonition type="note">

Enabling `asyncMessagesMultiSendEnabled` lets users record multiple voice messages or add text/attachments before sending.

</admonition>

## Audio recorder controller

Components consuming `MessageInputContext` can access the recording state via `recordingController`:

```tsx
import { useMessageInputContext } from "stream-chat-react";

const Component = () => {
  const {
    recordingController: {
      completeRecording,
      permissionState,
      recorder,
      recording,
      recordingState,
    },
  } = useMessageInputContext();
};
```

The controller exposes the following API:

| Property            | Description                                                                                                                               |
| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `completeRecording` | Stops recording, uploads it, and submits the message if `asyncMessagesMultiSendEnabled` is disabled.                                      |
| `permissionState`   | One of the values for microphone permission: `'granted'`, `'prompt'`, `'denied'`                                                          |
| `recorder`          | Instance of `MediaRecorderController` that exposes the API to control the recording states (`start`, `pause`, `resume`, `stop`, `cancel`) |
| `recording`         | Generated attachment of type `voiceRecording`. This is available once the recording is stopped.                                           |
| `recordingState`    | One of the values `'recording'`, `'paused'`, `'stopped'`. Useful to reflect the changes in `recorder` state in the UI.                    |


---

This page was last updated at 2026-04-21T07:55:45.428Z.

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/sdk/react/v13/components/message-input-components/audio_recorder/](https://getstream.io/chat/docs/sdk/react/v13/components/message-input-components/audio_recorder/).