5

跟着小白一起学鸿蒙—学习使用新媒体播放接口

 1 year ago
source link: https://www.51cto.com/article/751253.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

跟着小白一起学鸿蒙—学习使用新媒体播放接口

作者:左翼风发 2023-04-06 09:18:52
从3.2开始OpenHarmony推出了AVPlayer和AVRecorder接口,之前的VideoPlayer、AudioPlayer这些接口会停止维护,所以我们今天学习下怎么使用AVPlayer接口。
e8dca6f49f81edd4de1459418c2b0199997a79.png

​想了解更多关于开源的内容,请访问:​

​51CTO 开源基础软件社区​

​https://ost.51cto.com​

简介

媒体子系统是OpenHarmony中重要的子系统,可以提供音视频播放能力。媒体子系统为开发者提供一套简单且易于理解的接口,使得开发者能够方便接入系统并使用系统的媒体资源。媒体子系统提供以下常用功能:

音视频播放(AVPlayer9+),AudioPlayer6+和VideoPlayer8+整合,升级了状态机和错误码,推荐使用。

音视频录制(AVRecorder9+),AudioRecorder6+和VideoRecorder9+整合,推荐使用。

音频播放(AudioPlayer6+),AVPlayer9+发布后停止维护,请使用AVPlayer9+。

视频播放(VideoPlayer8+),AVPlayer9+发布后停止维护,请使用AVPlayer9+。

音频录制(AudioRecorder6+),AVRecorder9+发布后停止维护,请使用AVRecorder9+。

视频录制(VideoRecorder9+),AVRecorder9+发布后停止维护,请使用AVRecorder9+。

从3.2开始OpenHarmony推出了AVPlayer和AVRecorder接口,之前的VideoPlayer、AudioPlayer这些接口会停止维护,所以我们今天学习下怎么使用AVPlayer接口。

import media from '@ohos.multimedia.media';
  • 创建avplayer
this.avPlayer = await media.createAVPlayer()

如上,我们使用的是promise接口,对应的接口定义为:

/**
   * Creates an AVPlayer instance.
   * @since 9
   * @syscap SystemCapability.Multimedia.Media.AVPlayer
   * @param callback Callback used to return AVPlayer instance if the operation is successful; returns null otherwise.
   * @throws { BusinessError } 5400101 - No memory. Return by callback.
   */
   function createAVPlayer(callback: AsyncCallback<AVPlayer>): void;

  /**
   * Creates an AVPlayer instance.
   * @since 9
   * @syscap SystemCapability.Multimedia.Media.AVPlayer
   * @returns A Promise instance used to return AVPlayer instance if the operation is successful; returns null otherwise.
   * @throws { BusinessError } 5400101 - No memory. Return by promise.
   */
   function createAVPlayer() : Promise<AVPlayer>;
  • 注册avplayer回调
//注册状态变化回调,不同状态时做不同动作
avPlayer.on('stateChange', async (state, reason) => {
  ……
})
//注册时间变化回调,方便更新进度条时间
avPlayer.on('timeUpdate', (time:number) => {
  ……
})
  • avplayer播放流程
graph LR
赋值avPlayer.url开始播放 --> 回调进入initialized --> 赋值avPlayer.surfaceId --> avPlayer.prepare --> 回调进入prepared --> avPlayer.play
//视频播放伪代码
async avPlayerDemo() {
    this.avPlayer.on('stateChange', async (state, reason) => {
        switch (state) {
            case 'idle': // 成功调用reset接口后触发该状态机上报
                console.info(TAG + 'state idle called')
                this.avPlayer.release() // 释放avplayer对象
                break;
            case 'initialized': // avplayer 设置播放源后触发该状态上报
                console.info(TAG + 'state initialized called ')
                this.avPlayer.surfaceId = this.surfaceID // 设置显示画面,当播放的资源为纯音频时无需设置
                this.avPlayer.prepare().then(() => {
                    console.info(TAG+ 'prepare success');
                }, (err) => {
                    console.error(TAG + 'prepare filed,error message is :' + err.message)
                })
                break;
            case 'prepared': // prepare调用成功后上报该状态机
                console.info(TAG + 'state prepared called')
                this.avPlayer.play() // 调用播放接口开始播放
                break;
            case 'playing': // play成功调用后触发该状态机上报
                console.info(TAG + 'state playing called')
                if (this.count == 0) {
                    this.avPlayer.pause() // 调用暂停播放接口
                } else {
                    this.avPlayer.seek(10000, media.SeekMode.SEEK_PREV_SYNC) // 前向seek置10秒处,触发seekDone回调函数
                }
                break;
            case 'paused': // pause成功调用后触发该状态机上报
                console.info(TAG + 'state paused called')
                if (this.count == 0) {
                    this.count++
                    this.avPlayer.play() // 继续调用播放接口开始播放
                }
                break;
            case 'completed': // 播放结束后触发该状态机上报
                console.info(TAG + 'state completed called')
                this.avPlayer.stop() //调用播放结束接口
                break;
            case 'stopped': // stop接口成功调用后触发该状态机上报
                console.info(TAG + 'state stopped called')
                this.avPlayer.reset() // 调用reset接口初始化avplayer状态
                break;
            case 'released':
                console.info(TAG + 'state released called')
                break;
            case 'error':
                console.info(TAG + 'state error called')
                break;
            default:
                console.info(TAG + 'unkown state :' + state)
                break;
        }
    })

    // 创建avPlayer实例对象
    this.avPlayer = await media.createAVPlayer()
    let fdPath = 'fd://'
    let pathDir = "/data/storage/el2/base/haps/entry/files" // pathDir在FA模型和Stage模型的获取方式不同,请参考开发步骤首行的说明,根据实际情况自行获取。
    // path路径的码流可通过"hdc file send D:\xxx\H264_AAC.mp4 /data/app/el2/100/base/ohos.acts.multimedia.media.avplayer/haps/entry/files" 命令,将其推送到设备上
    let path = pathDir  + '/H264_AAC.mp4'
    let file = await fs.open(path)
    fdPath = fdPath + '' + file.fd
    //赋值url后就会进入stateChange callback
    this.avPlayer.url = fdPath
}
  • 其他播放控制接口
