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
Recording sounds
On Android and iOS, expo-audio saves recordings in the app's cache directory by default. The system may delete cache files when the device runs low on storage. To keep new recordings in a more persistent location, pass { ...RecordingPresets.HIGH_QUALITY, directory: 'document' } to useAudioRecorder or prepareToRecordAsync(). This stores them under the app's document directory. For existing recordings already saved in cache, use the returned recording URI to move them with expo-file-system.
Playing audio in the background
Background audio playback allows your app to continue playing audio when it moves to the background or when the device screen locks.
Configuration
To enable background audio playback, use the config plugin in your app config:
The above configuration automatically configures the required native settings:
- AndroidAdds
FOREGROUND_SERVICEandFOREGROUND_SERVICE_MEDIA_PLAYBACKpermissions. Also declares a media playback foreground service (AudioControlsService) in app's AndroidManifest.xml. - iOSAdds the
audioUIBackgroundModecapability
Usage
After configuring your app with the config plugin, you need to:
- Configure the audio session to allow background playback
- Enable lock screen controls (required on Android for sustained background playback)
import { View, Button } from 'react-native'; import { useAudioPlayer, setAudioModeAsync } from 'expo-audio'; import { useEffect } from 'react'; export default function AudioPlayerScreen() { const audioSource = require('./assets/audio.mp3'); const player = useAudioPlayer(audioSource); useEffect(() => { // Configure audio session for background playback setAudioModeAsync({ playsInSilentMode: true, shouldPlayInBackground: true, interruptionMode: 'doNotMix', }); }, []); const handlePlay = () => { // Enable lock screen controls with metadata player.setActiveForLockScreen(true, { title: 'My Audio Title', artist: 'Artist Name', albumTitle: 'Album Name', artworkUrl: 'https://example.com/artwork.jpg', // optional }); // Start playback - this will continue in the background player.play(); }; const handleStop = () => { player.pause(); // Optionally disable lock screen controls when done player.setActiveForLockScreen(false); }; return ( <View> <Button title="Play" onPress={handlePlay} /> <Button title="Stop" onPress={handleStop} /> </View> ); }
Note: On Android, you have to enable the lock screen controls with
setActiveForLockScreenfor sustained background playback. Otherwise, the audio will stop after approximately 3 minutes of background playback (OS limitation). Ensure to appropriately configure the config plugin.
- A media notification appears in the notification drawer with playback controls
- Audio continues playing indefinitely in the background
- Users can control playback from the lock screen and notification
- The foreground service keeps the playback alive during playback
On iOS, audio playback continues seamlessly in the background once the audio session is configured with shouldPlayInBackground: true. Lock screen controls are optional but enhance the user experience by providing playback controls on the lock screen and Control Center.
Are you using this library in an existing React Native app?
If you're not using Continuous Native Generation (CNG) (you're using native android and ios projects manually), then you need to configure the following for background playback:
-
For Android, add to android/app/src/main/AndroidManifest.xml:
android/app/src/main/AndroidManifest.xml -
For iOS, add to ios/YourApp/Info.plist:
ios/YourApp/Info.plist
Recording audio in the background
Background recording can significantly impact battery life. Only enable it when necessary for your app's functionality.
Background audio recording allows your app to continue recording when it moves to the background or when the device screen locks.
To enable background recording, use the config plugin in your app config:
The above configuration automatically configures the required native settings:
- AndroidAdds
FOREGROUND_SERVICE,FOREGROUND_SERVICE_MICROPHONE, andPOST_NOTIFICATIONSpermissions. Also declares an audio recording foreground service in app's AndroidManifest.xml. - iOSAdds the
audioUIBackgroundModecapability
Are you using this library in an existing React Native app?
If you're not using Continuous Native Generation (CNG) (you're using native android and ios projects manually), then you need to configure the following permissions in your native projects:
-
For Android, add to android/app/src/main/AndroidManifest.xml:
android/app/src/main/AndroidManifest.xml -
For iOS, add to ios/YourApp/Info.plist:
ios/YourApp/Info.plist
Usage
After configuring your app, enable background recording at runtime using setAudioModeAsync:
import { setAudioModeAsync, useAudioRecorder, RecordingPresets } from 'expo-audio'; await setAudioModeAsync({ playsInSilentMode: true, allowsRecording: true, allowsBackgroundRecording: true, }); const recorder = useAudioRecorder(RecordingPresets.HIGH_QUALITY); await recorder.prepareToRecordAsync(); await recorder.record(); // Recording continues in background
On Android, background recording requires a foreground service, which displays a persistent notification with the text "Recording audio" and a stop button. This notification cannot be dismissed while recording is active and automatically disappears when recording stops.
On iOS, background recording continues seamlessly when the app is in the background or the screen locks. No additional notifications or indicators are shown to the app user beyond the system status bar.
Using the AudioPlayer directly
In most cases, use the useAudioPlayer hook to create an AudioPlayer instance. It manages the player's lifecycle and ensures proper disposal when the component unmounts. However, in some advanced use cases, you may need to create an AudioPlayer that persists beyond the component's lifecycle.
In those cases, use 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. Using 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';
No API data file found, sorry!