HarmonyOS4.0从零开始的开发教程11Video组件的使用

news2024/11/23 14:50:22

HarmonyOS(九)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表示视频控制器。

参数的具体描述如下表:

参数名参数类型必填
srcstring | Resource
currentProgressRatenumber | string | PlaybackSpeed8+
previewUristring | PixelMap8+ | Resource
controllerVideoController

说明

视频支持的规格是:mp4、mkv、webm、TS。

下面我们通过具体的例子来说明参数的使用方法,我们选择播放本地视频,视频未播放时的预览图片路径也为本地,代码实现如下:

@Component
export 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组件还支持是否静音、是否自动播放、控制栏是否显示、视频显示模式以及单个视频是否循环播放五个私有属性。

名称参数类型描述
mutedboolean是否静音。默认值:false
autoPlayboolean是否自动播放。默认值:false
controlsboolean控制视频播放的控制栏是否显示。默认值:true
objectFitImageFit设置视频显示模式。默认值:Cover
loopboolean是否单个视频循环播放。默认值:false

其中,objectFit 中视频显示模式包括Contain、Cover、Auto、Fill、ScaleDown、None 6种模式,默认情况下使用ImageFit.Cover(保持宽高比进行缩小或者放大,使得图片两边都大于或等于显示边界),其他效果(如自适应显示、保持原有尺寸显示、不保持宽高比进行缩放等)可以根据具体使用场景/设备来进行选择。

在Codelab示例中体现了controls、autoplay和loop属性的配置,示例代码如下:

@Component
export 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组件来实现视频进度条的效果,代码如下:

@Component
export 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 < COMMON_NUM_DOUBLE ? `${ZERO_STR}${second}` : second;
  this.durationStringTime = `${head}${SPLIT}${end}`;
  ...
};

设置进度条参数及属性

Slider({
  value: this.currentTime,
  min: 0,
  max: this.durationTime,
  step: 1,
  style: SliderStyle.OutSet
})
  .blockColor($r('app.color.white'))
  .width(STRING_PERCENT.SLIDER_WITH)
  .trackColor(Color.Gray)
  .selectedColor($r('app.color.white'))
  .showSteps(true)
  .showTips(true)
  .trackThickness(this.isOpacity ? SMALL_TRACK_THICK_NESS : BIG_TRACK_THICK_NESS)
  .onChange((value: number, mode: SliderChangeMode) => {...})

计算当前进度播放时间及添加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 < COMMON_NUM_DOUBLE ? `${ZERO_STR}${second}` : second;
  let nowTime = `${head}${SPLIT}${end}`;
  return nowTime;
}; 

指定视频播放进度及添加onChange事件回调

如需手动进行进度条的拖动,则需要在Slider组件中指定播放进度,并为Slider组件添加onChange事件回调。Slider滑动时就会触发该事件回调,从而实现将视频定位到进度条当前刷新位置,完成时长组件渲染与视频播放进度数据联动。

