const TopLevelComponent = ({ children }) => {
return (
<AudioPlayerProvider value={{ allowConcurrentPlayback: false }}>
{children}
</AudioPlayerProvider>
);
};Audio Playback
As of the version stream-chat-react-native@8.9.0 it is possible to build audio player components with the following combo of components:
AudioPlayerProviderReact componentuseAudioPlayerControlhookuseActiveAudioPlayerhook
The previous useAudioPlayer hook is deprecated and will be removed in the future as most of the functionality is now managed in the AudioPlayer class.
Until the version stream-chat-react-native@8.8.1, the audio was played using useAudioController hook. The audio player was handled directly in the player UI component. That was limiting in scenarios like audio playback in Virtualized FlatList/FlashList. During the scroll, the Message component with audio element was removed and thus the playback stopped. This is not the case of useAudioPlayerControl hook which reaches into a central pool of audio players.
All the audio playback is controlled using the combination of AudioPlayerProvider React component wrapper and useAudioPlayerControl hook. Component AudioPlayerProvider is necessary to initiate and maintain a pool of AudioPlayer instances (this holds the audio player reference). The pool is not publicly accessible. We access individual AudioPlayer instances using useAudioPlayerControl hook instead.
By default, the SDK renders AudioPlayerProvider component inside the Channel component. All the Channel component’s children can thus reach to one shared pool of AudioPlayer instances using useAudioPlayerControl hook.
Audio Playback mode
We can decide, whether we want to allow only a single or multiple audios to be played at a time.
Single-playback mode - only a single audio can be reproduced at a time (default in Channel component).
Concurrent-playback mode - multiple audios can be reproduced at the same time
It is possible to change the default (false), by setting allowConcurrentPlayback param in the value prop of AudioPlayerProvider component.
Building Audio Components
If we wanted to build a React component separated from Channel and needed to play audio inside this component, we need to perform the following steps:
- Have a top-level component render
AudioPlayerProvider
- Have a child component that renders the audio player
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
When operating in single-playback mode it can make sense to have a global audio player UI that displays the playback of active audio player. For example if a user starts the playback from a message’s audio widget and scrolls away, we may want to show the global audio player UI from which the playback could still be controlled without having to return to the original message
Note: This is relavant when you are playing only one audio at a time.
import { useActiveAudioPlayer } from "stream-chat-react-native";
const activeAudioPlayer = useActiveAudioPlayer();Audio Player API
These are the AudioPlayer methods needed to create a audio player UI widget:
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 the progress of the audio in percentage(0-1). |
position | Get the current position of the audio in milliseconds. |
currentPlaybackRate | Get the current playback rate of the audio |
playbackRates | Get the available playback rates of the audio |
id | Get the id of the audio player |
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 the progress of the audio in percentage(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: number);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: number);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" });