【鸿蒙实战开发】基于AVPlayer的视频播放

100 篇文章 2 订阅
100 篇文章 1 订阅

1 场景描述

示例场景:AVPlayer播放视频ArkTS实现,创建AVPlayer,设置播放资源和窗口,设置播放参数,播放控制(播放/暂停/跳转),重置,销毁资源,播放完成后切换视频。

2 方案描述

AVPlayer:功能较完善的音视频播放ArkTS API,集成了流媒体和本地资源解析,媒体资源解封装,视频解码和渲染功能,适用于对媒体资源进行端到端播放的场景,可 直接播放mp4、mkv等格式的视频文件 。本示例就是使用avplayer进行视频播放的实现,功能包括多种方式播放视频,以及对于视频播放的控制。

具体实现步骤可分为Step1: 调用createAVPlayer()创建AVPlayer实例。Step2: 设置业务需要的监听事件,搭配全流程场景使用。Step3: 设置窗口:获取并设置属性SurfaceID,用于设置显示画面。应用需要从XComponent组件获取surfaceID。同时设置load事件,应该改成并在onload事件回调中完成设置播放资源的操作Step4: 注册avplayer回调函数Step5: 调用相关接口实现播放play(),暂停pause(),跳转seek()等操作。

2.1 创建AVPlayer实例

调用createAVPlayer()创建AVPlayer实例

1.通过url设置网络地址来实现播放


async avPlayerLiveDemo() {

// 创建avPlayer实例对象

let avPlayer: media.AVPlayer = await media.createAVPlayer();

// 创建状态机变化回调函数

this.setAVPlayerCallback(avPlayer);

avPlayer.url = 'https://xxxx; // 播放网络视频

}

}

2.使用fs文件系统打开沙箱地址获取媒体文件地址并通过dataSrc属性进行播放


async avPlayerLiveDemo() {

// 创建avPlayer实例对象

let avPlayer: media.AVPlayer = await media.createAVPlayer();

// 创建状态机变化回调函数

this.setAVPlayerCallback(avPlayer);

avPlayer.url = 'https://sns-video-bd.xhscdn.com/stream/110/258/01e602cadc11542d010370038e7ae8b418_258.mp4'; // 播放网络视频

}

}async avPlayerDataSrcDemo

// 创建avPlayer实例对象

let avPlayer: media.AVPlayer = await media.createAVPlayer();

// 创建状态机变化回调函数

this.setAVPlayerCallback(avPlayer);

// dataSrc播放模式的的播放源地址,当播放为Seek模式时fileSize为播放文件的具体大小,下面会对fileSize赋值

let src: media.AVDataSrcDescriptor = {

fileSize: -1,

callback: (buf: ArrayBuffer, length: number, pos: number | undefined) => {

let num = 0;

if (buf == undefined || length == undefined || pos == undefined) {

return -1;

}

num = fs.readSync(this.fd, buf, { offset: pos, length: length });

if (num > 0 && (this.fileSize >= pos)) {

return num;

}

return -1;

}

}

let context = getContext(this) as common.UIAbilityContext;

// 通过UIAbilityContext获取沙箱地址filesDir,以Stage模型为例

let pathDir = context.filesDir;

let path = pathDir + '/H264_AAC.mp4';

await fs.open(path).then((file: fs.File) => {

this.fd = file.fd;

})

// 获取播放文件的大小

this.fileSize = fs.statSync(path).size;

src.fileSize = this.fileSize;

avPlayer.dataSrc = src;

}

}

3.使用资源管理接口获取打包在HAP内的媒体资源文件并通过fdSrc属性进行播放


async avPlayerFdSrcDemo() {

// 创建avPlayer实例对象

this.player = await media.createAVPlayer();

// 创建状态机变化回调函数

this.setAVPlayerCallback(this.player);

// 通过UIAbilityContext的resourceManager成员的getRawFd接口获取媒体资源播放地址

// 返回类型为{fd,offset,length},fd为HAP包fd地址,offset为媒体资源偏移量,length为播放长度

let context = getContext(this) as common.UIAbilityContext;

let fileDescriptor = await context.resourceManager.getRawFd('1234.mp4');

let avFileDescriptor: media.AVFileDescriptor =

{ fd: fileDescriptor.fd, offset: fileDescriptor.offset, length: fileDescriptor.length };

// 为fdSrc赋值触发initialized状态机上报

this.player.fdSrc = avFileDescriptor;

}

4.使用fs文件系统打开沙箱地址获取媒体文件地址并通过url属性进行播放


async avPlayerUrlDemo() {

// 创建avPlayer实例对象

this.player = await media.createAVPlayer();

this.setAVPlayerCallback(this.player);

let fdPath = 'fd://';

let context = getContext(this) as common.UIAbilityContext;

// 通过UIAbilityContext获取沙箱地址filesDir,以Stage模型为例

let pathDir = context.filesDir;

console.info(pathDir)

let path = pathDir + '/1234.mp4';

// 打开相应的资源文件地址获取fd,并为url赋值触发initialized状态机上报

let file = await fs.open(path);

fdPath = fdPath + '' + file.fd;

this.player.url = fdPath;

}

