• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Using AVPlayer for Audio Playback
2
3The AVPlayer is used to play raw media assets in an end-to-end manner. In this topic, you will learn how to use the AVPlayer to play a complete piece of music.
4
5If you want the application to continue playing the music in the background or when the screen is off, you must use the [AVSession](avsession-overview.md) and [continuous task](../task-management/continuous-task.md) to prevent the playback from being forcibly interrupted by the system.
6
7
8The full playback process includes creating an **AVPlayer** instance, setting the media asset to play, setting playback parameters (volume, speed, and focus mode), controlling playback (play, pause, seek, and stop), resetting the playback configuration, and releasing the instance.
9
10
11During application development, you can use the **state** attribute of the AVPlayer to obtain the AVPlayer state or call **on('stateChange')** to listen for state changes. If the application performs an operation when the AVPlayer is not in the given state, the system may throw an exception or generate other undefined behavior.
12
13
14**Figure 1** Playback state transition
15![Playback status change](figures/playback-status-change.png)
16
17For details about the state, see [AVPlayerState](../reference/apis/js-apis-media.md#avplayerstate9). When the AVPlayer is in the **prepared**, **playing**, **paused**, or **completed** state, the playback engine is working and a large amount of RAM is occupied. If your application does not need to use the AVPlayer, call **reset()** or **release()** to release the instance.
18
19## How to Develop
20
21Read [AVPlayer](../reference/apis/js-apis-media.md#avplayer9) for the API reference.
22
231. Call **createAVPlayer()** to create an **AVPlayer** instance. The AVPlayer is the **idle** state.
24
252. Set the events to listen for, which will be used in the full-process scenario. The table below lists the supported events.
26   | Event Type| Description|
27   | -------- | -------- |
28   | stateChange | Mandatory; used to listen for changes of the **state** attribute of the AVPlayer.|
29   | error | Mandatory; used to listen for AVPlayer errors.|
30   | durationUpdate | Used to listen for progress bar updates to refresh the media asset duration.|
31   | timeUpdate | Used to listen for the current position of the progress bar to refresh the current time.|
32   | seekDone | Used to listen for the completion status of the **seek()** request.<br>This event is reported when the AVPlayer seeks to the playback position specified in **seek()**.|
33   | speedDone | Used to listen for the completion status of the **setSpeed()** request.<br>This event is reported when the AVPlayer plays music at the speed specified in **setSpeed()**.|
34   | volumeChange | Used to listen for the completion status of the **setVolume()** request.<br>This event is reported when the AVPlayer plays music at the volume specified in **setVolume()**.|
35   | bufferingUpdate | Used to listen for network playback buffer information. This event reports the buffer percentage and playback progress.|
36   | audioInterrupt | Used to listen for audio interruption. This event is used together with the **audioInterruptMode** attribute.<br>This event is reported when the current audio playback is interrupted by another (for example, when a call is coming), so the application can process the event in time.|
37
383. Set the media asset URL. The AVPlayer enters the **initialized** state.
39   > **NOTE**
40   >
41   > The URL in the code snippet below is for reference only. You need to check the media asset validity and set the URL based on service requirements.
42   >
43   > - If local files are used for playback, ensure that the files are available and the application sandbox path is used for access. For details about how to obtain the application sandbox path, see [Obtaining Application File Paths](../application-models/application-context-stage.md#obtaining-application-file-paths). For details about the application sandbox and how to push files to the application sandbox, see [File Management](../file-management/app-sandbox-directory.md).
44   >
45   > - If a network playback path is used, you must request the ohos.permission.INTERNET [permission](../security/accesstoken-guidelines.md).
46   >
47   > - You can also use **ResourceManager.getRawFd** to obtain the file descriptor of a file packed in the HAP file. For details, see [ResourceManager API Reference](../reference/apis/js-apis-resource-manager.md#getrawfd9).
48   >
49   > - The [playback formats and protocols](avplayer-avrecorder-overview.md#supported-formats-and-protocols) in use must be those supported by the system.
50
514. Call **prepare()** to switch the AVPlayer to the **prepared** state. In this state, you can obtain the duration of the media asset to play and set the volume.
52
535. Call **play()**, **pause()**, **seek()**, and **stop()** to perform audio playback control as required.
54
556. (Optional) Call **reset()** to reset the AVPlayer. The AVPlayer enters the **idle** state again and you can change the media asset URL.
56
577. Call **release()** to switch the AVPlayer to the **released** state. Now your application exits the playback.
58
59## Sample Code
60
61Refer to the sample code below to play a complete piece of music.
62
63```ts
64import media from '@ohos.multimedia.media';
65import fs from '@ohos.file.fs';
66import common from '@ohos.app.ability.common';
67import { BusinessError } from '@ohos.base';
68
69export class AVPlayerDemo {
70  private count: number = 0;
71  private isSeek: boolean = true; // Specify whether the seek operation is supported.
72  private fileSize: number = -1;
73  private fd: number = 0;
74  // Set AVPlayer callback functions.
75  setAVPlayerCallback(avPlayer: media.AVPlayer) {
76    // Callback function for the seek operation.
77    avPlayer.on('seekDone', (seekDoneTime: number) => {
78      console.info(`AVPlayer seek succeeded, seek time is ${seekDoneTime}`);
79    })
80    // Callback function for errors. If an error occurs during the operation on the AVPlayer, reset() is called to reset the AVPlayer.
81    avPlayer.on('error', (err: BusinessError) => {
82      console.error(`Invoke avPlayer failed, code is ${err.code}, message is ${err.message}`);
83      avPlayer.reset(); // Call reset() to reset the AVPlayer, which enters the idle state.
84    })
85    // Callback function for state changes.
86    avPlayer.on('stateChange', async (state: string, reason: media.StateChangeReason) => {
87      switch (state) {
88        case 'idle': // This state is reported upon a successful callback of reset().
89          console.info('AVPlayer state idle called.');
90          avPlayer.release(); // Call release() to release the instance.
91          break;
92        case 'initialized': // This state is reported when the AVPlayer sets the playback source.
93          console.info('AVPlayer state initialized called.');
94          avPlayer.prepare();
95          break;
96        case 'prepared': // This state is reported upon a successful callback of prepare().
97          console.info('AVPlayer state prepared called.');
98          avPlayer.play(); // Call play() to start playback.
99          break;
100        case 'playing': // This state is reported upon a successful callback of play().
101          console.info('AVPlayer state playing called.');
102          if (this.count !== 0) {
103            if (this.isSeek) {
104              console.info('AVPlayer start to seek.');
105              avPlayer.seek(avPlayer.duration); // Call seek() to seek to the end of the audio clip.
106            } else {
107              // When the seek operation is not supported, the playback continues until it reaches the end.
108              console.info('AVPlayer wait to play end.');
109            }
110          } else {
111            avPlayer.pause(); // Call pause() to pause the playback.
112          }
113          this.count++;
114          break;
115        case 'paused': // This state is reported upon a successful callback of pause().
116          console.info('AVPlayer state paused called.');
117          avPlayer.play(); // Call play() again to start playback.
118          break;
119        case 'completed': // This state is reported upon the completion of the playback.
120          console.info('AVPlayer state completed called.');
121          avPlayer.stop(); // Call stop() to stop the playback.
122          break;
123        case 'stopped': // This state is reported upon a successful callback of stop().
124          console.info('AVPlayer state stopped called.');
125          avPlayer.reset(); // Call reset() to reset the AVPlayer state.
126          break;
127        case 'released':
128          console.info('AVPlayer state released called.');
129          break;
130        default:
131          console.info('AVPlayer state unknown called.');
132          break;
133      }
134    })
135  }
136
137  // The following demo shows how to use the file system to open the sandbox address, obtain the media file address, and play the media file using the URL attribute.
138  async avPlayerUrlDemo() {
139    // Create an AVPlayer instance.
140    let avPlayer: media.AVPlayer = await media.createAVPlayer();
141    // Set a callback function for state changes.
142    this.setAVPlayerCallback(avPlayer);
143    let fdPath = 'fd://';
144    // Obtain the sandbox address filesDir through UIAbilityContext. The stage model is used as an example.
145    let context = getContext(this) as common.UIAbilityContext;
146    let pathDir = context.filesDir;
147    let path = pathDir + '/01.mp3';
148    // Open the corresponding file address to obtain the file descriptor and assign a value to the URL to trigger the reporting of the initialized state.
149    let file = await fs.open(path);
150    fdPath = fdPath + '' + file.fd;
151    this.isSeek = true; // The seek operation is supported.
152    avPlayer.url = fdPath;
153  }
154
155  // The following demo shows how to use resourceManager to obtain the media file packed in the HAP file and play the media file by using the fdSrc attribute.
156  async avPlayerFdSrcDemo() {
157    // Create an AVPlayer instance.
158    let avPlayer: media.AVPlayer = await media.createAVPlayer();
159    // Set a callback function for state changes.
160    this.setAVPlayerCallback(avPlayer);
161    // Call getRawFd of the resourceManager member of UIAbilityContext to obtain the media asset URL.
162    // The return type is {fd,offset,length}, where fd indicates the file descriptor address of the HAP file, offset indicates the media asset offset, and length indicates the duration of the media asset to play.
163    let context = getContext(this) as common.UIAbilityContext;
164    let fileDescriptor = await context.resourceManager.getRawFd('01.mp3');
165    let avFileDescriptor: media.AVFileDescriptor =
166      { fd: fileDescriptor.fd, offset: fileDescriptor.offset, length: fileDescriptor.length };
167    this.isSeek = true; // The seek operation is supported.
168    // Assign a value to fdSrc to trigger the reporting of the initialized state.
169    avPlayer.fdSrc = avFileDescriptor;
170  }
171
172  // The following demo shows how to use the file system to open the sandbox address, obtain the media file address, and play the media file with the seek operation using the dataSrc attribute.
173  async avPlayerDataSrcSeekDemo() {
174    // Create an AVPlayer instance.
175    let avPlayer: media.AVPlayer = await media.createAVPlayer();
176    // Set a callback function for state changes.
177    this.setAVPlayerCallback(avPlayer);
178    // dataSrc indicates the playback source address. When the seek operation is supported, fileSize indicates the size of the file to be played. The following describes how to assign a value to fileSize.
179    let src: media.AVDataSrcDescriptor = {
180      fileSize: -1,
181      callback: (buf: ArrayBuffer, length: number, pos: number | undefined) => {
182        let num = 0;
183        if (buf == undefined || length == undefined || pos == undefined) {
184          return -1;
185        }
186        num = fs.readSync(this.fd, buf, { offset: pos, length: length });
187        if (num > 0 && (this.fileSize >= pos)) {
188          return num;
189        }
190        return -1;
191      }
192    }
193    let context = getContext(this) as common.UIAbilityContext;
194    // Obtain the sandbox address filesDir through UIAbilityContext. The stage model is used as an example.
195    let pathDir = context.filesDir;
196    let path = pathDir  + '/01.mp3';
197    await fs.open(path).then((file: fs.File) => {
198      this.fd = file.fd;
199    })
200    // Obtain the size of the file to be played.
201    this.fileSize = fs.statSync(path).size;
202    src.fileSize = this.fileSize;
203    this.isSeek = true; // The seek operation is supported.
204    avPlayer.dataSrc = src;
205  }
206
207  // The following demo shows how to use the file system to open the sandbox address, obtain the media file address, and play the media file without the seek operation using the dataSrc attribute.
208  async avPlayerDataSrcNoSeekDemo() {
209    // Create an AVPlayer instance.
210    let avPlayer: media.AVPlayer = await media.createAVPlayer();
211    // Set a callback function for state changes.
212    this.setAVPlayerCallback(avPlayer);
213    let context = getContext(this) as common.UIAbilityContext;
214    let src: media.AVDataSrcDescriptor = {
215      fileSize: -1,
216      callback: (buf: ArrayBuffer, length: number) => {
217        let num = 0;
218        if (buf == undefined || length == undefined) {
219          return -1;
220        }
221        num = fs.readSync(this.fd, buf);
222        if (num > 0) {
223          return num;
224        }
225        return -1;
226      }
227    }
228    // Obtain the sandbox address filesDir through UIAbilityContext. The stage model is used as an example.
229    let pathDir = context.filesDir;
230    let path = pathDir  + '/01.mp3';
231    await fs.open(path).then((file: fs.File) => {
232      this.fd = file.fd;
233    })
234    this.isSeek = false; // The seek operation is not supported.
235    avPlayer.dataSrc = src;
236  }
237
238  // The following demo shows how to play live streams by setting the network address through the URL.
239  async avPlayerLiveDemo() {
240    // Create an AVPlayer instance.
241    let avPlayer: media.AVPlayer = await media.createAVPlayer();
242    // Set a callback function for state changes.
243    this.setAVPlayerCallback(avPlayer);
244    this.isSeek = false; // The seek operation is not supported.
245    avPlayer.url = 'http://xxx.xxx.xxx.xxx:xx/xx/index.m3u8';
246  }
247}
248```
249