This documentation is available as Markdown for AI agents and LLMs. See the full Markdown index or append .md to any documentation URL.
Expo Audio (expo-audio)
A library that provides an API to implement audio playback and recording in apps.
expo-audio is a cross-platform audio library for accessing the native audio capabilities of the device.
The Android media format support documentation covers formats supported when using Expo Player on Android. The iOS audio and video format documentation lists supported media formats for Apple devices.
Note that audio automatically stops if headphones/bluetooth audio devices are disconnected.
Installation
If you are installing this in an existing React Native app, make sure to install expo in your project.
Configuration in app config
You can configure expo-audio using its built-in config plugin if you use config plugins in your project (Continuous Native Generation (CNG)). The plugin allows you to configure various properties that cannot be set at runtime and require building a new app binary to take effect. If your app does not use CNG, then you'll need to manually configure the library.
Example app.json with config plugin
Configurable properties
Usage
Playing sounds
Note: If you're migrating from
expo-av, you'll notice thatexpo-audiodoesn't automatically reset the playback position when audio finishes. Afterplay(), the player stays paused at the end of the sound. To play it again, callseekTo(seconds)to reset the position — as shown in the example above.
Recording sounds
Playing or recording audio in background iOS
On iOS, audio playback and recording in background is only available in standalone apps, and it requires some extra configuration.
On iOS, each background feature requires a special key in UIBackgroundModes array in your Info.plist file.
In standalone apps this array is empty by default, so to use background features you will need to add appropriate keys to your app.json configuration.
See an example of app.json that enables audio playback in background:
{ "expo": { ... "ios": { ... "infoPlist": { ... "UIBackgroundModes": [ "audio" ] } } } }
Using the AudioPlayer directly
In most cases, the useAudioPlayer hook should be used to create a AudioPlayer instance. It manages the player's lifecycle and ensures that it is properly disposed of when the component is unmounted. However, in some advanced use cases, it might be necessary to create a AudioPlayer that does not get automatically destroyed when the component is unmounted.
In those cases, the AudioPlayer can be created using the createAudioPlayer function. You need to be aware of the risks that come with this approach, as it is your responsibility to call the release() method when the player is no longer needed. If not handled properly, this approach may lead to memory leaks.
import { createAudioPlayer } from 'expo-audio'; const player = createAudioPlayer(audioSource);
Notes on web usage
- A MediaRecorder issue on Chrome produces WebM files missing the duration metadata. See the open Chromium issue.
- MediaRecorder encoding options and other configurations are inconsistent across browsers, utilizing a Polyfill such as kbumsik/opus-media-recorder or ai/audio-recorder-polyfill in your application will improve your experience. Any options passed to
prepareToRecordAsyncwill be passed directly to the MediaRecorder API and as such the polyfill. - Web browsers require sites to be served securely for them to listen to a mic. See MediaDevices
getUserMedia()security for more details.
API
import { useAudioPlayer, useAudioRecorder } from 'expo-audio';
Constants
Type: {
HIGH_QUALITY: RecordingOptions,
LOW_QUALITY: RecordingOptions
}
Constant which contains definitions of the two preset examples of RecordingOptions, as implemented in the Audio SDK.
HIGH_QUALITY
RecordingPresets.HIGH_QUALITY = { extension: '.m4a', sampleRate: 44100, numberOfChannels: 2, bitRate: 128000, android: { outputFormat: 'mpeg4', audioEncoder: 'aac', }, ios: { outputFormat: IOSOutputFormat.MPEG4AAC, audioQuality: AudioQuality.MAX, linearPCMBitDepth: 16, linearPCMIsBigEndian: false, linearPCMIsFloat: false, }, web: { mimeType: 'audio/webm', bitsPerSecond: 128000, }, };
LOW_QUALITY
RecordingPresets.LOW_QUALITY = { extension: '.m4a', sampleRate: 44100, numberOfChannels: 2, bitRate: 64000, android: { extension: '.3gp', outputFormat: '3gp', audioEncoder: 'amr_nb', }, ios: { audioQuality: AudioQuality.MIN, outputFormat: IOSOutputFormat.MPEG4AAC, linearPCMBitDepth: 16, linearPCMIsBigEndian: false, linearPCMIsFloat: false, }, web: { mimeType: 'audio/webm', bitsPerSecond: 128000, }, };
Hooks
Creates an AudioPlayer instance that automatically releases when the component unmounts.
This hook manages the player's lifecycle and ensures it's properly disposed when no longer needed. The player will start loading the audio source immediately upon creation.
AudioPlayerAn AudioPlayer instance that's automatically managed by the component lifecycle.
Example
import { useAudioPlayer } from 'expo-audio'; function MyComponent() { const player = useAudioPlayer(require('./sound.mp3')); return ( <Button title="Play" onPress={() => player.play()} /> ); }
Example
import { useAudioPlayer } from 'expo-audio'; function MyComponent() { const player = useAudioPlayer('https://example.com/audio.mp3', { updateInterval: 1000, downloadFirst: true, }); return ( <Button title="Play" onPress={() => player.play()} /> ); }
Hook that provides real-time playback status updates for an AudioPlayer.
This hook automatically subscribes to playback status changes and returns the current status. The status includes information about playback state, current time, duration, loading state, and more.
AudioStatusThe current AudioStatus object containing playback information.
Example
import { useAudioPlayer, useAudioPlayerStatus } from 'expo-audio'; function PlayerComponent() { const player = useAudioPlayer(require('./sound.mp3')); const status = useAudioPlayerStatus(player); return ( <View> <Text>Playing: {status.playing ? 'Yes' : 'No'}</Text> <Text>Current Time: {status.currentTime}s</Text> <Text>Duration: {status.duration}s</Text> </View> ); }
Hook that creates an AudioRecorder instance for recording audio.
This hook manages the recorder's lifecycle and ensures it's properly disposed when no longer needed. The recorder is automatically prepared with the provided options and can be used to record audio.
AudioRecorderAn AudioRecorder instance that's automatically managed by the component lifecycle.
Example
import { useAudioRecorder, RecordingPresets } from 'expo-audio'; function RecorderComponent() { const recorder = useAudioRecorder( RecordingPresets.HIGH_QUALITY, (status) => console.log('Recording status:', status) ); const startRecording = async () => { await recorder.prepareToRecordAsync(); recorder.record(); }; return ( <Button title="Start Recording" onPress={startRecording} /> ); }
Hook that provides real-time recording state updates for an AudioRecorder.
This hook polls the recorder's status at regular intervals and returns the current recording state. Use this when you need to monitor the recording status without setting up a status listener.
RecorderStateThe current RecorderState containing recording information.
Example
import { useAudioRecorder, useAudioRecorderState, RecordingPresets } from 'expo-audio'; function RecorderStatusComponent() { const recorder = useAudioRecorder(RecordingPresets.HIGH_QUALITY); const state = useAudioRecorderState(recorder); return ( <View> <Text>Recording: {state.isRecording ? 'Yes' : 'No'}</Text> <Text>Duration: {Math.round(state.durationMillis / 1000)}s</Text> <Text>Can Record: {state.canRecord ? 'Yes' : 'No'}</Text> </View> ); }
Hook that sets up audio sampling for an AudioPlayer and calls a listener with audio data.
This hook enables audio sampling on the player (if supported) and subscribes to audio sample updates. Audio sampling provides real-time access to audio waveform data for visualization or analysis.
Note: Audio sampling requires
RECORD_AUDIOpermission on Android and is not supported on all platforms.
voidExample
import { useEffect } from 'react'; import { useAudioPlayer, useAudioSampleListener, requestRecordingPermissionsAsync } from 'expo-audio'; function AudioVisualizerComponent() { const player = useAudioPlayer(require('./music.mp3')); // if required on Android, request recording permissions useEffect(() => { async function requestPermission() { const { granted } = await requestRecordingPermissionsAsync(); if (granted) { console.log("Permission granted"); } } requestPermission(); }, []); useAudioSampleListener(player, (sample) => { // Use sample.channels array for audio visualization console.log('Audio sample:', sample.channels[0].frames); }); return <AudioWaveform player={player} />; }
Classes
Type: Class extends SharedObject<AudioEvents>
AudioPlayer Properties
booleanBoolean value indicating whether audio sampling is supported on the platform.
booleanBoolean value indicating whether the player is finished loading.
booleanBoolean value indicating whether the player is currently paused.
numberThe current playback rate of the audio. It accepts different values depending on the platform:
- Android:
0.1to2.0 - iOS:
0.0to2.0 - Web: Follows browser implementation
Example
import { useAudioPlayer } from 'expo-audio'; export default function App() { const player = useAudioPlayer(source); // Normal playback speed player.playbackRate = 1.0; // Slow motion (half speed) player.playbackRate = 0.5; // Fast playback (1.5x speed) player.playbackRate = 1.5; // Maximum speed on mobile player.playbackRate = 2.0; }
booleanBoolean value indicating whether the player is currently playing.
booleanA boolean describing if we are correcting the pitch for a changed rate.
numberThe current volume of the audio.
Range: 0.0 to 1.0. For example, 0.0 is completely silent (0%), 0.5 is half volume (50%), and 1.0 is full volume (100%).
Example
import { useAudioPlayer } from 'expo-audio'; export default function App() { const player = useAudioPlayer(source); // Mute the audio player.volume = 0.0; // Set volume to 50% player.volume = 0.5; // Set to full volume player.volume = 1.0; }
AudioPlayer Methods
Removes this player from lock screen controls if it's currently active. This will clear the lock screen's now playing info.
voidSets or removes this audio player as the active player for lock screen controls. Only one player can control the lock screen at a time.
voidSets the current playback rate of the audio.
voidType: Class extends SharedObject<RecordingEvents>
AudioRecorder Properties
booleanBoolean value indicating whether the recording is in progress.
AudioRecorder Methods
Returns a list of available recording inputs. This method can only be called if the Recording has been prepared.
RecordingInput[]A Promise that is fulfilled with an array of RecordingInput objects.
Returns the currently-selected recording input. This method can only be called if the Recording has been prepared.
Promise<RecordingInput>A Promise that is fulfilled with a RecordingInput object.
Status of the current recording.
RecorderStateDeprecated: Use
record({ forDuration: seconds })instead.
Stops the recording once the specified time has elapsed.
voidSets the current recording input.
voidA Promise that is resolved if successful or rejected if not.
Deprecated: Use
record({ atTime: seconds })instead.
Starts the recording at the given time.
voidStop the recording.
Promise<void>Methods
Creates an instance of an AudioPlayer that doesn't release automatically.
For most use cases you should use the
useAudioPlayerhook instead. See the Using theAudioPlayerdirectly section for more details.
AudioPlayerChecks the current status of recording permissions without requesting them.
This function returns the current permission status for microphone access
without triggering a permission request dialog. Use this to check permissions
before deciding whether to call requestRecordingPermissionsAsync().
Promise<PermissionResponse>A Promise that resolves to a PermissionResponse object containing the current permission status.
Example
import { getRecordingPermissionsAsync, requestRecordingPermissionsAsync } from 'expo-audio'; const ensureRecordingPermissions = async () => { const { status } = await getRecordingPermissionsAsync(); if (status !== 'granted') { // Permission not granted, request it const { granted } = await requestRecordingPermissionsAsync(); return granted; } return true; // Already granted };
Requests permission to record audio from the microphone.
This function prompts the user for microphone access permission, which is required
for audio recording functionality. On iOS, this will show the system permission dialog.
On Android, this requests the RECORD_AUDIO permission.
Promise<PermissionResponse>A Promise that resolves to a PermissionResponse object containing the permission status.
Example
import { requestRecordingPermissionsAsync } from 'expo-audio'; const checkPermissions = async () => { const { status, granted } = await requestRecordingPermissionsAsync(); if (granted) { console.log('Recording permission granted'); } else { console.log('Recording permission denied:', status); } };
Configures the global audio behavior and session settings.
This function allows you to control how your app's audio interacts with other apps, background playback behavior, audio routing, and interruption handling.
Promise<void>A Promise that resolves when the audio mode has been applied.
Example
import { setAudioModeAsync } from 'expo-audio'; // Configure audio for background playback with mixing await setAudioModeAsync({ playsInSilentMode: true, shouldPlayInBackground: true, interruptionMode: 'mixWithOthers' }); // Configure audio for recording await setAudioModeAsync({ allowsRecording: true, playsInSilentMode: true });
Enables or disables the audio subsystem globally.
When set to false, this will pause all audio playback and prevent new audio from playing.
This is useful for implementing app-wide audio controls or responding to system events.
Promise<void>A Promise that resolves when the audio state has been updated.
Example
import { setIsAudioActiveAsync } from 'expo-audio'; // Disable all audio when app goes to background const handleAppStateChange = async (nextAppState) => { if (nextAppState === 'background') { await setIsAudioActiveAsync(false); } else if (nextAppState === 'active') { await setIsAudioActiveAsync(true); } };
Event subscriptions
Hook that sets up audio sampling for an AudioPlayer and calls a listener with audio data.
This hook enables audio sampling on the player (if supported) and subscribes to audio sample updates. Audio sampling provides real-time access to audio waveform data for visualization or analysis.
Note: Audio sampling requires
RECORD_AUDIOpermission on Android and is not supported on all platforms.
voidExample
import { useEffect } from 'react'; import { useAudioPlayer, useAudioSampleListener, requestRecordingPermissionsAsync } from 'expo-audio'; function AudioVisualizerComponent() { const player = useAudioPlayer(require('./music.mp3')); // if required on Android, request recording permissions useEffect(() => { async function requestPermission() { const { granted } = await requestRecordingPermissionsAsync(); if (granted) { console.log("Permission granted"); } } requestPermission(); }, []); useAudioSampleListener(player, (sample) => { // Use sample.channels array for audio visualization console.log('Audio sample:', sample.channels[0].frames); }); return <AudioWaveform player={player} />; }
Types
Literal type: string
Audio encoder options for Android recording.
Specifies the audio codec used to encode recorded audio on Android. Different encoders offer different quality, compression, and compatibility trade-offs.
Acceptable values are: 'default' | 'amr_nb' | 'amr_wb' | 'aac' | 'he_aac' | 'aac_eld'
Literal type: string
Audio output format options for Android recording.
Specifies the container format for recorded audio files on Android. Different formats have different compatibility and compression characteristics.
Acceptable values are: 'default' | '3gp' | 'mpeg4' | 'amrnb' | 'amrwb' | 'aac_adts' | 'mpeg2ts' | 'webm'
Event types that an AudioPlayer can emit.
These events allow you to listen for changes in playback state and receive real-time audio data.
Use player.addListener() to subscribe to these events.
Deprecated: Use
AudioPlayerOptionsinstead. Options for audio loading behavior.
Type: AudioPlayerOptions
Options for configuring which playback controls should be displayed on the lock screen.
Represents a single audio sample containing waveform data from all audio channels.
Audio samples are provided in real-time when audio sampling is enabled on an AudioPlayer.
Each sample contains the raw PCM audio data for all channels (mono has 1 channel, stereo has 2).
This data can be used for audio visualization, analysis, or processing.
Represents audio data for a single channel (for example, left or right in stereo audio).
Contains the raw PCM (Pulse Code Modulation) audio frames for this channel. Frame values are normalized between -1.0 and 1.0, where 0 represents silence.
Comprehensive status information for an AudioPlayer.
This object contains all the current state information about audio playback,
including playback position, duration, loading state, and playback settings.
Used by useAudioPlayerStatus() to provide real-time status updates.
Literal type: string
Bit rate strategies for audio encoding.
Determines how the encoder manages bit rate during recording, affecting file size consistency and quality characteristics.
Acceptable values are: 'constant' | 'longTermAverage' | 'variableConstrained' | 'variable'
Literal type: string
Audio interruption behavior modes.
Controls how your app's audio interacts with other apps' audio.
-
'doNotMix': Requests exclusive audio focus. Other apps will pause their audio. -
'duckOthers': Requests audio focus with ducking. Other apps lower their volume but continue playing. -
'mixWithOthers': Audio plays alongside other apps without interrupting them.On Android, this means no audio focus is requested. Best suited for sound effects, UI feedback, or short audio clips. Note that on Android your app won't receive audio focus loss callbacks (for example, during phone calls) when using this mode.
Note: When using
setActiveForLockScreen, this must be set todoNotMix.
Acceptable values are: 'mixWithOthers' | 'doNotMix' | 'duckOthers'
Deprecated: Use
InterruptionModeinstead, which now works on both platforms.
Type: InterruptionMode
Literal type: union
Permission expiration time. Currently, all permissions are granted permanently.
Acceptable values are: 'never' | number
Literal type: string
Pitch correction quality settings for audio playback rate changes.
When changing playback rate, pitch correction can be applied to maintain the original pitch. Different quality levels offer trade-offs between processing power and audio quality.
Acceptable values are: 'low' | 'medium' | 'high'
Current state information for an AudioRecorder.
This object contains detailed information about the recorder's current state,
including recording status, duration, and technical details. This is what you get
when calling recorder.getStatus() or using useAudioRecorderState().
Event types that an AudioRecorder can emit.
These events are used internally by expo-audio hooks to provide real-time status updates.
Use useAudioRecorderState() or the statusListener parameter in useAudioRecorder() instead of subscribing directly.
Represents an available audio input device for recording.
This type describes audio input sources like built-in microphones, external microphones, or other audio input devices that can be used for recording. Each input has an identifying information that can be used to select the preferred recording source.
Recording configuration options specific to Android.
Android recording uses MediaRecorder with options for format, encoder, and file constraints.
These settings control the output format and quality characteristics.
Recording configuration options specific to iOS.
iOS recording uses AVAudioRecorder with extensive format and quality options.
These settings provide fine-grained control over the recording characteristics.
Recording options for the web.
Web recording uses the MediaRecorder API, which has different capabilities
compared to native platforms. These options map directly to MediaRecorder settings.
Literal type: string
Recording source for android.
An audio source defines both a default physical source of audio signal, and a recording configuration.
camcorder: Microphone audio source tuned for video recording, with the same orientation as the camera if available.default: The default audio source.mic: Microphone audio source.unprocessed: Microphone audio source tuned for unprocessed (raw) sound if available, behaves likedefaultotherwise.voice_communication: Microphone audio source tuned for voice communications such as VoIP. It will for instance take advantage of echo cancellation or automatic gain control if available.voice_performance: Source for capturing audio meant to be processed in real time and played back for live performance (e.g karaoke). The capture path will minimize latency and coupling with playback path.voice_recognition: Microphone audio source tuned for voice recognition.
Acceptable values are: 'camcorder' | 'default' | 'mic' | 'remote_submix' | 'unprocessed' | 'voice_communication' | 'voice_performance' | 'voice_recognition'
Status information for recording operations from the event system.
This type represents the status data emitted by recordingStatusUpdate events.
It contains high-level information about the recording session and any errors.
Used internally by the event system. Most users should use useAudioRecorderState() instead.
Enums
Audio quality levels for recording.
Predefined quality levels that balance file size and audio fidelity. Higher quality levels produce better sound but larger files and require more processing power.
Audio output format options for iOS recording.
Comprehensive enum of audio formats supported by iOS for recording. Each format has different characteristics in terms of quality, file size, and compatibility. Some formats like LINEARPCM offer the highest quality but larger file sizes, while compressed formats like AAC provide good quality with smaller files.