鸿蒙上制作一个视频播放器

媒体子系统是 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): 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.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:xxxh264_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;    /**     * 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;    /**     * 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;    /**     * 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;    /**     * 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;    /**     * 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;    /**     * 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;     /**      * 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;    /**     * 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;    /**     * 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;    /**     * 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;    /**     * 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;    /**     * 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? 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): 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;    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): 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): 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): 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): 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): 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;    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) => 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   


计算机网络的三种交换方式
东芝推出新型低触发电流光继电器,满足电池供电设备的低功耗需求
从“制造”到“创造”,硬核科技释放创造力
自动油漆混合机的制作
诺基亚没拿到中国移动5G订单后 给联通发了一封信
鸿蒙上制作一个视频播放器
Embedded Target for RH850Multicore基于模型的开发环境的简介
仅需2颗芯片外围的12V1A无Y无共模适配器方案介绍
调速器的工作原理_调速器怎么接线
多亏刘老师!看似复杂的故障原来如此---
5G即将到来 无人驾驶已经离我们的生活越来越近
网站不可使用不安全的HTTP协议
商汤科技数字哨兵便捷通行系统加快推进企业复工复产
浅析多种FPC的区别
高通推出支持WiFi 6技术的新型WiFi芯片,可推动5G芯片的销量增长
自动化技术中需要掌握的45个伺服电机知识
下代iPhone 13可全力支持8K视频录制了
车联网隐患提示器怎样研发实现
中国移动以线下3D展厅结合的形式,展示工业互联网的典型应用场景
处理器损坏的原因是什么