---
title: Audio (expo-audio)
description: A library that provides an API to implement audio playback and recording in apps.
sourceCodeUrl: https://github.com/expo/expo/tree/sdk-53/packages/expo-audio
packageName: expo-audio
iconUrl: /static/images/packages/expo-av.png
platforms: ["android", "ios", "web", "tvos"]
---
`expo-audio` is a cross-platform audio library for accessing the native audio capabilities of the device.
Note that audio automatically stops if headphones/bluetooth audio devices are disconnected.
## Installation
## Configuration in app config
You can configure `expo-audio` using its built-in [config plugin](/config-plugins/introduction/) if you use config plugins in your project ([EAS Build](/build/introduction) or `npx expo run:[android|ios]`). 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 EAS Build, then you'll need to manually configure the package.
```json app.json
{
"expo": {
"plugins": [
[
"expo-audio",
{
"microphonePermission": "Allow $(PRODUCT_NAME) to access your microphone."
}
]
]
}
}
```
## Usage
### Playing sounds
```jsx
const audioSource = require('./assets/Hello.mp3');
const player = useAudioPlayer(audioSource);
return (
<View style={styles.container}>
<Button title="Play Sound" onPress={() => player.play()} />
<Button
title="Replay Sound"
onPress={() => {
player.seekTo(0);
player.play();
}}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
backgroundColor: '#ecf0f1',
padding: 10,
},
});
```
> **Info** **Note:** If you're migrating from [`expo-av`](av.md), you'll notice that `expo-audio` doesn't automatically reset the playback position when audio finishes. After [`play()`](#play), the player stays paused at the end of the sound. To play it again, call [`seekTo(seconds)`](#seektoseconds) to reset the position — as shown in the example above.
### Recording sounds
```jsx
import {
useAudioRecorder,
AudioModule,
RecordingPresets,
setAudioModeAsync,
useAudioRecorderState,
} from 'expo-audio';
const audioRecorder = useAudioRecorder(RecordingPresets.HIGH_QUALITY);
const recorderState = useAudioRecorderState(audioRecorder);
const record = async () => {
await audioRecorder.prepareToRecordAsync();
audioRecorder.record();
};
const stopRecording = async () => {
// The recording will be available on `audioRecorder.uri`.
await audioRecorder.stop();
};
useEffect(() => {
(async () => {
const status = await AudioModule.requestRecordingPermissionsAsync();
if (!status.granted) {
Alert.alert('Permission to access microphone was denied');
}
setAudioModeAsync({
playsInSilentMode: true,
allowsRecording: true,
});
})();
}, []);
return (
<View style={styles.container}>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
backgroundColor: '#ecf0f1',
padding: 10,
},
});
```
### Playing or recording audio in background 
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:
```json
{
"expo": {
...
"ios": {
...
"infoPlist": {
...
"UIBackgroundModes": [
"audio"
]
}
}
}
}
```
### Using the AudioPlayer directly
In most cases, the [`useAudioPlayer`](#useaudioplayersource-updateinterval) 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`](#audiocreateaudioplayersource-updateinterval) function. You need be aware of the risks that come with this approach, as it is your responsibility to call the [`release()`](../sdk/expo/#release) method when the player is no longer needed. If not handled properly, this approach may lead to memory leaks.
```tsx
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](https://bugs.chromium.org/p/chromium/issues/detail?id=642012).
- MediaRecorder encoding options and other configurations are inconsistent across browsers, utilizing a Polyfill such as [kbumsik/opus-media-recorder](https://github.com/kbumsik/opus-media-recorder) or [ai/audio-recorder-polyfill](https://github.com/ai/audio-recorder-polyfill) in your application will improve your experience. Any options passed to `prepareToRecordAsync` will 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](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia#security) for more details.
## API
```js
```