xref: /expo/docs/pages/versions/unversioned/sdk/av.mdx (revision 53eb0d93)
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