2.3 设置业务需要的监听事件

支持的监听事件包括:

事件类型说明
stateChange必要事件,监听播放器的state属性改变。
error必要事件,监听播放器的错误信息。
durationUpdate用于进度条,监听进度条长度,刷新资源时长。
timeUpdate用于进度条,监听进度条当前位置,刷新当前时间。
seekDone响应API调用,监听seek()请求完成情况。当使用seek()跳转到指定播放位置后,如果seek操作成功,将上报该事件。
speedDone响应API调用,监听setSpeed()请求完成情况。当使用setSpeed()设置播放倍速后,如果setSpeed操作成功,将上报该事件。
volumeChange响应API调用,监听setVolume()请求完成情况。当使用setVolume()调节播放音量后,如果setVolume操作成功,将上报该事件。
bitrateDone响应API调用,用于HLS协议流,监听setBitrate()请求完成情况。当使用setBitrate()指定播放比特率后,如果setBitrate操作成功,将上报该事件。
availableBitrates用于HLS协议流,监听HLS资源的可选bitrates,用于setBitrate()。
bufferingUpdate用于网络播放,监听网络播放缓冲信息。
tartRenderFrame于视频播放,监听视频播放首帧渲染时间。当AVPlayer首次起播进入playing状态后,等到首帧视频画面被渲染到显示画面时,将上报该事件。应用通常可以利用此事件上报,进行视频封面移除,达成封面与视频画面的顺利衔接。
ideoSizeChange于视频播放,监听视频播放的宽高信息,可用于调整窗口大小、比例。
udioInterrupt听音频焦点切换信息,搭配属性audioInterruptMode使用。如果当前设备存在多个媒体正在播放,音频焦点被切换(即播放其他媒体如通话等)时将上报该事件,应用可以及时处理。

avPlayer.on('speedDone', (number: Number) => this.speedDone(number));

avPlayer.on('seekDone', (number: Number) => this.seekDone(number));

2.4 设置窗口

XComponent的类型设置为SURFACE,在type设置为为SURFACE时可以支持Load事件,Load事件的作用是插件加载完成时回调事件,在回调中设置好需要播放的资源。


build()

