HarmonyOS 鸿蒙Next 音视频播放场景化代码

发布于 1周前 作者 yuanlaile 最后一次编辑是 5天前 来自 鸿蒙OS

HarmonyOS 鸿蒙Next 音视频播放场景化代码

介绍

本示例基于Avplayer构建了一个音视频播放器,几乎包括了所有对音视频的基本操作。

音视频播放案例源码链接

效果图

使用说明

  • 打开应用,展示视频播放器,选择不同按钮进行不同操作。
  • 切换音频,展示音频播放器,选择不同按钮进行不同操作。

实现思路

AVPlayer播放主流程

  1. 播放的全流程包含:创建AVPlayer,设置播放资源,设置播放参数(音量/倍速),播放控制(播放/暂停/上一个视频/下一个视频),重置,销毁资源。
createAVPlayer() {
 media.createAVPlayer().then((video: media.AVPlayer) => {
   if (video != null) {
     this.avPlayer = video;
     this.setAVPlayerCallback(this.avPlayer);
     if (this.avPlayer && this.sourceFiles.length > this.currentIndex) {
       this.avPlayer.fdSrc = this.sourceFiles[this.currentIndex];
     }
   } 
 }
}
  1. 视频播放之前需要初始化XComponent组件用于展示视频画面。XComponent组件初始化成功之后在onLoad()中获取surfaceID用于与AVPlayer实例关联。
.onLoad(() => {
 this.xComponentController.setXComponentSurfaceRect({
   surfaceWidth: 1920,
   surfaceHeight: 1080
 });
 this.surfaceID = this.xComponentController.getXComponentSurfaceId();
})
  1. 使用AVPlayer前需要通过createAVPlayer()构建一个实例对象,并为AVPlayer实例绑定状态机,状态机具体请参考AVPlayerState。
 createAVPlayer() {
   media.createAVPlayer().then((video: media.AVPlayer) => {
     if (video != null) {
       this.avPlayer = video;
       this.setAVPlayerCallback(this.avPlayer);
       if (this.avPlayer && this.sourceFiles.length > this.currentIndex) {
         this.avPlayer.fdSrc = this.sourceFiles[this.currentIndex];
       }
     } 
 })
 }
  1. AVPlayer实例需设置播放路径(本地资源使用fd、offset、length构建media.AVFileDescriptor对象对AVPlayer.fdSrc属性赋值或使用fd://${fd}格式对AVPlayer.url属性赋值,网络资源可直接使用网络地址对AVPlayer.url属性赋值)和XComponent中获取的surfaceID,设置播放路径之后AVPlayer状态机变为initialized状态,在此状态下调用prepare(),进入prepared状态。
case 'initialized': 
 logger.info('AVPlayerDemo AVPlayer state initialized called.');
 this.reset()
 if (this.isVideo) {
   avPlayer.surfaceId = this.surfaceID;
 }
 avPlayer.prepare();
 break;
  1. 在prepared状态下可获取当前播放路径对应视频的总时长,并执行play()进行视频播放。

  2. 视频播放后,变为playing状态,可通过“播放/暂停”按钮切换播放状态,当视频暂停时状态机变为paused状态。

  3. 视频播放完成之后,进入completed状态,需调用reset()对视频进行重置,此时变为idle转态,在idle状态下设置下一个视频的播放地址,又会进入initialized状态。

  4. 播放网络视频需要声明ohos.permission.INTERNET权限

使用pipWindow实现画中画

  1. 初始化:使用pipWindow.create(PiPConfiguration)初始化PiPController画中画控制器,可在PiPConfiguration设置对应的XComponent控制器、点击画中画返回应用的navigationId、画中画类型(视频播放VIDEO_PLAY、视频电话VIDEO_CALL、视频会议VIDEO_MEETING、视频直播VIDEO_LIVE)、画中画宽高。
pipWindow.create(config).then((data: pipWindow.PiPController) => {
 logger.info(`AVPlayerDemo Succeeded in creating pip controller. Data:${data}`);
 this.pipController = data;
 this.setPipWindowCallback(data)
})
  1. 设置回调:初始化完成后,可在回调中设置相关监听处理,来处理小屏播放时播放控制。

  2. 启动画中画:调用pipController.startPiP()可以开启画中画,在开启前可以设置返回桌面时是否自动启动画中画pipController.setAutoStartEnabled(true/false)。

 startPipWindow() {
   if (this.pipController) {
     this.pipController.setAutoStartEnabled(true)
     this.pipController.startPiP().then(() => {
       ···
     });
   }
 }
  1. 停止画中画:调用pipController.stopPiP()可以停止画中画。
 stopPipWindow() {
   if (this.pipController) {
     this.pipController.stopPiP().then(() => {
       logger.info(`AVPlayerDemo Succeeded in stop pip.`);
     }).catch((err: BusinessError) => {
       logger.error(`AVPlayerDemo Failed to stop pip. Cause:${err.code}, message:${err.message}`);
     });
   }
 }

使用AVSession接入播控中心

  1. 初始化:使用avSession.createAVSession(context: Context, tag: string, type: AVSessionType): Promise创建媒体会话,可以通过第三个参数设置媒体会话类型:视频video、音频audio。
 async createAVSession() {
   let type: avSession.AVSessionType = this.isVideo ? 'video' : 'audio';
   await avSession.createAVSession(getContext(this), 'AVPlayerDemo', type).then((data: avSession.AVSession) => {
     logger.info(`AVPlayerDemo CreateAVSession : SUCCESS : sessionId = ${data.sessionId}`);
     this.currentAVSession = data;
     this.curSessionId = data.sessionId;
     this.setAVSessionCallback(data);
   })
   }
  1. 设置回调:创建完媒体会话后,可以设置回调事件,监听播控中心播放、暂停、停止、上一个、下一个、快进、快退等播控事件,可以在这些回调中触发avplyer实例来实现对应功能。

  2. 设置元数据:通过setAVMetadata(data: AVMetadata): Promise方法为媒体会话设置元数据,主要设置当前媒体源ID、标题、时长、上一个媒体源ID、下一个媒体源ID、展示图片等,其中媒体源ID是媒体的唯一标识,由业务自定义。

 async startAVSession() {
   if (!this.currentAVSession) {
     logger.error('AVPlayerDemo currentAVSession is undefined.')
     return;
   }
   let metadata: avSession.AVMetadata = this.generateAVMetadata();
   await this.currentAVSession.setAVMetadata(metadata).then(() => {
     ···
   });
 }
  1. 设置播放状态:通过setAVPlaybackState(state: AVPlaybackState): Promise设置播放状态、当前播放进度、播放速率、循环模式、媒体音量等。
this.currentAVSession.setAVPlaybackState()
  1. 激活媒体会话:通过activate(): Promise可激活媒体会话,激活后可以在播控中心看到设置的元数据。
   await this.currentAVSession.activate().then(() => {
     logger.info(`AVPlayerDemo Activate : SUCCESS `);
   })
  1. 进度展示:在avplayer的timeUpdate回调事件中,可以通过setAVPlaybackState(state: AVPlaybackState): Promise实时更新当前媒体源的播放进度。

  2. 状态同步:在avplayer的stateChange回调事件中,可以通过setAVPlaybackState(state: AVPlaybackState): Promise实时同步当前媒体源的播放状态。

  3. 后台播放:如果想实现应用切换后台后,播控中心仍能控制媒体播放,需要申请audioPlayback的长时任务,声明ohos.permission.KEEP_BACKGROUND_RUNNING权限

工程目录

entry/src/main/ets/
|---entryability
|   |---EntryAbility.ets
|---pages
|   |---AVPlayerDemo.ets      // 播放主页
|---util
|   |---GlobalContext.ets     // 存储工具类

约束与限制

  • 手机ROM版本:NOH-AN00 5.0.0.102(SP6C00E102R5P9log)
  • IDE:DevEco Studio NEXT Release 5.0.1.910
  • SDK:OpenHarmony SDK Ohos_sdk_public 5.0.0.71 (API 12 Release)

更多关于HarmonyOS 鸿蒙Next 音视频播放场景化代码的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html

1 回复

更多关于HarmonyOS 鸿蒙Next 音视频播放场景化代码的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS鸿蒙Next系统中,针对音视频播放的场景化代码,可以基于媒体框架(Media Framework)进行开发。以下是一个简化的示例代码,展示如何在特定场景中实现音视频播放功能:

#include <media/player.h>
#include <media/surface_view.h>

using namespace OHOS::Media;

void PlayMedia(const std::string& mediaPath) {
    Player player;
    if (!player.SetDataSource(mediaPath)) {
        // Handle error
        return;
    }

    player.Prepare();
    player.Start();

    SurfaceView surfaceView;
    if (!surfaceView.AttachPlayer(&player)) {
        // Handle error
        return;
    }

    // Assuming a layout has been set up to display surfaceView
    // surfaceView.SetLayout(...);

    // Maintain the player and surfaceView state as needed for playback
}

// Example usage:
// PlayMedia("/path/to/your/media/file");

此代码段展示了如何创建一个Player对象并设置数据源,然后准备和开始播放媒体文件。同时,它展示了如何将Player对象附加到SurfaceView上,以便在界面上显示视频内容。注意,实际项目中需处理更多细节,如错误处理、资源释放、UI布局设置等。

如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html

回到顶部