/**
     * Prepare audio/video playback, it will request resource for playing.
     * @since 9
     * @syscap SystemCapability.Multimedia.Media.AVPlayer
     * @param callback A callback instance used to return when prepare completed.
     * @throws { BusinessError } 5400102 - Operation not allowed. Return by callback.
     * @throws { BusinessError } 5400106 - Unsupport format. Return by callback.
     */
    prepare(callback: AsyncCallback<void>): void;

    /**
     * Prepare audio/video playback, it will request resource for playing.
     * @since 9
     * @syscap SystemCapability.Multimedia.Media.AVPlayer
     * @returns A Promise instance used to return when prepare completed.
     * @throws { BusinessError } 5400102 - Operation not allowed. Return by promise.
     * @throws { BusinessError } 5400106 - Unsupport format. Return by promise.
     */
    prepare(): Promise<void>;

    /**
     * Play audio/video playback.
     * @since 9
     * @syscap SystemCapability.Multimedia.Media.AVPlayer
     * @param callback A callback instance used to return when play completed.
     * @throws { BusinessError } 5400102 - Operation not allowed. Return by callback.
     */
    play(callback: AsyncCallback<void>): void;

    /**
     * Play audio/video playback.
     * @since 9
     * @syscap SystemCapability.Multimedia.Media.AVPlayer
     * @returns A Promise instance used to return when play completed.
     * @throws { BusinessError } 5400102 - Operation not allowed. Return by promise.
     */
    play(): Promise<void>;

    /**
     * Pause audio/video playback.
     * @since 9
     * @syscap SystemCapability.Multimedia.Media.AVPlayer
     * @param callback A callback instance used to return when pause completed.
     * @throws { BusinessError } 5400102 - Operation not allowed. Return by callback.
     */
    pause(callback: AsyncCallback<void>): void;

    /**
     * Pause audio/video playback.
     * @since 9
     * @syscap SystemCapability.Multimedia.Media.AVPlayer
     * @returns A Promise instance used to return when pause completed.
     * @throws { BusinessError } 5400102 - Operation not allowed. Return by promise.
     */
    pause(): Promise<void>;

    /**
     * Stop audio/video playback.
     * @since 9
     * @syscap SystemCapability.Multimedia.Media.AVPlayer
     * @param callback A callback instance used to return when stop completed.
     * @throws { BusinessError } 5400102 - Operation not allowed. Return by callback.
     */
    stop(callback: AsyncCallback<void>): void;

     /**
      * Stop audio/video playback.
      * @since 9
      * @syscap SystemCapability.Multimedia.Media.AVPlayer
      * @returns A Promise instance used to return when stop completed.
      * @throws { BusinessError } 5400102 - Operation not allowed. Return by promise.
      */
    stop(): Promise<void>;

    /**
     * Reset AVPlayer, it will to idle state and can set src again.
     * @since 9
     * @syscap SystemCapability.Multimedia.Media.AVPlayer
     * @param callback A callback instance used to return when reset completed.
     * @throws { BusinessError } 5400102 - Operation not allowed. Return by callback.
     */
    reset(callback: AsyncCallback<void>): void;

    /**
     * Reset AVPlayer, it will to idle state and can set src again.
     * @since 9
     * @syscap SystemCapability.Multimedia.Media.AVPlayer
     * @returns A Promise instance used to return when reset completed.
     * @throws { BusinessError } 5400102 - Operation not allowed. Return by promise.
     */
    reset(): Promise<void>;

    /**
     * Releases resources used for AVPlayer.
     * @since 9
     * @syscap SystemCapability.Multimedia.Media.AVPlayer
     * @param callback A callback instance used to return when release completed.
     * @throws { BusinessError } 5400102 - Operation not allowed. Return by callback.
     */
    release(callback: AsyncCallback<void>): void;

    /**
     * Releases resources used for AVPlayer.
     * @since 9
     * @syscap SystemCapability.Multimedia.Media.AVPlayer
     * @returns A Promise instance used to return when release completed.
     * @throws { BusinessError } 5400102 - Operation not allowed. Return by promise.
     */
    release(): Promise<void>;

    /**
     * Jumps to the specified playback position.
     * @since 9
     * @syscap SystemCapability.Multimedia.Media.AVPlayer
     * @param timeMs Playback position to jump, should be in [0, duration].
     * @param mode See @SeekMode .
     */
    seek(timeMs: number, mode?:SeekMode): void;
  • 其他回调接口