Column() {

XComponent({

id: 'AVPlayer',

type: XComponentType.SURFACE,

controller: this.xComponentController

})

.onLoad (()=> {

this.surfaceID = this.xComponentController.getXComponentSurfaceId()

this.xComponentContext = this.xComponentController.getXComponentContext() as Record<string, () => void>

})

2.5 注册avplayer回调函数

  • idle:闲置状态,AVPlayer刚被创建createAVPlayer()或者调用了reset()方法之后,进入Idle状态。首次创建createAVPlayer(),所有属性都为默认值。 调用reset()方法,url 或 fdSrc或dataSrc属性及loop属性会被重置,其他用户设置的属性将被保留。

  • initialized:资源初始化,在Idle 状态设置 url或 fdSrc属性,AVPlayer会进入initialized状态,此时可以配置窗口、音频等静态属性。

  • prepared:已准备状态,在initialized状态调用prepare()方法,AVPlayer会进入prepared状态,此时播放引擎的资源已准备就绪。

  • playing:正在播放状态,在prepared/paused/completed状态调用play()方法,AVPlayer会进入playing状态。

  • paused:暂停状态,在playing状态调用pause方法,AVPlayer会进入paused状态。

  • completed:播放至结尾状态,当媒体资源播放至结尾时,如果用户未设置循环播放,AVPlayer会进入completed状态。

  • stopped:停止状态,在prepared/playing/paused/completed状态调用stop()方法,AVPlayer会进入stopped状态,此时播放引擎只会保留属性,但会释放内存资源,可以调用prepare()重新准备,也可以调用reset()重置,或者调用release()彻底销毁。

  • released:销毁状态,销毁与当前AVPlayer关联的播放引擎,无法再进行状态转换,调用release()方法后,会进入released状态,结束流程。


private setAVPlayerCallback(avPlayer: media.AVPlayer) {

if (this.player == null) {

return;

}

// // 响应API调用,监听seek()请求完成情况。

avPlayer.on('speedDone', (number: Number) => this.speedDone(number));

avPlayer.on('seekDone', (number: Number) => this.seekDone(number));

// 状态机变化回调函数

avPlayer.on('stateChange', async (state: string, reason: media.StateChangeReason) => {

switch (state) {

case 'idle': // 成功调用reset接口后触发该状态机上报

console.info('AVPlayer state idle called.');

break;

case 'initialized': // avplayer 设置播放源后触发该状态上报

console.info('AVPlayer state initialized called.');

avPlayer.surfaceId = this.surfaceID; // 设置显示画面,当播放的资源为纯音频时无需设置

avPlayer.prepare();

break;

case 'prepared': // prepare调用成功后上报该状态机

console.info('AVPlayer state prepared called.');

avPlayer.play(); // 调用播放接口开始播放

break;

case 'playing': // play成功调用后触发该状态机上报

console.info('AVPlayer state playing called.');

break;

case 'paused': // pause成功调用后触发该状态机上报

console.info('AVPlayer state paused called.');

break;

case 'completed': // 播放结束后触发该状态机上报

console.info('AVPlayer state completed called.');

avPlayer.stop(); //调用播放结束接口

break;

case 'stopped': // stop接口成功调用后触发该状态机上报

console.info('AVPlayer state stopped called.');

avPlayer.release();

break;

case 'released':

console.info('AVPlayer state released called.');

break;

default:

console.info('AVPlayer state unknown called.');

break;

}

})

}

2.6 播放控制

1.暂停和播放


Button('start')

.onClick(() => {

this.avPlayerDataSrcNOSeekDemo()

})

.margin({right:12})

.margin({top:5})

.width(150)

Button('paused')

.onClick(() => {

this.player?.pause();

})

.margin({right:12})

.margin({top:5})

.width(150)

Button('player')

.onClick(() => {

this.player?.play();

})

.margin({right:12})

.margin({top:5})

.width(150)

2.停止播放,销毁


Button('stop')

.onClick(() => {

this.player?.stop();

})

.margin({right:12})

3.重置切换视频


Button('reset')

.onClick(() => {

this.player?.reset();

})

.margin({right:12})

4.倍速这里设置的是二倍速播放这里可以通过设置PlaybackSpeed的枚举,来实现不同速率的播放。这里设置的是SPEED_FORWARD_2_00_X,二倍速。


Button('speed')

.onClick(() => {

this.player?.setSpeed(media.PlaybackSpeed.SPEED_FORWARD_2_00_X);

})

.margin({right:12})

5.跳转seek跳转到指定播放位置,只能在prepared/playing/paused/completed状态调用,跳转时间节点的单位是ms,通过设置枚举值控制跳转的模式。

名称说明
SEEK_NEXT_SYNC0表示跳转到指定时间点的下一个关键帧,建议向后快进的时候用这个枚举值。
SEEK_PREV_SYNC1表示跳转到指定时间点的上一个关键帧,建议向前快进的时候用这个枚举值。
SEEK_CLOSEST2表示跳转到指定时间点的最接近的帧,建议精准查找的时候用这个枚举值。
Button('seek')

.onClick(() => {

this.player?.seek(6000,0);

})

.margin({right:12}

鸿蒙全栈开发全新学习指南

有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以要有一份实用的鸿蒙(HarmonyOS NEXT)学习路线与学习文档用来跟着学习是非常有必要的。

针对一些列因素,整理了一套纯血版鸿蒙(HarmonyOS Next)全栈开发技术的学习路线,包含了鸿蒙开发必掌握的核心知识要点,内容有(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、WebGL、元服务、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、OpenHarmony驱动开发、系统定制移植等等)鸿蒙(HarmonyOS NEXT)技术知识点。

本路线共分为四个阶段

第一阶段:鸿蒙初中级开发必备技能

在这里插入图片描述

第二阶段:鸿蒙南北双向高工技能基础:gitee.com/MNxiaona/733GH

在这里插入图片描述

第三阶段:应用开发中高级就业技术

第四阶段:全网首发-工业级南向设备开发就业技术:gitee.com/MNxiaona/733GH

在这里插入图片描述

《鸿蒙 (Harmony OS)开发学习手册》(共计892页)

如何快速入门?

1.基本概念
2.构建第一个ArkTS应用
3.……

开发基础知识:gitee.com/MNxiaona/733GH

1.应用基础知识
2.配置文件
3.应用数据管理
4.应用安全管理
5.应用隐私保护
6.三方应用调用管控机制
7.资源分类与访问
8.学习ArkTS语言
9.……

在这里插入图片描述

基于ArkTS 开发

1.Ability开发
2.UI开发
3.公共事件与通知
4.窗口管理
5.媒体
6.安全
7.网络与链接
8.电话服务
9.数据管理
10.后台任务(Background Task)管理
11.设备管理
12.设备使用信息统计
13.DFX
14.国际化开发
15.折叠屏系列
16.……

在这里插入图片描述

鸿蒙开发面试真题(含参考答案):gitee.com/MNxiaona/733GH

在这里插入图片描述

鸿蒙入门教学视频:

美团APP实战开发教学:gitee.com/MNxiaona/733GH

写在最后

  • 如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
  • 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。
  • 想要获取更多完整鸿蒙最新学习资源,请移步前往小编:gitee.com/MNxiaona/733GH

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值