const TopLevelComponent = ({ children }) => {
return (
<AudioPlayerProvider value={{ allowConcurrentPlayback: false }}>
{children}
</AudioPlayerProvider>
);
};Audio Playback
As of stream-chat-react-native@8.11.0, you can build audio players using:
AudioPlayerProviderReact componentuseAudioPlayerControlhookuseActiveAudioPlayerhook
Best Practices
- Wrap audio UI in
AudioPlayerProviderto keep playback stable in lists. - Use
useStateStoreselectors to avoid re-rendering on unrelated audio state. - Prefer single-playback mode unless your UX clearly needs concurrency.
- Reuse the shared player pool instead of creating per-row players.
- Test playback when items unmount to confirm continuity.
The old useAudioPlayer hook is deprecated; most functionality is now in AudioPlayer.
Before stream-chat-react-native@8.10.0, audio used useAudioController and lived inside the UI component, which broke playback in virtualized lists. useAudioPlayerControl uses a central pool, so playback continues even if the message component unmounts.
Audio playback is controlled via AudioPlayerProvider and useAudioPlayerControl. The provider maintains a pool of AudioPlayer instances; access them with useAudioPlayerControl.
By default, Channel renders AudioPlayerProvider, so its children share a single pool.
Audio Playback mode
Choose between single or concurrent playback:
Single-playback mode: only one audio at a time (default in Channel).
Concurrent-playback mode: multiple audios can play at once.
Enable concurrent playback by setting allowConcurrentPlayback in AudioPlayerProvider’s value.
Building Audio Components
To build audio components outside Channel:
- Have a top-level component render
AudioPlayerProvider
- Render the audio player in a child component
import {
AudioPlayerState,
useAudioPlayerControl,
useStateStore,
} from "stream-chat-react-native";
const audioPlayerSelector = (state: AudioPlayerState) => ({
currentPlaybackRate: state.currentPlaybackRate,
duration: state.duration,
isPlaying: state.isPlaying,
position: state.position,
progress: state.progress,
});
const AudioPlayerComponent = () => {
const audioPlayer = useAudioPlayerControl({
duration: item.duration ?? 0,
mimeType: item.mime_type ?? "",
requester: "audio-player-component",
type: isVoiceRecording ? "voiceRecording" : "audio",
uri: item.asset_url ?? "",
});
// You can use the following state to build your own audio player UI
const { duration, isPlaying, position, progress, currentPlaybackRate } =
useStateStore(audioPlayer.state, audioPlayerSelector);
};- Get the active audio player
In single-playback mode, a global player UI can show the active audio even if the user scrolls away.
Note: This is relevant only for single-playback mode.
import { useActiveAudioPlayer } from "stream-chat-react-native";
const activeAudioPlayer = useActiveAudioPlayer();Audio Player API
Use the following AudioPlayer methods to build a UI:
Getters
| Method | Description |
|---|---|
isPlaying | Get the current playing state of the audio, whether it is playing or not. |
duration | Get the duration of the audio in milliseconds. |
progress | Get progress as a percentage (0-1). |
position | Get the current position of the audio in milliseconds. |
currentPlaybackRate | Get the current playback rate. |
playbackRates | Get available playback rates. |
id | Get the audio player ID. |
Setters
| Method | Description |
|---|---|
duration | Set the duration of the audio in milliseconds. |
position | Set the position of the audio in milliseconds and update the progress. |
progress | Set progress (0-1) and update the position. |
isPlaying | Set the playing state of the audio. |
Methods
play - plays the audio.
| Type | Description |
|---|---|
() => void | Plays the audio. |
audioPlayer.play();pause - pauses the audio.
| Type | Description |
|---|---|
() => void | Pauses the audio. |
audioPlayer.pause();toggle - toggles the playing state of the audio.
| Type | Description |
|---|---|
() => void | Toggles the playing state of the audio. |
audioPlayer.toggle();seek - seeks to a specific position in the audio.
| Type | Description |
|---|---|
(positionInSeconds: number) => Promise<void> | Seeks to a specific position in the audio. |
await audioPlayer.seek(positionInSeconds);stop - stops the audio.
| Type | Description |
|---|---|
() => Promise<void> | Stops the audio. |
await audioPlayer.stop();changePlaybackRate - changes the playback rate of the audio.
| Type | Description |
|---|---|
() => Promise<void> | Changes the playback rate of the audio. |
await audioPlayer.changePlaybackRate(playbackRate);initPlayer - initializes the audio player using the provided URL or provided player reference.
| Type | Description |
|---|---|
({url?: string, playerRef?: React.RefObject<AudioPlayer>}) => Promise<void> | Initializes the audio player using the provided URL or provided player reference. For Expo, we pass the URL while for audio playing using react-native-video, we pass the player reference. |
await audioPlayer.initPlayer({ url: "https://example.com/audio.mp3" });