Slider({...})
  .onChange((value: number, mode: SliderChangeMode) => {
    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装饰器进行的数据联动。

参考链接

  • Video组件的更多属性和参数的使用,可以参考API:Video。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1307067.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

06_W5500_DHCP

1.DHCP协议介绍&#xff1a; DHCP&#xff08;Dynamic Host Configuration Protocol&#xff09;是一种用于自动分配IP地址和其他网络配置信息的协议。它允许网络中的设备&#xff08;如计算机、手机、打印机等&#xff09;在连接到网络时自动获取IP地址、子网掩码、默认网关、…

数据入表 | 详解数据资产会计核算与企业应对

从2015年《促进大数据发展行动纲要》到2022年《数据20条》到2023年8月份出台了《企业数据资源相关会计处理暂行规定》&#xff0c;可见国家层面对数据的重视和探索如何进一步挖掘数据价值&#xff0c;发挥数据的应用潜力。一石激起千层浪&#xff0c;面对如此重要的规定&#x…

C++1114新标准——统一初始化(Uniform Initialization)、Initializer_list(初始化列表)、explicit

系列文章目录 C11&14新标准——Variadic templates&#xff08;数量不定的模板参数&#xff09; C11&14新标准——Uniform Initialization&#xff08;统一初始化&#xff09;、Initializer_list&#xff08;初始化列表&#xff09;、explicit 文章目录 系列文章目录1…

python+pytest接口自动化(12)-自动化用例编写思路 (使用pytest编写一个测试脚本)

经过之前的学习铺垫&#xff0c;我们尝试着利用pytest框架编写一条接口自动化测试用例&#xff0c;来厘清接口自动化用例编写的思路。 我们在百度搜索天气查询&#xff0c;会出现如下图所示结果&#xff1a; 接下来&#xff0c;我们以该天气查询接口为例&#xff0c;编写接口测…

【Java 基础】32 定时调度

文章目录 Timer 类创建 Timer注意事项 ScheduledExecutorService 接口创建 ScheduledExecutorService注意事项 选择合适的定时调度方式Timer 的适用场景ScheduledExecutorService 的适用场景 总结 在软件开发中&#xff0c;定时任务是一种常见的需求&#xff0c;用于周期性地执…

了解振弦采集仪:工程质量控制的得力助手

了解振弦采集仪&#xff1a;工程质量控制的得力助手 振弦采集仪是一种专门用于工程质量控制的仪器设备&#xff0c;它可以帮助工程师监测和评估结构物的振动性能。它的工作原理是通过将传感器固定在结构物上的振弦上&#xff0c;然后测量振弦的振动频率、振动幅度等参数&#…

GPTs prompts灵感库:创意无限,专业级创作指南,打造吸睛之作的秘诀

GPTs prompts灵感库&#xff1a;创意无限&#xff0c;专业级创作指南&#xff0c;打造吸睛之作的秘诀 优质prompt展示 1.1 极简翻译 中英文转换 你是一个极简翻译工具&#xff0c;请在对话中遵循以下规则&#xff1a; - Prohibit repeating or paraphrasing any user instru…

mysql更新某个字段=这个字段+字符串

当我们像c#中用拼接执行sql语句时&#xff0c;如下&#xff1a; UPDATE abpusers set UserNameqyUserName where UserNameqy-wh 会出现以下错误&#xff1a; 在mysql中通过concat函数来实现 UPDATE abpusers set UserNameCONCAT(qy_,UserName) where UserNameqy-wh

Unity中实现ShaderToy卡通火(总结篇)

文章目录 前言一、把卡通火修改为后处理效果1、在Shader属性面板定义属性接收帧缓存纹理2、在片元着色器对其纹理采样后&#xff0c;与卡通火相加输出请添加图片描述 二、我们自定义卡通火1、修改 _CUTOFF 使卡通火显示在屏幕两侧2、使火附近屏幕偏红色 前言 在之前的文章中&a…

PP材料粘接ABS材料使用UV胶的好处?

跟随着现阶段材料的不断发展更迭&#xff0c;PP材料应用越来越广&#xff0c;生产效率要求越来越高&#xff0c;为了加快生产&#xff0c;提高效率&#xff0c;PP材料的粘接上使用UV胶粘接PP&#xff08;聚丙烯&#xff09;和ABS&#xff08;丙烯腈-丁二烯-苯乙烯共聚物&#x…

AI日报:人工智能与新材料的发现

文章目录 总览人工智能正在革命性地发现新的或更强的材料&#xff0c;这将改变制造业。更坚韧的合金问题研究解决方案 新材料人工智能存在的挑战方法探索 日本的研究人员正在使用人工智能制造更强的金属合金或发现新材料&#xff0c;并彻底改变制造过程 总览 日本的研究人员开…

解决使用pnpm安装时Sharp模块报错的方法

在使用pnpm进行项目依赖安装的过程中&#xff0c;有时候会遇到Sharp模块报错的情况。Sharp是一个用于处理图像的Node.js模块&#xff0c;但它的安装可能会因为各种原因而失败&#xff0c;导致项目无法正常启动。本文将介绍这个问题的方法。 问题描述 解决方法 在命令行分别输…

【Zerotier】自建PLANET服务器内网地址连接

之前已经完成了【Zerotier】通过docker自建PLANET服务器&#xff0c;但是遇到一个问题&#xff0c;因为各种原因&#xff0c;内网里面的ZeroTier Client无法通过PLANET服务器的公网地址连接&#xff0c;愁怀了这下。在经过多方测试验证后&#xff0c;可以采取重新生成一个PLANE…

MYSQL练题笔记-子查询-电影评分

一、题目相关内容 1&#xff09;相关的表 2&#xff09;题目 3&#xff09;帮助理解题目的示例&#xff0c;提供返回结果的格式 二、自己初步的理解 1.字典序是指从前到后比较两个字符串大小的方法。 首先比较第1个字符&#xff0c;如果不同则第1个字符较小的字符串更小&…

Linux install manual 1Panel

前言 1Panel 是一个现代化、开源的 Linux 服务器运维管理面板。1Panel 的功能和优势包括: 快速建站:深度集成 Wordpress 和 Halo,域名绑定、SSL 证书配置等一键搞定;高效管理:通过 Web 端轻松管理 Linux 服务器,包括主机监控、文件管理、数据库管理、容器管理等;安全可…

CentOS 7.x操作系统的ECS云服务器上搭建WordPress网站

WordPress是使用PHP语言开发的博客平台&#xff0c;在支持PHP和MySQL数据库的服务器上&#xff0c;您可以用WordPress架设自己的网站&#xff0c;也可以用作内容管理系统&#xff08;CMS&#xff09;。本教程介绍如何在CentOS 7.x操作系统的ECS实例上搭建WordPress网站。 背景…

指针浅谈(四)

在指针浅谈(三)中http://t.csdnimg.cn/wYgJG我们知道了数组名是什么&#xff0c;任何用指针访问数组&#xff0c;一维数组传参的本质是什么&#xff0c;这一次我们来学习二级指针&#xff0c;指针数组&#xff0c;以及如何用指针数组模拟二维数组。 1.二级指针 指针变量也是变…

数据爬虫:获取申万一级行业数据

目录 1. 获取访问接口 2. 链接网址 3. 链接名单 免责声明&#xff1a;本文由作者参考相关资料&#xff0c;并结合自身实践和思考独立完成&#xff0c;对全文内容的准确性、完整性或可靠性不作任何保证。同时&#xff0c;文中提及的数据仅作为举例使用&#xff0c;不构成推荐…

1-4、JDK目录结构

语雀原文链接 文章目录 1、目录结构2、JDK中rt.jar、tools.jar和dt.jar作用3、bin目录部分说明&#xff08;基本工具&#xff09; 1、目录结构 bin目录&#xff1a;包含一些用于开发Java程序的工具&#xff0c;例如&#xff1a;编译工具(javac.exe)、运行工具 (java.exe) 、打…

[Python进阶] 消息框、弹窗:批处理消息框\msg

5.20 消息框、弹窗&#xff1a;批处理消息框\msg 批处理中的MSG命令是一个用于向用户发送消息的命令。它可以用来在批处理脚本中向指定的用户发送消息。 命令格式为MSG {username | sessionname | sessionid | filename | *}[/SERVER:servername] [/TIME:seconds] [/V] [/W] […