HarmonyOS Audio Development Guide: Use AVPlayer to develop audio playback functions

How to choose an audio playback development method

In the HarmonyOS system, a variety of APIs provide support for audio playback development. Different APIs are suitable for different audio data formats, audio resource sources, audio usage scenarios, and even different development languages. Therefore, choosing an appropriate audio playback API can help reduce development workload and achieve better audio playback effects.

●  AVPlayer : A relatively complete audio and video playback ArkTS/JS API that integrates streaming media and local resource parsing, media resource decapsulation, audio decoding and audio output functions. It can be used to directly play audio files in mp3, m4a and other formats. It does not support direct playback of PCM format files.

●  AudioRenderer : ArkTS/JS API for audio output. It only supports PCM format and requires the application to continuously write audio data to work. Applications can add data preprocessing before input, such as setting the sampling rate and bit width of audio files, etc. This requires developers to have basic knowledge of audio processing and is suitable for the development of more professional and diverse media playback applications.

●  OpenSL ES : A set of cross-platform standardized audio Native API. It is the only audio Native API at this stage. It also provides audio output capabilities and only supports PCM format. It is suitable for porting from other embedded platforms or relying on the Native layer to implement audio. The output function is used by the playback application.

● In audio playback, applications often need to use some quick and short sound effects, such as camera shutter sound effects, button sound effects, game shooting sound effects, etc. Currently, AVPlayer can only be used to play audio files instead. Related interfaces will be launched in subsequent versions of HarmonyOS. to support this scenario.

Use AVPlayer to develop audio playback functions

Using AVPlayer, you can achieve end-to-end playback of original media resources. This development guide will use the complete playback of a piece of music as an example to explain to developers the related functions of AVPlayer audio playback.

The entire playback process includes: creating AVPlayer, setting playback resources, setting playback parameters (volume/double speed/focus mode), playback control (play/pause/jump/stop), resetting, and destroying resources.

During application development, developers can actively obtain the current state through the state attribute of AVPlayer or use the on('stateChange') method to monitor state changes. If your app performs operations while the audio player is in an error state, the system might throw exceptions or generate other undefined behavior.

Figure 1 Schematic diagram of playback status changes

For detailed description of the state, please refer to AVPlayerState . When the playback is in the prepared/playing/paused/completed state, the playback engine is in working state, which requires more running memory of the system. When the client is not using the player temporarily, call reset() or release() to recycle memory resources and make good resource utilization.

Development steps and precautions

For detailed API description, please refer to AVPlayer API Reference .

1. Create an instance createAVPlayer(), and AVPlayer initializes the idle state.

2. Set the listening events required by the business and use them in full-process scenarios. Supported listening events include:

event type illustrate
stateChange Necessary events to monitor changes in the player's state attribute.
error Necessary events to monitor player error messages.
durationUpdate Used for progress bars, monitoring the length of the progress bar, and the duration of refreshing resources.
timeUpdate Used for progress bars, monitor the current position of the progress bar and refresh the current time.
seekDone Respond to API calls and monitor the completion of seek() requests. After using seek() to jump to the specified playback position, if the seek operation is successful, this event will be reported.
speedDone Respond to API calls and monitor the completion of setSpeed() requests. After using setSpeed() to set the playback speed, if the setSpeed ​​operation is successful, this event will be reported.
volumeChange Respond to API calls and monitor the completion of setVolume() requests. After using setVolume() to adjust the playback volume, if the setVolume operation is successful, this event will be reported.
bufferingUpdate Used for network playback, monitoring network playback buffer information, and used to report buffering percentage and cache playback progress.
audioInterrupt Monitor audio focus switching information and use it with the attribute audioInterruptMode. If there are multiple audios being played on the current device, this event will be reported when the audio focus is switched (that is, playing other media such as calls, etc.), and the application can handle it in a timely manner.

3. Set resources: Set the attribute url, and AVPlayer enters the initialized state.

illustrate

The URL in the code example below is for illustration only. Developers need to confirm the validity of the resource and set it according to the actual situation:

a. If you use local resources to play, you must confirm that the resource files are available and use the application sandbox path to access the corresponding resources. See Obtaining the Application File Path . For an introduction to the application sandbox and how to push files to the application sandbox, please refer to File Management .

b. If you use the network playback path, you need to apply for the relevant permission : ohos.permission.INTERNET.

c. If you use ResourceManager.getRawFd to open the HAP resource file descriptor, please refer to the ResourceManager API reference for usage .

d. Supported playback formats and protocols need to be used .

4. Prepare to play: Call prepare(), and AVPlayer enters the prepared state. At this time, you can get the duration and set the volume.

5. Audio playback control: play(), pause(), jump seek(), stop stop() and other operations.

