A library that provides an API to implement audio playback and recording in apps.
This page documents an upcoming version of the Audio library. Expo audio is currently in alpha and subject to breaking changes.
expo-audio
is a cross-platform audio library for accessing the native audio capabilities of the device.
Audio recording APIs are not available on tvOS (Apple TV).
Note that audio automatically stops if headphones/bluetooth audio devices are disconnected.
-
npx expo install expo-audio
If you are installing this in an existing React Native app, start by installing expo
in your project. Then, follow the additional instructions as mentioned by the library's README under "Installation in bare React Native projects" section.
You can configure expo-audio
using its built-in config plugin if you use config plugins in your project (EAS Build 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.
{
"expo": {
"plugins": [
[
"expo-audio",
{
"microphonePermission": "Allow $(PRODUCT_NAME) to access your microphone."
}
]
]
}
}
Name | Default | Description |
---|---|---|
microphonePermission | "Allow $(PRODUCT_NAME) to access your microphone" | Only for: iOS A string to set the |
import { useEffect, useState } from 'react';
import { View, StyleSheet, Button } from 'react-native';
import { useAudioPlayer } from 'expo-audio';
export default function App() {
const player = useAudioPlayer(audioSource);
return (
<View style={styles.container}>
<Button title="Play Sound" onPress={() => player.play()} />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
backgroundColor: '#ecf0f1',
padding: 10,
},
});
import { useState } from 'react';
import { View, StyleSheet, Button } from 'react-native';
import { useAudioRecorder, RecordingOptions, AudioModule, RecordingPresets } from 'expo-audio';
export default function App() {
const audioRecorder = useAudioRecorder(RecordingPresets.HIGH_QUALITY;);
const record = () => 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');
}
})();
}, []);
return (
<View style={styles.container}>
<Button
title={audioRecorder.isRecording ? 'Stop Recording' : 'Start Recording'}
onPress={audioRecorder.isRecording ? stopRecording : record}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
backgroundColor: '#ecf0f1',
padding: 10,
},
});
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"
]
}
}
}
}
prepareToRecordAsync
will be passed directly to the MediaRecorder API and as such the polyfill.getUserMedia()
security for more details.import { useAudioPlayer, useAudioRecorder } from 'expo-audio';
Audio.RecordingPresets
Type: Record<string, 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,
},
};
useAudioPlayer(source, updateInterval)
Parameter | Type |
---|---|
source (optional) | number | AudioSource |
updateInterval (optional) | number |
useAudioRecorder(options, statusListener)
Parameter | Type |
---|---|
options | RecordingOptions |
statusListener (optional) | (status: RecordingStatus) => void |
useAudioRecorderState(recorder, interval)
Parameter | Type |
---|---|
recorder | AudioRecorder |
interval (optional) | number |
useAudioSampleListener(player, listener)
Parameter | Type |
---|---|
player | AudioPlayer |
listener | (data: AudioSample) => void |
void
AudioPlayer
Type: Class extends SharedObject<AudioEvents>
AudioPlayer Properties
isAudioSamplingSupported
boolean
Boolean value indicating whether audio sampling is supported on the platform.
shouldCorrectPitch
boolean
A boolean describing if we are correcting the pitch for a changed rate.
AudioPlayer Methods
seekTo(seconds)
Parameter | Type | Description |
---|---|---|
seconds | number | The number of seconds to seek by. |
Seeks the playback by the given number of seconds.
Promise<void>
setPlaybackRate(rate, pitchCorrectionQuality)
Parameter | Type | Description |
---|---|---|
rate | number | The playback rate of the audio. |
pitchCorrectionQuality (optional) | PitchCorrectionQuality | The quality of the pitch correction. |
Sets the current playback rate of the audio.
void
AudioRecorder
Type: Class extends SharedObject<RecordingEvents>
AudioRecorder Properties
AudioRecorder Methods
getAvailableInputs()
Returns a list of available recording inputs. This method can only be called if the Recording
has been prepared.
A Promise
that is fulfilled with an array of RecordingInput
objects.
getCurrentInput()
Returns the currently-selected recording input. This method can only be called if the Recording
has been prepared.
A Promise
that is fulfilled with a RecordingInput
object.
prepareToRecordAsync(options)
Parameter | Type |
---|---|
options (optional) | Partial<RecordingOptions> |
Prepares the recording for recording.
Promise<void>
recordForDuration(seconds)
Parameter | Type | Description |
---|---|---|
seconds | number | The time in seconds to stop recording at. |
Stops the recording once the specified time has elapsed.
void
setInput(inputUid)
Parameter | Type | Description |
---|---|---|
inputUid | string | The uid of a |
Sets the current recording input.
void
A Promise
that is resolved if successful or rejected if not.
startRecordingAtTime(seconds)
Parameter | Type | Description |
---|---|---|
seconds | number | The time in seconds to start recording at. |
Starts the recording at the given time.
void
Audio.useAudioSampleListener(player, listener)
Parameter | Type |
---|---|
player | AudioPlayer |
listener | (data: AudioSample) => void |
void
PermissionResponse
An object obtained by permissions get and request functions.
PermissionResponse Properties
Name | Type | Description |
---|---|---|
canAskAgain | boolean | Indicates if user can be asked again for specific permission. If not, one should be directed to the Settings app in order to enable/disable the permission. |
expires | PermissionExpiration | Determines time when the permission expires. |
granted | boolean | A convenience boolean that indicates if the permission is granted. |
status | PermissionStatus | Determines the status of the permission. |
AndroidAudioEncoder
Literal Type: string
Acceptable values are: 'default'
| 'amr_nb'
| 'amr_wb'
| 'aac'
| 'he_aac'
| 'aac_eld'
AndroidOutputFormat
Literal Type: string
Acceptable values are: 'default'
| '3gp'
| 'mpeg4'
| 'amrnb'
| 'amrwb'
| 'aac_adts'
| 'mpeg2ts'
| 'webm'
AudioEvents
Name | Type | Description |
---|---|---|
audioSampleUpdate | (data: AudioSample) => void | - |
playbackStatusUpdate | (status: AudioStatus) => void | - |
AudioMode
Name | Type | Description |
---|---|---|
allowsRecording | boolean | - |
interruptionMode | InterruptionMode | - |
playsInSilentMode | boolean | - |
shouldPlayInBackground | boolean | - |
shouldRouteThroughEarpiece | boolean | - |
AudioSource
Type: string
or null
or object shaped as below:
Name | Type | Description |
---|---|---|
headers (optional) | Record<string, string> | An object representing the HTTP headers to send along with the request for a remote audio source.
On web requires the |
uri (optional) | string | A string representing the resource identifier for the audio, which could be an HTTPS address, a local file path, or the name of a static audio file resource. |
AudioStatus
Name | Type | Description |
---|---|---|
currentTime | number | - |
duration | number | - |
id | number | - |
isBuffering | boolean | - |
isLoaded | boolean | - |
loop | boolean | - |
mute | boolean | - |
playbackRate | number | - |
playbackState | string | - |
playing | boolean | - |
reasonForWaitingToPlay | string | - |
shouldCorrectPitch | boolean | - |
timeControlStatus | string | - |
BitRateStrategy
Literal Type: string
Acceptable values are: 'constant'
| 'longTermAverage'
| 'variableConstrained'
| 'variable'
InterruptionMode
Literal Type: string
Acceptable values are: 'mixWithOthers'
| 'doNotMix'
| 'duckOthers'
PermissionExpiration
Literal Type: multiple types
Permission expiration time. Currently, all permissions are granted permanently.
Acceptable values are: 'never'
| number
PitchCorrectionQuality
Literal Type: string
Acceptable values are: 'low'
| 'medium'
| 'high'
RecorderState
Name | Type | Description |
---|---|---|
canRecord | boolean | - |
durationMillis | number | - |
isRecording | boolean | - |
mediaServicesDidReset | boolean | - |
metering (optional) | number | - |
url | string | null | - |
RecordingEvents
Name | Type | Description |
---|---|---|
recordingStatusUpdate | (status: RecordingStatus) => void | - |
RecordingOptions
Name | Type | Description |
---|---|---|
android | RecordingOptionsAndroid | Recording options for the Android platform. |
bitRate | number | The desired bit rate. Example |
extension | string | The desired file extension. Example |
ios | RecordingOptionsIos | Recording options for the iOS platform. |
numberOfChannels | number | The desired number of channels. Example |
sampleRate | number | The desired sample rate. Example |
web (optional) | RecordingOptionsWeb | Recording options for the Web platform. |
RecordingOptionsAndroid
Name | Type | Description |
---|---|---|
audioEncoder | AndroidAudioEncoder | The desired audio encoder. See the |
extension (optional) | string | The desired file extension. Example |
maxFileSize (optional) | number | The desired maximum file size in bytes, after which the recording will stop (but Example
|
outputFormat | AndroidOutputFormat | The desired file format. See the |
sampleRate (optional) | number | The desired sample rate. Example |
RecordingOptionsIos
Name | Type | Description |
---|---|---|
audioQuality | AudioQuality | number | The desired audio quality. See the |
bitDepthHint (optional) | number | The desired bit depth hint. Example |
bitRateStrategy (optional) | number | The desired bit rate strategy. See the next section for an enumeration of all valid values of |
extension (optional) | string | The desired file extension. Example |
linearPCMBitDepth (optional) | number | The desired PCM bit depth. Example |
linearPCMIsBigEndian (optional) | boolean | A boolean describing if the PCM data should be formatted in big endian. |
linearPCMIsFloat (optional) | boolean | A boolean describing if the PCM data should be encoded in floating point or integral values. |
outputFormat (optional) | string | IOSOutputFormat | number | The desired file format. See the |
sampleRate (optional) | number | The desired sample rate. Example |
RecordingOptionsWeb
Name | Type | Description |
---|---|---|
bitsPerSecond (optional) | number | - |
mimeType (optional) | string | - |
RecordingStatus
Name | Type | Description |
---|---|---|
error | string | null | - |
hasError | boolean | - |
id | number | - |
isFinished | boolean | - |
url | string | null | - |
MIN
AudioQuality.MIN = 0
LOW
AudioQuality.LOW = 32
MEDIUM
AudioQuality.MEDIUM = 64
HIGH
AudioQuality.HIGH = 96
MAX
AudioQuality.MAX = 127
MPEGLAYER1
IOSOutputFormat.MPEGLAYER1 = ".mp1"
MPEGLAYER2
IOSOutputFormat.MPEGLAYER2 = ".mp2"
MPEGLAYER3
IOSOutputFormat.MPEGLAYER3 = ".mp3"
MPEG4AAC
IOSOutputFormat.MPEG4AAC = "aac "
MPEG4AAC_ELD
IOSOutputFormat.MPEG4AAC_ELD = "aace"
MPEG4AAC_ELD_SBR
IOSOutputFormat.MPEG4AAC_ELD_SBR = "aacf"
MPEG4AAC_ELD_V2
IOSOutputFormat.MPEG4AAC_ELD_V2 = "aacg"
MPEG4AAC_HE
IOSOutputFormat.MPEG4AAC_HE = "aach"
MPEG4AAC_LD
IOSOutputFormat.MPEG4AAC_LD = "aacl"
MPEG4AAC_HE_V2
IOSOutputFormat.MPEG4AAC_HE_V2 = "aacp"
MPEG4AAC_SPATIAL
IOSOutputFormat.MPEG4AAC_SPATIAL = "aacs"
AC3
IOSOutputFormat.AC3 = "ac-3"
AES3
IOSOutputFormat.AES3 = "aes3"
APPLELOSSLESS
IOSOutputFormat.APPLELOSSLESS = "alac"
ALAW
IOSOutputFormat.ALAW = "alaw"
AUDIBLE
IOSOutputFormat.AUDIBLE = "AUDB"
60958AC3
IOSOutputFormat.60958AC3 = "cac3"
MPEG4CELP
IOSOutputFormat.MPEG4CELP = "celp"
ENHANCEDAC3
IOSOutputFormat.ENHANCEDAC3 = "ec-3"
MPEG4HVXC
IOSOutputFormat.MPEG4HVXC = "hvxc"
ILBC
IOSOutputFormat.ILBC = "ilbc"
APPLEIMA4
IOSOutputFormat.APPLEIMA4 = "ima4"
LINEARPCM
IOSOutputFormat.LINEARPCM = "lpcm"
MACE3
IOSOutputFormat.MACE3 = "MAC3"
MACE6
IOSOutputFormat.MACE6 = "MAC6"
AMR
IOSOutputFormat.AMR = "samr"
AMR_WB
IOSOutputFormat.AMR_WB = "sawb"
DVIINTELIMA
IOSOutputFormat.DVIINTELIMA = 1836253201
MICROSOFTGSM
IOSOutputFormat.MICROSOFTGSM = 1836253233
QUALCOMM
IOSOutputFormat.QUALCOMM = "Qclp"
QDESIGN2
IOSOutputFormat.QDESIGN2 = "QDM2"
QDESIGN
IOSOutputFormat.QDESIGN = "QDMC"
MPEG4TWINVQ
IOSOutputFormat.MPEG4TWINVQ = "twvq"
ULAW
IOSOutputFormat.ULAW = "ulaw"
UNDETERMINED
PermissionStatus.UNDETERMINED = "undetermined"
User hasn't granted or denied the permission yet.