1--- 2title: AV 3description: A universal library that provides separate APIs for Audio and Video playback. 4sourceCodeUrl: 'https://github.com/expo/expo/tree/main/packages/expo-av' 5packageName: 'expo-av' 6iconUrl: '/static/images/packages/expo-av.png' 7--- 8 9import { APIInstallSection } from '~/components/plugins/InstallSection'; 10import APISection from '~/components/plugins/APISection'; 11import PlatformsSection from '~/components/plugins/PlatformsSection'; 12import { 13 ConfigReactNative, 14 ConfigPluginExample, 15 ConfigPluginProperties, 16} from '~/components/plugins/ConfigSection'; 17import { AndroidPermissions, IOSPermissions } from '~/components/plugins/permissions'; 18 19The [`Audio.Sound`](audio.mdx) objects and [`Video`](video.mdx) components share a unified imperative API for media playback. 20 21Note that for `Video`, all of the operations are also available via props on the component. However, we recommend using this imperative playback API for most applications where finer control over the state of the video playback is needed. 22 23Try the [playlist example app](http://expo.dev/@community/playlist) (source code is [on GitHub](https://github.com/expo/playlist-example)) to see an example usage of the playback API for both `Audio.Sound` and `Video`. 24 25<PlatformsSection android emulator ios simulator web /> 26 27## Installation 28 29<APIInstallSection /> 30 31## Configuration in app.json/app.config.js 32 33You can configure `expo-av` 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. 34 35<ConfigPluginExample> 36 37```json app.json 38{ 39 "expo": { 40 "plugins": [ 41 [ 42 "expo-av", 43 { 44 "microphonePermission": "Allow $(PRODUCT_NAME) to access your microphone." 45 } 46 ] 47 ] 48 } 49} 50``` 51 52</ConfigPluginExample> 53 54<ConfigPluginProperties 55 properties={[ 56 { 57 name: 'microphonePermission', 58 platform: 'ios', 59 description: 60 'A string to set the [`NSMicrophoneUsageDescription`](#permission-nsmicrophoneusagedescription) permission message.', 61 default: '"Allow $(PRODUCT_NAME) to access your microphone"', 62 }, 63 ]} 64/> 65 66<ConfigReactNative> 67 68Learn how to configure the native projects in the [installation instructions in the `expo-av` repository](https://github.com/expo/expo/tree/main/packages/expo-av#installation-in-bare-react-native-projects). 69 70</ConfigReactNative> 71 72## Usage 73 74On this page, we reference operations on `playbackObject`s. Here is an example of obtaining access to the reference for both sound and video: 75 76### Example: `Audio.Sound` 77 78```javascript 79await Audio.setAudioModeAsync({ playsInSilentModeIOS: true }); 80 81const playbackObject = new Audio.Sound(); 82// OR 83const { sound: playbackObject } = await Audio.Sound.createAsync( 84 { uri: 'http://foo/bar.mp3' }, 85 { shouldPlay: true } 86); 87... 88``` 89 90See the [audio documentation](audio.mdx) for further information on `Audio.Sound.createAsync()`. 91 92### Example: `Video` 93 94```javascript 95... 96_handleVideoRef = component => { 97 const playbackObject = component; 98 ... 99} 100 101... 102 103render() { 104 return ( 105 ... 106 <Video 107 ref={this._handleVideoRef} 108 ... 109 /> 110 ... 111 ) 112} 113... 114``` 115 116See the [video documentation](video.mdx) for further information. 117 118### Example: `setOnPlaybackStatusUpdate()` 119 120```javascript 121_onPlaybackStatusUpdate = playbackStatus => { 122 if (!playbackStatus.isLoaded) { 123 // Update your UI for the unloaded state 124 if (playbackStatus.error) { 125 console.log(`Encountered a fatal error during playback: ${playbackStatus.error}`); 126 // Send Expo team the error on Slack or the forums so we can help you debug! 127 } 128 } else { 129 // Update your UI for the loaded state 130 131 if (playbackStatus.isPlaying) { 132 // Update your UI for the playing state 133 } else { 134 // Update your UI for the paused state 135 } 136 137 if (playbackStatus.isBuffering) { 138 // Update your UI for the buffering state 139 } 140 141 if (playbackStatus.didJustFinish && !playbackStatus.isLooping) { 142 // The player has just finished playing and will stop. Maybe you want to play something else? 143 } 144 145 ... // etc 146 } 147}; 148 149... // Load the playbackObject and obtain the reference. 150playbackObject.setOnPlaybackStatusUpdate(this._onPlaybackStatusUpdate); 151... 152``` 153 154### Example: Loop media exactly 20 times 155 156```javascript 157const N = 20; 158... 159 160_onPlaybackStatusUpdate = (playbackStatus) => { 161 if (playbackStatus.didJustFinish) { 162 if (this.state.numberOfLoops == N - 1) { 163 playbackObject.setIsLooping(false); 164 } 165 this.setState({ numberOfLoops: this.state.numberOfLoops + 1 }); 166 } 167}; 168 169... 170this.setState({ numberOfLoops: 0 }); 171... // Load the playbackObject and obtain the reference. 172playbackObject.setOnPlaybackStatusUpdate(this._onPlaybackStatusUpdate); 173playbackObject.setIsLooping(true); 174... 175``` 176 177## What is seek tolerance and why would I want to use it [iOS only] 178 179When asked to seek an A/V item, native player in iOS sometimes may seek to a slightly different time. This technique, mentioned in [Apple documentation](https://developer.apple.com/documentation/avfoundation/avplayer/1387741-seek#discussion), is used to shorten the time of the `seekTo` call (the player may decide to play immediately from a different time than requested, instead of decoding the exact requested part and playing it with the decoding delay). 180 181If precision is important, you can specify the tolerance with which the player will seek. However, this will result in an increased delay. 182 183## API 184 185```js 186import { Audio, Video } from 'expo-av'; 187``` 188 189<APISection packageName="expo-av" apiName="AV" /> 190 191## Permissions 192 193### Android 194 195You must add the following permissions to your **app.json** inside the [`expo.android.permissions`](/versions/latest/config/app/#permissions) array. 196 197<AndroidPermissions permissions={['RECORD_AUDIO']} /> 198 199### iOS 200 201The following usage description keys are used by this library: 202 203<IOSPermissions permissions={['NSMicrophoneUsageDescription']} /> 204