6. (Optional) Replace resources: Call reset() to reset the resources. AVPlayer re-enters the idle state, allowing the resource URL to be changed.

7. Exit playback: Call release() to destroy the instance, AVPlayer enters the released state, and exits playback.

Complete example

Use the following example to play a piece of music in its entirety.

import media from '@ohos.multimedia.media';
import fs from '@ohos.file.fs';
import common from '@ohos.app.ability.common';

export class AVPlayerDemo {
  private avPlayer;
  private count: number = 0;

  // 注册avplayer回调函数
  setAVPlayerCallback() {
    // seek操作结果回调函数
    this.avPlayer.on('seekDone', (seekDoneTime) => {
      console.info(`AVPlayer seek succeeded, seek time is ${seekDoneTime}`);
    })
    // error回调监听函数,当avPlayer在操作过程中出现错误时调用reset接口触发重置流程
    this.avPlayer.on('error', (err) => {
      console.error(`Invoke avPlayer failed, code is ${err.code}, message is ${err.message}`);
      this.avPlayer.reset(); // 调用reset重置资源,触发idle状态
    })
    // 状态机变化回调函数
    this.avPlayer.on('stateChange', async (state, reason) => {
      switch (state) {
        case 'idle': // 成功调用reset接口后触发该状态机上报
          console.info('AVPlayer state idle called.');
          this.avPlayer.release(); // 调用release接口销毁实例对象
          break;
        case 'initialized': // avplayer 设置播放源后触发该状态上报
          console.info('AVPlayerstate initialized called.');
          this.avPlayer.prepare().then(() => {
            console.info('AVPlayer prepare succeeded.');
          }, (err) => {
            console.error(`Invoke prepare failed, code is ${err.code}, message is ${err.message}`);
          });
          break;
        case 'prepared': // prepare调用成功后上报该状态机
          console.info('AVPlayer state prepared called.');
          this.avPlayer.play(); // 调用播放接口开始播放
          break;
        case 'playing': // play成功调用后触发该状态机上报
          console.info('AVPlayer state playing called.');
          if (this.count !== 0) {
            console.info('AVPlayer start to seek.');
            this.avPlayer.seek(this.avPlayer.duration); //seek到音频末尾
          } else {
            this.avPlayer.pause(); // 调用暂停接口暂停播放
          }
          this.count++;
          break;
        case 'paused': // pause成功调用后触发该状态机上报
          console.info('AVPlayer state paused called.');
          this.avPlayer.play(); // 再次播放接口开始播放
          break;
        case 'completed': // 播放结束后触发该状态机上报
          console.info('AVPlayer state completed called.');
          this.avPlayer.stop(); //调用播放结束接口
          break;
        case 'stopped': // stop接口成功调用后触发该状态机上报
          console.info('AVPlayer state stopped called.');
          this.avPlayer.reset(); // 调用reset接口初始化avplayer状态
          break;
        case 'released':
          console.info('AVPlayer state released called.');
          break;
        default:
          console.info('AVPlayer state unknown called.');
          break;
      }
    })
  }

  // 以下demo为使用fs文件系统打开沙箱地址获取媒体文件地址并通过url属性进行播放示例
  async avPlayerUrlDemo() {
    // 创建avPlayer实例对象
    this.avPlayer = await media.createAVPlayer();
    // 创建状态机变化回调函数
    this.setAVPlayerCallback();
    let fdPath = 'fd://';
    // 通过UIAbilityContext获取沙箱地址filesDir,以下为Stage模型获方式,如需在FA模型上获取请参考《访问应用沙箱》获取地址
    let context = getContext(this) as common.UIAbilityContext;
    let pathDir = context.filesDir;
    let path = pathDir + '/01.mp3';
    // 打开相应的资源文件地址获取fd,并为url赋值触发initialized状态机上报
    let file = await fs.open(path);
    fdPath = fdPath + '' + file.fd;
    this.avPlayer.url = fdPath;
  }

  // 以下demo为使用资源管理接口获取打包在HAP内的媒体资源文件并通过fdSrc属性进行播放示例
  async avPlayerFdSrcDemo() {
    // 创建avPlayer实例对象
    this.avPlayer = await media.createAVPlayer();
    // 创建状态机变化回调函数
    this.setAVPlayerCallback();
    // 通过UIAbilityContext的resourceManager成员的getRawFd接口获取媒体资源播放地址
    // 返回类型为{fd,offset,length},fd为HAP包fd地址,offset为媒体资源偏移量,length为播放长度
    let context = getContext(this) as common.UIAbilityContext;
    let fileDescriptor = await context.resourceManager.getRawFd('01.mp3');
    // 为fdSrc赋值触发initialized状态机上报
    this.avPlayer.fdSrc = fileDescriptor;
  }
}

Guess you like

Origin blog.csdn.net/HarmonyOSDev/article/details/133927594