# Voice Recording

Stream chat allows you to exchange Voice Recordings in your channels. Those Voice Recordings are a built-in Attachment types (as are being defined [here](/chat/docs/sdk/ios/v4/uikit/guides/working-with-attachments/)). We are going to take a look in the main parts of Voice Recording feature below.

<admonition type="note">

Voice Recordings are available since version 4.32.0.

</admonition>

VoiceRecording creation and playback is by default disabled. If you would like to enable it, you can do so by setting the Components `isVoiceRecordingEnabled` property to `true` like below:

```swift
Components.default.isVoiceRecordingEnabled = true
```

<admonition type="note">

When the VoiceRecording feature is disabled, any message containing VoiceRecordings will render them as regular audio attachments.

</admonition>

## UI Flows

### Recording

The recording flow is being presented on the `ComposerContentView` of the `ComposerVC` and it's being managed by `VoiceRecordingVC`. The `VoiceRecordingVC` takes care of the following:

- Update the UI based on the recordings state (for example recording, locked or in preview)
- Update the UI with recording related information (for example duration, current playback time)
- Coordinate information flow from audio recording and player.
- Communicate with `ComposerVC` in order to add a VoiceRecording as attachment or send it.

The main UI components that `VoiceRecordingVC` manages are the following:

#### recordingTipView

A view that is being used to display a tip to user when the tap duration on the recording button wasn't long enough (the display of this view relates to `RecordButton.minimumPressDuration`).

#### slideToCancelView

A view that during an unlocked recording, displays information on how to cancel the active recording.

#### recordingIndicatorView

A view that indicates to the user that we are currently recording audio.

#### lockIndicatorView

A view that indicates to the user if the currently active recording is locked or not.

#### liveRecordingView

A view that during a locked recording, displays information about the active recording or its preview.

#### bidirectionalPanGestureRecogniser

The gesture recogniser used to identify touch movements in the horizontal or vertical axis.

### Presentation

VoiceRecordings are being presented using the `voiceRecordingAttachmentView` that is defined and configurable in Components:

```swift
Components.default.voiceRecordingAttachmentView = ChatMessageVoiceRecordingAttachmentListView.ItemView.self
```

The view manages the visibility and state of all UI components (e.g play/pause button, waveform visualization, playback rate button and name label).

## Components Configuration

### Audio player

The `AudioPlayer` that will be used for the voice recording playback.

```swift
Components.default.audioPlayer = StreamAudioQueuePlayer.self
```

The default value is `StreamAudioQueuePlayer.self`. In case you want to disable voice recording messages to play automatically once the previous one finishes, you can set this one to `StreamAudioPlayer.self`.

If you want to provide a custom audio session configuration, you can do that by providing it in initializer of your custom audio player. This can be useful if you want to change the logic of the audio session, for example, force the audio to play from the speaker even if a Bluetooth device is connected.

Here is an example of how to provide a custom audio session configuration:

```swift
final class CustomAudioPlayer: StreamAudioQueuePlayer {
    required convenience init() {
        self.init(
            assetPropertyLoader: StreamAssetPropertyLoader(),
            audioSessionConfigurator: CustomAudioSessionConfigurator()
        )
    }
}

Components.default.audioPlayer = CustomAudioPlayer.self
```

### Audio recorder

The `AudioRecorder` that will be used to record new voice recordings.

```swift
Components.default.audioRecorder = StreamAudioRecorder.self
```

When recording audio, it will also use the Bluetooth device's mic if there is one connected. If you need to customize this behaviour, you can provide a custom audio session configuration in the `AudioRecorder` initializer.

```swift
class CustomAudioRecorder: StreamAudioRecorder {
    required convenience init() {
        self.init(
            configuration: .default,
            audioSessionConfigurator: CustomAudioSessionConfigurator()
        )
    }
}

Components.default.audioRecorder = CustomAudioRecorder.self
```

### Feedback generator

A `feedbackGenerator` that will be used to provide haptic feedback during the recording flow. It can be customized in cases where you want to provide different or none haptic feedback for actions during the recording flow.

```swift
Components.default.audioSessionFeedbackGenerator = StreamAudioSessionFeedbackGenerator.self
```

### Disabling confirmation required

By default, you can record multiple voice recordings and send them as part of one message. If you want to disable this behavior, you can set the `isVoiceRecordingConfirmationRequiredEnabled` property to `false`.

```swift
Components.default.isVoiceRecordingConfirmationRequiredEnabled = false
```

### Queue player next item provider

`ComposerVC` parent view controllers (`ChatChannelVC` and `ChatThreadVC`) will become the data source of the audio player if it's an instance of `StreamRemoteAudioQueuePlayer`.

The default implementation of the `AudioQueuePlayerDatasource` in those view controllers is using the `audioQueuePlayerNextItemProvider` instance defined here to find the next (if any) voice recording to play.

```swift
Components.default.audioQueuePlayerNextItemProvider = AudioQueuePlayerNextItemProvider.self
```

When calling `findNextItem` on the `AudioQueuePlayerNextItemProvider` instance, we can specify a lookup scope. This will inform the `AudioQueuePlayerNextItemProvider` to know where to look for the next voice recording. The available values for the `lookUpScope` are:

- `sameMessage` - look for the next VoiceRecording in the attachments of the message containing the currently playing URL.
- `subsequentMessagesFromUser` - look for the next VoiceRecording in the attachments of the of the message containing the currently playing URL and if not found will apply the same logic in all subsequent messages that have the same author.

You can create your own `lookupScope` instances and override the implementation `AudioQueuePlayerNextItemProvider` in order to fit its functionality to your use-cases.


---

This page was last updated at 2026-04-17T17:33:37.223Z.

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/sdk/ios/v4/uikit/components/voice-recording/](https://getstream.io/chat/docs/sdk/ios/v4/uikit/components/voice-recording/).