OpenHarmony视频播放的基本实现
前言
OpenHarmony 视频播放将视频数据转码并输出到设备进行播放,同时管理播放任务,注册播放监听回调等。本文将带大家学习如何搜索视频并对视频播放全流程场景开发进行介绍说明。
API和组件介绍
-
媒体子系统为开发者提供一套简单且易于理解的接口,使得开发者能够方便接入系统并使用系统的媒体资源。
-
用于访问和修改用户等个人媒体数据信息(如音频、视频、图片、文档等)。
-
可用于EGL/OpenGLES和媒体数据写入,并显示在XComponent组件。
-
用于播放单个视频并控制其播放状态的组件。
视频播放组件架构图


视频播放状态机


兼容性
推荐使用视频软件主流的播放格式和主流分辨率,不建议开发者自制非常或者异常码流,以免产生无法播放、卡住、花屏等兼容性问题。
主流的播放格式和主流分辨率:
| 视频容器规格 | 规格描述 | 分辨率 |
|---|---|---|
| mp4 | 视频格式:H264/MPEG2/MPEG4/H263 音频格式:AAC/MP3 | 主流分辨率,如1080P/720P/480P/270P |
| mkv | 视频格式:H264/MPEG2/MPEG4/H263 音频格式:AAC/MP3 | 主流分辨率,如1080P/720P/480P/270P |
| ts | 视频格式:H264/MPEG2/MPEG4 音频格式:AAC/MP3 | 主流分辨率,如1080P/720P/480P/270P |
| webm | 视频格式:VP8 音频格式:VORBIS | 主流分辨率,如1080P/720P/480P/270P |
开发流程
-
在配置文件中添加视频播放需要的权限,编写用户授权逻辑;
-
在页面中添加 XComponent 组件或者 Video组件;
-
获取媒体库实例;
-
搜索文件资源;
-
把文件地址放入 VideoPlayer 或者 Video组件;
-
编写播放、暂停、循环播放和监听等逻辑。
权限
视频播放需要用户授予相应的权限后才能使用媒体库资源或网络资源,如果用户不同意授权,应用是无法使用媒体库资源或网络资源。
需要的权限:
-
网络权限: ohos.permission.INTERNET
-
媒体和文件操作权限: ohos.permission.MEDIA_LOCATION, ohos.permission.READ_MEDIA, ohos.permission.WRITE_MEDIA
相关文档:
配置权限
在进行视频播放开发前需要先在配置文件中配置需要的权限信息。
Stage 模型配置 module.json5
{ "module":{ "requestPermissions": [ { "name": "ohos.permission.INTERNET" }, { "name": "ohos.permission.MEDIA_LOCATION" }, { "name": "ohos.permission.READ_MEDIA" }, { "name": "ohos.permission.WRITE_MEDIA" } ] } }
FA 模型配置 config.json
{ "module":{ "reqPermissions": [ { "name": "ohos.permission.INTERNET" }, { "name": "ohos.permission.MEDIA_LOCATION" }, { "name": "ohos.permission.READ_MEDIA" }, { "name": "ohos.permission.WRITE_MEDIA" } ] } }
请求用户授权
获取 AbilityContext
Stage 模型通过继承 Ability 接口,在 Ability 被拉起时获取上下文环境。
export default class MainAbility extends Ability { onCreate(want, launchParam) { globalThis.context = this.context } }
FA 模型通过 FeatureAbility API 获取上下文环境。
import FeatureAbility from '@ohos.ability.featureAbility' globalThis.context = FeatureAbility.getContext()
获取 bundleName
Stage 模型通过 Context 可以直接获取到当前应用包名信息。
const bundleName = globalThis.context.abilityInfo.bundleName
FA 模型通过 getBundleName 接口获取当前应用包名信息。
const bundleName = globalThis.context.getBundleName()
获取 accessTokenId
根据给定的包名获取 ApplicationInfo (应用程序信息),其中包含字段:accessTokenId
accessTokenId 是应用在安装时由系统分配的唯一标识,重新安装会刷新。
import Bundle from '@ohos.bundle' const appInfo = Bundle.getApplicationInfo(bundleName: string, bundleFlags: number, userId?: number): Promise<ApplicationInfo> const accessTokenId = appInfo.accessTokenId
校验应用是否授予权限
-
获取访问控制模块对象。
import AbilityAccessCtrl from '@ohos.abilityAccessCtrl' AtManager = AbilityAccessCtrl.createAtManager()
-
校验应用是否授予权限, tokenID 为应用程序的 accessTokenId,permissionName 为权限名称。
AtManager.verifyAccessToken(tokenID: number, permissionName: string): Promise<GrantStatus>
GrantStatus 说明
export enum GrantStatus { // access_token permission check fail PERMISSION_DENIED = -1, // access_token permission check success PERMISSION_GRANTED = 0, }
动态申请权限
拉起弹窗请求用户授权,传入需要申请的权限数组,得到用户授权结果。
Context.requestPermissionsFromUser(permissions: Array<string>) : Promise<PermissionRequestResult>;
PermissionRequestResult 说明
interface PermissionRequestResult { requestCode: number; // 用户传入的权限数组 permissions: Array<string>; // 相应请求权限的结果数组。0表示授权成功,-1表示失败 authResults: Array<number>; }
请求用户授权代码示例
Stage 模型为例:
Module 配置文件: Ability 生命周期管理类: 请求用户授权页面:
获取媒体库资源
通过媒体库管理器搜索媒体视频资源。
-
获取媒体库的实例,用于访问和修改用户等个人媒体数据信息(如音频、视频、图片、文档等)。
import MediaLibrary from '@ohos.multimedia.mediaLibrary'; mediaLib = MediaLibrary.getMediaLibrary(context: Context): MediaLibrary
-
获取文件检索结果集。
fetchFileResult = await getFileAssets(options: MediaFetchOptions): Promise<FetchFileResult>
-
获取文件资源
fileAsset = await fetchFileResult.getFirstObject(): Promise<FileAsset>
-
获取视频播放地址
uri = fileAsset.uri
获取视频播放资源代码示例
Stage 模型为例:
获取视频播放资源页面:
Video 组件
用于播放单个视频并控制其播放状态的组件。
在页面 build 中添加 Video 组件
controller: VideoController = new VideoController() Video({ src: this.src, previewUri: this.previewUri, currentProgressRate: this.currentProgressRate, controller: this.controller }) .muted(this.muted) .autoPlay(this.autoPlay) .controls(this.controls) .objectFit(this.objectFit) .loop(this.loop) .onStart(() => { console.log('onStart'); }) .onPause(() => { console.log('onPause'); }) .onFinish(() => { console.log('onFinish'); }) .onError(() => { console.error('onError'); }) .onPrepared((e) => { console.log('onPrepared is ' + e.duration); }) .onSeeking((e) => { console.log('onSeeking is ' + e.time); }) .onSeeked((e) => { console.log('onSeeked ' + e.time); }) .onUpdate((e) => { console.log('onUpdate ' + e.time); })
VideoOptions
| 参数名 | 参数类型 | 必填 | 默认值 | 参数描述 |
|---|---|---|---|---|
| src | string | Resource | 否 | - | 视频播放源的路径,支持本地视频路径和网络路径。 支持在resources下面的video或rawfile文件夹里放置媒体资源。 支持dataability://的路径前缀,用于访问通过Data Ability提供的视频路径。 |
| currentProgressRate | number | PlaybackSpeed | 否 | 1.0 | PlaybackSpeed. Speed_Forward_1_00_X | 视频播放倍速。 |
| previewUri | string | PixelMap | Resource | 否 | - | 预览图片的路径。 |
| controller | VideoController | 否 | - | 控制器。 |
属性
| 名称 | 参数类型 | 默认值 | 描述 |
|---|---|---|---|
| muted | boolean | false | 是否静音。 |
| autoPlay | boolean | false | 是否自动播放。 |
| controls | boolean | true | 控制视频播放的控制栏是否显示。 |
| objectFit | ImageFit | Cover | 设置视频显示模式。 |
| loop | boolean | false | 是否单个视频循环播放。 |
事件
| 名称 | 功能描述 |
|---|---|
| onStart() => void | 播放时触发该事件。 |
| onPause() => void | 暂停时触发该事件。 |
| onFinish() => void | 播放结束时触发该事件。 |
| onError() => void | 播放失败时触发该事件。 |
| onPrepared(event?: { duration: number }) => void | 视频准备完成时触发该事件,通过duration可以获取视频时长,单位为秒(s)。 |
| onSeeking(event?: { time: number }) => void | 操作进度条过程时上报时间信息,单位为s。 |
| onSeeked(event?: { time: number }) => void | 操作进度条完成后,上报播放时间信息,单位为s。 |
| onUpdate(event?: { time: number }) => void | 播放进度变化时触发该事件,单位为s,更新时间间隔为250ms。 |
VideoController
start
start(): void
开始播放。
pause
pause(): void
暂停播放。
stop
stop(): void
停止播放。
requestFullscreen
requestFullscreen(value: boolean)
请求全屏播放。
参数:
| 参数名 | 参数类型 | 必填 | 默认值 | 参数描述 |
|---|---|---|---|---|
| value | boolean | 是 | false | 是否全屏播放。 |
exitFullscreen
exitFullscreen()
退出全屏播放。
setCurrentTime
setCurrentTime(value: number)
指定视频播放的进度位置。
参数:
| 参数名 | 参数类型 | 必填 | 默认值 | 参数描述 |
|---|---|---|---|---|
| value | number | 是 | - | 视频播放进度位置。 |
setCurrentTime
setCurrentTime(value: number, seekMode: SeekMode)
指定视频播放的进度位置,并指定跳转模式。
参数:
| 参数名 | 参数类型 | 必填 | 默认值 | 参数描述 |
|---|---|---|---|---|
| value | number | 是 | - | 视频播放进度位置。 |
| seekMode | SeekMode | 是 | - | 跳转模式。 |
SeekMode 说明:
| 名称 | 描述 |
|---|---|
| PreviousKeyframe | 跳转到前一个最近的关键帧。 |
| NextKeyframe | 跳转到后一个最近的关键帧。 |
| ClosestKeyframe | 跳转到最近的关键帧。 |
| Accurate | 精准跳转,不论是否为关键帧。 |
Video组件代码示例
Stage 模型为例:
Video组件页面:
VideoPlayer 播放器
视频播放管理类,用于管理和播放视频媒体。
XComponent 组件
-
在页面 build 中添加 XComponent 组件
XComponent 可用于EGL/OpenGLES和媒体数据写入,并显示在XComponent组件,相机中使用 XComponent 组件来展示预览图像数据。
xComponentController: XComponentController = new XComponentController() XComponent({ id: '', type: 'surface', controller: this.xComponentController }).onLoad(() => {})
XComponent 的 width 和 height 可以随页面逻辑需要设置。
-
获取 XComponent 对应 Surface 的 ID
xComponentController.getXComponentSurfaceId(): string
-
设置 XComponent 持有 Surface 的宽度和高度
xComponentController.setXComponentSurfaceSize(value: {surfaceWidth: number, surfaceHeight: number}): void
Surface:用于管理和传递图形和媒体的共享内存。具体场景包括图形的送显、合成,媒体的播放、录制等。 Surface 的 width 和 height 不可随意设置,需要设置视频的宽和高。
VideoPlayer
一个简单的播放器
-
创建 Video 播放管理类
videoPlayer = await Media.createVideoPlayer() : Promise<VideoPlayer>
-
设置视频媒体 URL
this.videoPlayer.src = 'fd://xx'
-
设置 SurfaceId
this.videoPlayer.setDisplaySurface(surfaceId: string): Promise<void>
SurfaceId 从 XComponent 组件控制器获取。 SetDisplaySurface 需要在设置 url 和 Prepare 之间,无音频的视频流必须设置 Surface 否则 Prepare 失败。
-
准备播放视频
this.videoPlayer.prepare(callback: AsyncCallback<void>): void
-
开始播放视频
this.videoPlayer.play(): Promise<void>;
属性
| 名称 | 类型 | 可读 | 可写 | 说明 |
|---|---|---|---|---|
| url | string | 是 | 是 | 视频媒体URL,支持当前主流的视频格式(mp4、mpeg-ts、webm、mkv)。 |
| loop | boolean | 是 | 是 | 视频循环播放属性,设置为'true'表示循环播放。 |
| currentTime | number | 是 | 否 | 视频的当前播放位置。 |
| duration | number | 是 | 否 | 视频时长,返回-1表示直播模式。 |
| state | VideoPlayState | 是 | 否 | 视频播放的状态。 |
| width | number | 是 | 否 | 视频宽。 |
| height | number | 是 | 否 | 视频高。 |
事件
| 名称 | 功能描述 |
|---|---|
| on(type: 'playbackCompleted', callback: Callback<void>): void | 开始监听视频播放完成事件。 |
| on(type: 'bufferingUpdate', callback: (infoType: BufferingInfoType, value: number) => void): void | 开始监听视频缓存更新事件。 |
| on(type: 'startRenderFrame', callback: Callback<void>): void | 开始监听视频播放首帧送显上报事件。 |
| on(type: 'videoSizeChanged', callback: (width: number, height: number) => void): void | 开始监听视频播放宽高变化事件。 |
| on(type: 'error', callback: ErrorCallback): void | 开始监听视频播放错误事件。 |
| on(type: 'availableBitrateCollected', callback: (bitrates: Array<number>) => void): void | 开始监听视频播放码率上报事件。 |
setDisplaySurface
setDisplaySurface(surfaceId: string): Promise<void>
设置SurfaceId。
注意:SetDisplaySurface需要在设置url和Prepare之间,无音频的视频流必须设置Surface否则Prepare失败。
参数:
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| surfaceId | string | 是 | SurfaceId |
| callback | function | 是 | 设置SurfaceId的回调方法。 |
prepare
prepare(): Promise<void>
准备播放视频。
参数:
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| callback | function | 是 | 准备播放视频的回调方法。 |
play
play(callback: AsyncCallback<void>): void;
开始播放视频。
参数:
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| callback | function | 是 | 开始播放视频的回调方法。 |
pause
pause(callback: AsyncCallback<void>): void
暂停播放视频。
参数:
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| callback | function | 是 | 暂停播放视频的回调方法。 |
stop
stop(callback: AsyncCallback<void>): void
停止播放视频。
参数:
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| callback | function | 是 | 停止播放视频的回调方法。 |
reset
reset(callback: AsyncCallback<void>): void
切换播放视频。
参数:
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| callback | function | 是 | 切换播放视频的回调方法。 |
seek
seek(timeMs: number, mode:SeekMode, callback: AsyncCallback<number>): void
跳转到指定播放位置。
参数:
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| timeMs | number | 是 | 指定的跳转时间节点,单位毫秒(ms)。 |
| mode | SeekMode | 是 | 跳转模式。 |
| callback | function | 是 | 跳转到指定播放位置的回调方法。 |
setSpeed
setSpeed(speed:number, callback: AsyncCallback<number>): void
设置播放速度。
参数:
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| speed | number | 是 | 指定播放视频速度。 |
| callback | function | 是 | 设置播放速度的回调方法。 |
selectBitrate
selectBitrate(bitrate:number): Promise<number>
设置码率。
参数:
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| bitrate | number | 是 | 指定码率播放,用于hls多码率场景,单位为bps。 |
getTrackDescription
getTrackDescription(): Promise<Array<MediaDescription>>
获取视频轨道信息。
release
release(): Promise<void>
释放视频资源。
VideoPlayer代码示例
Stage 模型为例:
VideoPlayer页面:
参考文献
[1] 视频播放开发指导.
更多推荐


所有评论(0)