/**
     * Register or unregister listens for media playback events.
     * @since 9
     * @syscap SystemCapability.Multimedia.Media.AVPlayer
     * @param type Type of the playback event to listen for.
     * @param callback Callback used to listen for the playback stateChange event.
     */
    on(type: 'stateChange', callback: (state: AVPlayerState, reason: StateChangeReason) => void): void;
    off(type: 'stateChange'): void;
    /**
     * Register or unregister listens for media playback events.
     * @since 9
     * @syscap SystemCapability.Multimedia.Media.AVPlayer
     * @param type Type of the playback event to listen for.
     * @param callback Callback used to listen for the playback volume event.
     */
    on(type: 'volumeChange', callback: Callback<number>): void;
    off(type: 'volumeChange'): void;
    /**
     * Register or unregister listens for media playback events.
     * @since 9
     * @syscap SystemCapability.Multimedia.Media.AVPlayer
     * @param type Type of the playback event to listen for.
     * @param callback Callback used to listen for the playback end of stream
     */
    on(type: 'endOfStream', callback: Callback<void>): void;
    off(type: 'endOfStream'): void;
    /**
     * Register or unregister listens for media playback events.
     * @since 9
     * @syscap SystemCapability.Multimedia.Media.AVPlayer
     * @param type Type of the playback event to listen for.
     * @param callback Callback used to listen for the playback seekDone event.
     */
    on(type: 'seekDone', callback: Callback<number>): void;
    off(type: 'seekDone'): void;
    /**
     * Register or unregister listens for media playback events.
     * @since 9
     * @syscap SystemCapability.Multimedia.Media.AVPlayer
     * @param type Type of the playback event to listen for.
     * @param callback Callback used to listen for the playback speedDone event.
     */
    on(type: 'speedDone', callback: Callback<number>): void;
    off(type: 'speedDone'): void;
    /**
     * Register or unregister listens for media playback events.
     * @since 9
     * @syscap SystemCapability.Multimedia.Media.AVPlayer
     * @param type Type of the playback event to listen for.
     * @param callback Callback used to listen for the playback setBitrateDone event.
     */
    on(type: 'bitrateDone', callback: Callback<number>): void;
    off(type: 'bitrateDone'): void;
    /**
     * LRegister or unregister listens for media playback events.
     * @since 9
     * @syscap SystemCapability.Multimedia.Media.AVPlayer
     * @param type Type of the playback event to listen for.
     * @param callback Callback used to listen for the playback timeUpdate event.
     */
    on(type: 'timeUpdate', callback: Callback<number>): void;
    off(type: 'timeUpdate'): void;
    /**
     * Register or unregister listens for media playback events.
     * @since 9
     * @syscap SystemCapability.Multimedia.Media.AVPlayer
     * @param type Type of the playback event to listen for.
     * @param callback Callback used to listen for the playback durationUpdate event.
     */
    on(type: 'durationUpdate', callback: Callback<number>): void;
    off(type: 'durationUpdate'): void;
    /**
     * Register or unregister listens for video playback buffering events.
     * @since 9
     * @syscap SystemCapability.Multimedia.Media.AVPlayer
     * @param type Type of the playback buffering update event to listen for.
     * @param callback Callback used to listen for the buffering update event, return BufferingInfoType and the value.
     */
    on(type: 'bufferingUpdate', callback: (infoType: BufferingInfoType, value: number) => void): void;
    off(type: 'bufferingUpdate'): void;
    /**
     * Register or unregister listens for start render video frame events.
     * @since 9
     * @syscap SystemCapability.Multimedia.Media.AVPlayer
     * @param type Type of the playback event to listen for.
     * @param callback Callback used to listen for the playback event return .
     */
    on(type: 'startRenderFrame', callback: Callback<void>): void;
    off(type: 'startRenderFrame'): void;
    /**
     * Register or unregister listens for video size change event.
     * @since 9
     * @syscap SystemCapability.Multimedia.Media.AVPlayer
     * @param type Type of the playback event to listen for.
     * @param callback Callback used to listen for the playback event return video size.
     */
    on(type: 'videoSizeChange', callback: (width: number, height: number) => void): void;
    off(type: 'videoSizeChange'): void;
    /**
     * Register or unregister listens for audio interrupt event, refer to {@link #audio.InterruptEvent}
     * @since 9
     * @syscap SystemCapability.Multimedia.Media.AVPlayer
     * @param type Type of the playback event to listen for.
     * @param callback Callback used to listen for the playback event return audio interrupt info.
     */
    on(type: 'audioInterrupt', callback: (info: audio.InterruptEvent) => void): void;
    off(type: 'audioInterrupt'): void;
    /**
     * Register or unregister listens for available bitrate list collect completed events for HLS protocol stream playback.
     * This event will be reported after the {@link #prepare} called.
     * @since 9
     * @syscap SystemCapability.Multimedia.Media.AVPlayer
     * @param type Type of the playback event to listen for.
     * @param callback Callback used to listen for the playback event return available bitrate list.
     */
    on(type: 'availableBitrates', callback: (bitrates: Array<number>) => void): void;
    off(type: 'availableBitrates'): void;
