鸿蒙ArkUI开发-Video组件的使用

概述在手机、平板或是智慧屏这些终端设备上,媒体功能可以算作是我们最常用的场景之一。无论是实现音频的播放、录制、采集,还是视频的播放、切换、循环,亦或是相机的预览、拍照等功能,媒体组件都是必不可少的。以视频功能为例,在应用开发过程中,我们需要通过arkui提供的video组件为应用增加基础的视频播放功能。借助video组件,我们可以实现视频的播放功能并控制其播放状态。常见的视频播放场景包括观看网络上的较为流行的短视频,也包括查看我们存储在本地的视频内容。
本文将结合《简易视频播放器(arkts)》这个codelab,对video组件的参数、属性及事件进行介绍,然后通过组件的属性调用和事件回调阐明video组件的基本使用方法,最后结合video组件使用过程中的常见问题讲解自定义控制器的使用。
video组件用法介绍video组件参数介绍 video组件的接口表达形式为:
video(value: {src?: string | resource, currentprogressrate?: number | string |playbackspeed, previewuri?: string |pixelmap | resource, controller?: videocontroller})其中包含四个可选参数,src、currentprogressrate、previewuri和controller。
src表示视频播放源的路径,可以支持本地视频路径和网络路径。使用网络地址时,如https,需要注意的是需要在module.json5文件中申请网络权限。在使用本地资源播放时,当使用本地视频地址我们可以使用媒体库管理模块medialibrary来查询公共媒体库中的视频文件,示例代码如下:import medialibrary from '@ohos.multimedia.medialibrary'; async querymediavideo() { let option = { // 根据媒体类型检索 selections: medialibrary.filekey.media_type + '=?', // 媒体类型为视频 selectionargs: [medialibrary.mediatype.video.tostring()] }; let media = medialibrary.getmedialibrary(getcontext(this)); // 获取资源文件 const fetchfileresult = await media.getfileassets(option); // 以获取的第一个文件为例获取视频地址 let fileasset = await fetchfileresult.getfirstobject(); this.source = fileasset.uri}为了方便功能演示,示例中媒体资源需存放在resources下的rawfile文件夹里。
currentprogressrate表示视频播放倍速,其参数类型为number,取值支持0.75,1.0,1.25,1.75,2.0,默认值为1.0倍速;previewuri表示视频未播放时的预览图片路径;controller表示视频控制器。参数的具体描述如下表:
参数名参数类型必填
src string resource
currentprogressrate number string
previewuri string pixelmap8+
controller videocontroller 否
说明视频支持的规格是:mp4、mkv、webm、ts。 下面我们通过具体的例子来说明参数的使用方法,我们选择播放本地视频,视频未播放时的预览图片路径也为本地,代码实现如下:
@componentexport struct videoplayer { private source: string | resource; private controller: videocontroller; private previewuris: resource = $r('app.media.preview'); ... build() { column() { video({ src: this.source, previewuri: this.previewuris, controller: this.controller }) ... videoslider({ controller: this.controller }) } }}效果如下:
video组件属性介绍除了支持组件的尺寸设置、位置设置等通用属性外,video组件还支持是否静音、是否自动播放、控制栏是否显示、视频显示模式以及单个视频是否循环播放五个私有属性。
名称参数类型描述
muted boolean 是否静音。默认值:false
autoplay boolean 是否自动播放。默认值:false
controls boolean 控制视频播放的控制栏是否显示。默认值:true
objectfit imagefit 设置视频显示模式。默认值:cover
loop boolean 是否单个视频循环播放。默认值:false
其中,objectfit 中视频显示模式包括contain、cover、auto、fill、scaledown、none 6种模式,默认情况下使用imagefit.cover(保持宽高比进行缩小或者放大,使得图片两边都大于或等于显示边界),其他效果(如自适应显示、保持原有尺寸显示、不保持宽高比进行缩放等)可以根据具体使用场景/设备来进行选择。 在codelab示例中体现了controls、autoplay和loop属性的配置,示例代码如下:
@componentexport struct videoplayer { private source: string | resource; private controller: videocontroller; ... build() { column() { video({ controller: this.controller }) .controls(false) //不显示控制栏 .autoplay(false) // 手动点击播放 .loop(false) // 关闭循环播放 ... } }}效果如下:
video组件回调事件介绍video组件能够支持常规的点击、触摸等通用事件,同时也支持onstart、onpause、onfinish、onerror等事件,具体事件的功能描述见下表:
事件名称功能描述
onstart(event:() => void) 播放时触发该事件。
onpause(event:() => void) 暂停时触发该事件。
onfinish(event:() => void) 播放结束时触发该事件。
onerror(event:() => void) 播放失败时触发该事件。
onprepared(callback:(event?: { duration: number }) => void) 视频准备完成时触发该事件,通过duration可以获取视频时长,单位为s。
onseeking(callback:(event?: { time: number }) => void) 操作进度条过程时上报时间信息,单位为s。
onseeked(callback:(event?: { time: number }) => void) 操作进度条完成后,上报播放时间信息,单位为s。
onupdate(callback:(event?: { time: number }) => void) 播放进度变化时触发该事件,单位为s,更新时间间隔为250ms。
onfullscreenchange(callback:(event?: { fullscreen: boolean }) => void) 在全屏播放与非全屏播放状态之间切换时触发该事件
在codelab中我们以更新事件、准备事件、失败事件以及点击事件为回调为例进行演示,代码实现如下:
video({ ... }) .onupdate((event) = > { this.currenttime = event.time; this.currentstringtime = changeslidertime(this.currenttime); //更新事件 }) .onprepared((event) = > { prepared.call(this, event); //准备事件 }) .onerror(() = > { prompt.showtoast({ duration: common_num_duration, //播放失败事件 message: message }); ... })其中,onupdate更新事件在播放进度变化时触发,从event中可以获取当前播放进度,从而更新进度条显示事件,比如视频播放时间从24秒更新到30秒。onerror事件在视频播放失败时触发,在commonconstants.ets中定义了常量类message,所以在视频播放失败时会显示“请检查网络”。
const message: string = '请检查网络'自定义控制器的组成与实现自定义控制器的组成video组件的原生控制器样式相对固定,当我们对页面的布局色调的一致性有所要求,或者在拖动进度条的同时需要显示其百分比进度时,原生控制器就无法满足需要了。如下图右侧的效果需要使用自定义控制器实现,接下来我们看一下自定义控制器的组成。
为了实现自定义控制器的进度显示等功能,我们需要通过row容器实现控制器的整体布局,然后借由text组件来显示视频的播放起始时间、进度时间以及视频总时长,最后通过滑动进度条slider组件来实现视频进度条的效果,代码如下:
@componentexport struct videoslider { ... build() { row(...) { image(...) text(...) slider(...) text(...) } ... }}自定义控制器的实现自定义控制器容器内嵌套了视频播放时间text组件、滑动器slider组件以及视频总时长text组件 3个横向排列的组件,其中text组件在之前的基础组件课程中已经有过详细介绍,这里就不再进行赘述。需要强调的是两个text组件显示的时长是由slider组件的onchange(callback: (value: number, mode: sliderchangemode) => void)回调事件来进行传递的,而text组件的数值与视频播放进度数值value则是通过@provide与 @consume装饰器进行的数据联动,实现效果可见图片下方黑色控制栏部分,具体代码步骤及代码如下: 获取/计算视频时长
export function prepared(event) { this.durationtime = event.duration; let second: number = event.duration % common_num_minute; let min: number = parseint((event.duration / common_num_minute).tostring()); let head = min < common_num_double ? `${zero_str}${min}` : min; let end = second {...})计算当前进度播放时间及添加onupdate回调 最后,在我们播放视频时还需要更新显示播放的时间进度,也就是左侧的text组件。在视频开始播放前,播放时间默认为00:00,随着视频播放,时间需要不断更新为当前进度时间。所以左侧的text组件我们不仅需要读取时间,还需要为其添加数据联动。这里,我们就是通过为video组件添加onupdate事件来实现的,在视频播放过程中会不断调用changeslidertime方法获取当前的播放时间并进行计算及单位转化,从而不断刷新进度条的值,也就是控制器左侧的播放进度时间text组件。
video({...}) ... .onupdate((event) = > { this.currenttime = event.time; this.currentstringtime = changeslidertime(this.currenttime) })export function changeslidertime(value: number): string { let second: number = value % common_num_minute; let min: number = parseint((value / common_num_minute).tostring()); let head = min < common_num_double ? `${zero_str}${min}` : min; let end = second { slideronchange.call(this, value, mode); })export function slideronchange(value: number, mode: sliderchangemode) { this.currenttime = parseint(value.tostring()); this.controller.setcurrenttime(parseint(value.tostring()), seekmode.accurate); ...};到这里我们就实现了自定义控制器的构建,两个text组件显示的时长是由slider组件的onchange回调事件来进行传递的,而text组件的数值与视频播放进度数值value则通过是onupdate与onchange事件并借由@provide @consume装饰器进行的数据联动。


3D打印活性仿生骨技术取得突破,可在生物体内生长发育
华为麒麟芯片会消失吗,3nm麒麟9010正在研发
C语言基础知识(6)--数组与函数
AI在手游方面有哪些新的应用?
区块链金融行业标准进行的怎么样了
鸿蒙ArkUI开发-Video组件的使用
一文弄懂CPU卡是什么
全方位测评奥迪Q7 35TFSI 运动型
国家鼓励的电动汽车到底安全吗?
联网汽车对于物联网卡都有哪些个性化需求
三星Note7官方翻新版要来了, 网友评论: “亡者归来”
特斯拉电机小而牛的原因
打造中国云计算生态,阿里云平台强势出击
OPPO旗舰机OPPOMIX即将来临,全面屏+骁龙835比OPPOFind9值得期待
聚焦超声技术可为阿尔茨海默氏病的治疗带来帮助
led显示屏真的节能了吗
拓扑结构有哪些
LG 五年亏损 45 亿美元,手机业务下滑,索尼会不会是下一个?
NFC与RFID技术有什么新的发展
三星S10+评测 素质均衡却又不乏亮点