build() {
    Stack({ alignContent: Alignment.Center }) {
      if (this.isShowMenu) {
        Column() {
          //视频名称
          PlayTitle({ title: this.displayName, handleBack: this.handleBack })
          Row() {
            //播放控件
            PreVideo({ handleClick: this.handlePrevClick })
            PlayButton({ isPlaying: $isPlaying })
            NextVideo({ handleClick: this.handleNextClick })
          }
          .margin({ top: '40%' })

          Blank()
          //时间刻度
          Row() {
            Text(getTimeString(this.currentTime))
              .fontSize(25)
              .fontColor(Color.White)
            Blank()
            Text(this.fileAsset ? getTimeString(this.fileAsset.duration) : '00:00')
              .fontSize(25)
              .fontColor(Color.White)
          }
          .width('95%')
      //进度条
          Slider({ value: this.fileAsset ? this.currentTime / this.fileAsset.duration * 100 : 0 })
            .width('92%')
            .selectedColor(Color.White)
            .onChange((value: number) => {
              Logger.info(TAG, 'seek time change')
              this.currentTime = this.fileAsset.duration * value / 100
              this.videoPlayer.seek(this.currentTime)
            })
        }
        .height('100%')
        .zIndex(2)
      }
      Row() {
        XComponent({
          id: 'componentId',
          type: 'surface',
          controller: this.mxcomponentController
        })
          .onLoad(() => {
            Logger.info(TAG, 'onLoad is called')
            this.playVideo()
          })
          .width('100%')
          .aspectRatio(this.ratio)
      }
      .height('100%')
      .width('100%')
      .justifyContent(FlexAlign.Center)
    }
    .width('100%')
    .height('100%')
    .backgroundColor(Color.Black)
    .onClick(() => {
      this.isShowMenu = !this.isShowMenu
    })
  }
//根据视频文件获取视频源尺寸并生成surface
  //视频文件的路径在/storage/media/100/local/files/Videos
  async prepareVideo() {
    this.ratio = this.fileAsset.width / this.fileAsset.height
    this.mxcomponentController.setXComponentsurfaceSize({
      surfaceWidth: this.fileAsset.width,
      surfaceHeight: this.fileAsset.height
    })
    this.surfaceId = this.mxcomponentController.getXComponentsurfaceId()
    this.fd = await this.fileAsset.open('Rw')
    Logger.info(TAG, `fd://' ${this.fd} `)
    return 'fd://' + this.fd
  }
  //初始化视频文件并初始化avplayer
  async playVideo() {
    Logger.info(TAG, 'playVideo')
    try{
      await this.getMediaList()
      let fdPath = await this.prepareVideo()
      this.videoPlayer.on('timeUpdate', (time:number) => {
        console.info('timeUpdate success,and new time is :' + time)
        this.currentTime = time;
      })
      await this.videoPlayer.initVideoPlayer(fdPath, this.surfaceId)
      this.isPlaying = true
    }catch(error) {
      Logger.info(TAG, `playVideo error ${JSON.stringify(error)}`)
    }
  }

参考链接:​​​https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-media.md#play9。​

​想了解更多关于开源的内容,请访问:​

​51CTO 开源基础软件社区​

​https://ost.51cto.com​

责任编辑:jianghua 来源: 51CTO 开源基础软件社区

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK