openharmony视频开发(代码片段)

Geek.Fan Geek.Fan     2023-01-28     501

关键词:

1.简介

        OpenHarmony视频播放的主要工作是将视频数据转码并输出到设备进行播放,同时管理播放任务,包括开始播放、暂停播放、停止播放、资源释放、音量设置、跳转播放位置、设置倍数、获取轨道信息等功能控制。本文将对视频播放全流程、视频切换、视频循环播放等场景开发进行介绍说明。

2. OpenHarmony视频播放系统运行机制

         视频播放状态变化示意图如图1.1所示。

                                                     图1.1 视频播放状态变化示意图

        视频播放外部模块交互图如图1.2所示:

                                               图1.2 视频播放外部模块交互图

        说明:三方应用通过调用JS接口层提供的js接口实现相应功能时,框架层会通过Native Framework的媒体服务,调用音频部件将软件解码后的音频数据,输出至音频HDI,和图形子系统将硬件接口层的解码HDI部件的解码后的图像数据,输出至显示HDI,实现视频播放功能。

注意:视频播放需要显示、音频、编解码等硬件能力。

  1. 三方应用从Xcomponent组件获取surfaceID。
  2. 三方应用把surfaceID传递给VideoPlayer JS。
  3. 媒体服务把帧数据flush给surface buffer。

3.兼容性说明

        推荐使用视频软件主流的播放格式和主流分辨率,不建议开发者自制非常或者异常码流,以免产生无法播放、卡住、花屏等兼容性问题。若发生此类问题不会影响系统,退出码流播放即可。

        主流的播放格式和主流分辨率如下:

开发指导

详细API含义可参考:媒体服务API文档VideoPlayer

(1)、全流程场景:

        视频播放的全流程场景包含:创建实例,设置url,设置SurfaceId,准备播放视频,播放视频,暂停播放,获取轨道信息,跳转播放位置,设置音量,设置倍速,结束播放,重置,释放资源等流程。

VideoPlayer支持的url媒体源输入类型可参考:url属性说明

Xcomponent创建方法可参考:Xcomponent创建方法

import media from '@ohos.multimedia.media'
import fileIO from '@ohos.fileio'
export class VideoPlayerDemo 
  // 函数调用发生错误时用于上报错误信息
  failureCallback(error) 
    console.info(`error happened,error Name is $error.name`);
    console.info(`error happened,error Code is $error.code`);
    console.info(`error happened,error Message is $error.message`);
  

  // 当函数调用发生异常时用于上报错误信息
  catchCallback(error) 
    console.info(`catch error happened,error Name is $error.name`);
    console.info(`catch error happened,error Code is $error.code`);
    console.info(`catch error happened,error Message is $error.message`);
  

  // 用于打印视频轨道信息
  printfDescription(obj) 
    for (let item in obj) 
      let property = obj[item];
      console.info('key is ' + item);
      console.info('value is ' + property);
    
  

  async videoPlayerDemo() 
    let videoPlayer = undefined;
    let surfaceID = 'test' // surfaceID用于播放画面显示,具体的值需要通过Xcomponent接口获取,相关文档链接见上面Xcomponent创建方法
    let fdPath = 'fd://'
    // path路径的码流可通过"hdc file send D:\\xxx\\H264_AAC.mp4 /data/app/el1/bundle/public/ohos.acts.multimedia.video.videoplayer/ohos.acts.multimedia.video.videoplayer/assets/entry/resources/rawfile" 命令,将其推送到设备上
    let path = '/data/app/el1/bundle/public/ohos.acts.multimedia.video.videoplayer/ohos.acts.multimedia.video.videoplayer/assets/entry/resources/rawfile/H264_AAC.mp4';
    await fileIO.open(path).then((fdNumber) => 
      fdPath = fdPath + '' + fdNumber;
      console.info('open fd success fd is' + fdPath);
    , (err) => 
      console.info('open fd failed err is' + err);
    ).catch((err) => 
      console.info('open fd failed err is' + err);
    );
    // 调用createVideoPlayer接口返回videoPlayer实例对象
    await media.createVideoPlayer().then((video) => 
      if (typeof (video) != 'undefined') 
        console.info('createVideoPlayer success!');
        videoPlayer = video;
       else 
        console.info('createVideoPlayer fail!');
      
    , this.failureCallback).catch(this.catchCallback);
    // 设置播放源
    videoPlayer.url = fdPath;

    // 设置surfaceID用于显示视频画面
    await videoPlayer.setDisplaySurface(surfaceID).then(() => 
      console.info('setDisplaySurface success');
    , this.failureCallback).catch(this.catchCallback);

    // 调用prepare完成播放前准备工作
    await videoPlayer.prepare().then(() => 
      console.info('prepare success');
    , this.failureCallback).catch(this.catchCallback);

    // 调用play接口正式开始播放
    await videoPlayer.play().then(() => 
      console.info('play success');
    , this.failureCallback).catch(this.catchCallback);

    // 暂停播放
    await videoPlayer.pause().then(() => 
      console.info('pause success');
    , this.failureCallback).catch(this.catchCallback);

    // 通过promise回调方式获取视频轨道信息communication_dsoftbus
    let arrayDescription;
    await videoPlayer.getTrackDescription().then((arrlist) => 
      if (typeof (arrlist) != 'undefined') 
        arrayDescription = arrlist;
       else 
        console.log('video getTrackDescription fail');
      
    , this.failureCallback).catch(this.catchCallback);

    for (let i = 0; i < arrayDescription.length; i++) 
      this.printfDescription(arrayDescription[i]);
    

    // 跳转播放时间到50s位置,具体入参意义请参考接口文档
    let seekTime = 50000;
    await videoPlayer.seek(seekTime, media.SeekMode.SEEK_NEXT_SYNC).then((seekDoneTime) => 
      console.info('seek success');
    , this.failureCallback).catch(this.catchCallback);

    // 音量设置接口,具体入参意义请参考接口文档
    let volume = 0.5;
    await videoPlayer.setVolume(volume).then(() => 
      console.info('setVolume success');
    , this.failureCallback).catch(this.catchCallback);

    // 倍速设置接口,具体入参意义请参考接口文档
    let speed = media.PlaybackSpeed.SPEED_FORWARD_2_00_X;
    await videoPlayer.setSpeed(speed).then(() => 
      console.info('setSpeed success');
    , this.failureCallback).catch(this.catchCallback);

    // 结束播放
    await videoPlayer.stop().then(() => 
      console.info('stop success');
    , this.failureCallback).catch(this.catchCallback);

    // 重置播放配置
    await videoPlayer.reset().then(() => 
      console.info('reset success');
    , this.failureCallback).catch(this.catchCallback);

    // 释放播放资源
    await videoPlayer.release().then(() => 
      console.info('release success');
    , this.failureCallback).catch(this.catchCallback);

    // 相关对象置undefined
    videoPlayer = undefined;
    surfaceID = undefined;
  

(2)、正常播放场景:

import media from '@ohos.multimedia.media'
import fileIO from '@ohos.fileio'
export class VideoPlayerDemo 
  // 函数调用发生错误时用于上报错误信息
  failureCallback(error) 
    console.info(`error happened,error Name is $error.name`);
    console.info(`error happened,error Code is $error.code`);
    console.info(`error happened,error Message is $error.message`);
  

  // 当函数调用发生异常时用于上报错误信息
  catchCallback(error) 
    console.info(`catch error happened,error Name is $error.name`);
    console.info(`catch error happened,error Code is $error.code`);
    console.info(`catch error happened,error Message is $error.message`);
  

  // 用于打印视频轨道信息
  printfDescription(obj) 
    for (let item in obj) 
      let property = obj[item];
      console.info('key is ' + item);
      console.info('value is ' + property);
    
  

  async videoPlayerDemo() 
    let videoPlayer = undefined;
    let surfaceID = 'test' // surfaceID用于播放画面显示,具体的值需要通过Xcomponent接口获取,相关文档链接:
    let fdPath = 'fd://'
    // path路径的码流可通过"hdc file send D:\\xxx\\H264_AAC.mp4 /data/app/el1/bundle/public/ohos.acts.multimedia.video.videoplayer/ohos.acts.multimedia.video.videoplayer/assets/entry/resources/rawfile" 命令,将其推送到设备上
    let path = '/data/app/el1/bundle/public/ohos.acts.multimedia.video.videoplayer/ohos.acts.multimedia.video.videoplayer/assets/entry/resources/rawfile/H264_AAC.mp4';
    await fileIO.open(path).then((fdNumber) => 
      fdPath = fdPath + '' + fdNumber;
      console.info('open fd success fd is' + fdPath);
    , (err) => 
      console.info('open fd failed err is' + err);
    ).catch((err) => 
      console.info('open fd failed err is' + err);
    );
    // 调用createVideoPlayer接口返回videoPlayer实例对象
    await media.createVideoPlayer().then((video) => 
      if (typeof (video) != 'undefined') 
        console.info('createVideoPlayer success!');
        videoPlayer = video;
       else 
        console.info('createVideoPlayer fail!');
      
    , this.failureCallback).catch(this.catchCallback);
    // 设置播放源
    videoPlayer.url = fdPath;

    // 设置surfaceID用于显示视频画面
    await videoPlayer.setDisplaySurface(surfaceID).then(() => 
      console.info('setDisplaySurface success');
    , this.failureCallback).catch(this.catchCallback);

    // 调用prepare完成播放前准备工作
    await videoPlayer.prepare().then(() => 
      console.info('prepare success');
    , this.failureCallback).catch(this.catchCallback);

    // 调用play接口正式开始播放
    await videoPlayer.play().then(() => 
      console.info('play success');
    , this.failureCallback).catch(this.catchCallback);

    // 结束播放
    await videoPlayer.stop().then(() => 
      console.info('stop success');
    , this.failureCallback).catch(this.catchCallback);

    // 释放播放资源
    await videoPlayer.release().then(() => 
      console.info('release success');
    , this.failureCallback).catch(this.catchCallback);

    // 相关对象置undefined
    videoPlayer = undefined;
    surfaceID = undefined;
  

(3)、切视频场景:

import media from '@ohos.multimedia.media'
import fileIO from '@ohos.fileio'
export class VideoPlayerDemo 
  // 函数调用发生错误时用于上报错误信息
  failureCallback(error) 
    console.info(`error happened,error Name is $error.name`);
    console.info(`error happened,error Code is $error.code`);
    console.info(`error happened,error Message is $error.message`);
  

  // 当函数调用发生异常时用于上报错误信息
  catchCallback(error) 
    console.info(`catch error happened,error Name is $error.name`);
    console.info(`catch error happened,error Code is $error.code`);
    console.info(`catch error happened,error Message is $error.message`);
  

  // 用于打印视频轨道信息
  printfDescription(obj) 
    for (let item in obj) 
      let property = obj[item];
      console.info('key is ' + item);
      console.info('value is ' + property);
    
  

  async videoPlayerDemo() 
    let videoPlayer = undefined;
    let surfaceID = 'test' // surfaceID用于播放画面显示,具体的值需要通过Xcomponent接口获取,相关文档链接:
    let fdPath = 'fd://'
    // path路径的码流可通过"hdc file send D:\\xxx\\H264_AAC.mp4 /data/app/el1/bundle/public/ohos.acts.multimedia.video.videoplayer/ohos.acts.multimedia.video.videoplayer/assets/entry/resources/rawfile" 命令,将其推送到设备上
    let path = '/data/app/el1/bundle/public/ohos.acts.multimedia.video.videoplayer/ohos.acts.multimedia.video.videoplayer/assets/entry/resources/rawfile/H264_AAC.mp4';
    let nextPath = '/data/app/el1/bundle/public/ohos.acts.multimedia.video.videoplayer/ohos.acts.multimedia.video.videoplayer/assets/entry/resources/rawfile/MP4_AAC.mp4';
    await fileIO.open(path).then((fdNumber) => 
      fdPath = fdPath + '' + fdNumber;
      console.info('open fd success fd is' + fdPath);
    , (err) => 
      console.info('open fd failed err is' + err);
    ).catch((err) => 
      console.info('open fd failed err is' + err);
    );
    // 调用createVideoPlayer接口返回videoPlayer实例对象
    await media.createVideoPlayer().then((video) => 
      if (typeof (video) != 'undefined') 
        console.info('createVideoPlayer success!');
        videoPlayer = video;
       else 
        console.info('createVideoPlayer fail!');
      
    , this.failureCallback).catch(this.catchCallback);
    // 设置播放源
    videoPlayer.url = fdPath;

    // 设置surfaceID用于显示视频画面
    await videoPlayer.setDisplaySurface(surfaceID).then(() => 
      console.info('setDisplaySurface success');
    , this.failureCallback).catch(this.catchCallback);

    // 调用prepare完成播放前准备工作
    await videoPlayer.prepare().then(() => 
      console.info('prepare success');
    , this.failureCallback).catch(this.catchCallback);

    // 调用play接口正式开始播放
    await videoPlayer.play().then(() => 
      console.info('play success');
    , this.failureCallback).catch(this.catchCallback);

    // 重置播放配置
    await videoPlayer.reset().then(() => 
      console.info('reset success');
    , this.failureCallback).catch(this.catchCallback);

    // 获取下一个视频fd地址
    fdPath = 'fd://'
    await fileIO.open(nextPath).then((fdNumber) => 
      fdPath = fdPath + '' + fdNumber;
      console.info('open fd success fd is' + fdPath);
    , (err) => 
      console.info('open fd failed err is' + err);
    ).catch((err) => 
      console.info('open fd failed err is' + err);
    );
    // 设置第二个视频播放源
    videoPlayer.url = fdPath;

    // 调用prepare完成播放前准备工作
    await videoPlayer.prepare().then(() => 
      console.info('prepare success');
    , this.failureCallback).catch(this.catchCallback);

    // 调用play接口正式开始播放
    await videoPlayer.play().then(() => 
      console.info('play success');
    , this.failureCallback).catch(this.catchCallback);

    // 释放播放资源
    await videoPlayer.release().then(() => 
      console.info('release success');
    , this.failureCallback).catch(this.catchCallback);

    // 相关对象置undefined
    videoPlayer = undefined;
    surfaceID = undefined;
  

(4)、单个视频循环场景:

import media from '@ohos.multimedia.media'
import fileIO from '@ohos.fileio'
export class VideoPlayerDemo 
  // 函数调用发生错误时用于上报错误信息
  failureCallback(error) 
    console.info(`error happened,error Name is $error.name`);
    console.info(`error happened,error Code is $error.code`);
    console.info(`error happened,error Message is $error.message`);
  

  // 当函数调用发生异常时用于上报错误信息
  catchCallback(error) 
    console.info(`catch error happened,error Name is $error.name`);
    console.info(`catch error happened,error Code is $error.code`);
    console.info(`catch error happened,error Message is $error.message`);
  

  // 用于打印视频轨道信息
  printfDescription(obj) 
    for (let item in obj) 
      let property = obj[item];
      console.info('key is ' + item);
      console.info('value is ' + property);
    
  

  async videoPlayerDemo() 
    let videoPlayer = undefined;
    let surfaceID = 'test' // surfaceID用于播放画面显示,具体的值需要通过Xcomponent接口获取,相关文档链接:
    let fdPath = 'fd://'
    // path路径的码流可通过"hdc file send D:\\xxx\\H264_AAC.mp4 /data/app/el1/bundle/public/ohos.acts.multimedia.video.videoplayer/ohos.acts.multimedia.video.videoplayer/assets/entry/resources/rawfile" 命令,将其推送到设备上
    let path = '/data/app/el1/bundle/public/ohos.acts.multimedia.video.videoplayer/ohos.acts.multimedia.video.videoplayer/assets/entry/resources/rawfile/H264_AAC.mp4';
    await fileIO.open(path).then((fdNumber) => 
      fdPath = fdPath + '' + fdNumber;
      console.info('open fd success fd is' + fdPath);
    , (err) => 
      console.info('open fd failed err is' + err);
    ).catch((err) => 
      console.info('open fd failed err is' + err);
    );
    // 调用createVideoPlayer接口返回videoPlayer实例对象
    await media.createVideoPlayer().then((video) => 
      if (typeof (video) != 'undefined') 
        console.info('createVideoPlayer success!');
        videoPlayer = video;
       else 
        console.info('createVideoPlayer fail!');
      
    , this.failureCallback).catch(this.catchCallback);
    // 设置播放源
    videoPlayer.url = fdPath;

    // 设置surfaceID用于显示视频画面
    await videoPlayer.setDisplaySurface(surfaceID).then(() => 
      console.info('setDisplaySurface success');
    , this.failureCallback).catch(this.catchCallback);

    // 调用prepare完成播放前准备工作
    await videoPlayer.prepare().then(() => 
      console.info('prepare success');
    , this.failureCallback).catch(this.catchCallback);
    // 设置循环播放属性
    videoPlayer.loop = true;
    // 调用play接口正式开始循环播放
    await videoPlayer.play().then(() => 
      console.info('play success, loop value is ' + videoPlayer.loop);
    , this.failureCallback).catch(this.catchCallback);
  

视频播放相关实例:

        针对视频播放开发,有以下相关实例可供参考:

openharmony视频开发(代码片段)

1.简介    OpenHarmony视频播放的主要工作是将视频数据转码并输出到设备进行播放,同时管理播放任务,包括开始播放、暂停播放、停止播放、资源释放、音量设置、跳转播放位置、设置倍数、获取轨道信息等功能控制... 查看详情

openharmony3.2beta多媒体系列——音视频播放框架(代码片段)

作者:巴延兴一、简介媒体子系统为开发者提供一套接口,方便开发者使用系统的媒体资源,主要包含音视频开发、相机开发、流媒体开发等模块。每个模块都提供给上层应用对应的接口,本文会对音视频开发中的音视频播放框... 查看详情

openharmony媒体子系统详解(代码片段)

1、OpenHarmony媒体子系统     Openharmony媒体子系统为开发者提供一套简单且易于理解的接口,使得开发者能够方便接入系统并使用系统的媒体资源。2、OpenHarmony媒体子系统常用功能   Openharmony媒体子系统包含了音视频、相... 查看详情

openharmony视频录制开发(代码片段)

1、OpenHarmony视频录制开发简介    视频录制的主要工作是捕获音视频信号,完成音视频编码并保存到文件中,帮助开发者轻松实现音视频录制功能,包括开始录制、暂停录制、恢复录制、停止录制、释放资源等功能... 查看详情

#打卡不停更#-openharmony/docs开发入门(代码片段)

作者:朱子道杨成前言不管是作为软件开发的爱好者还是已经从事软件开发这个行业的从业者,对于接触一种全新的系统OpenHarmony。学习OpenHarmony,需要清楚OpenHarmony这个系统是什么,能干什么,今日分享从设备开发和应用开发两... 查看详情

openharmony开发环境搭建(代码片段)

开发环境:开发系统:Ubuntu20.04开发板:Pegasus物联网开发板MCU:Hi3861OpenHarmony版本:3.0.1-LTS本文将介绍如何搭建OpenHarmony开发环境,OpenHarmony主要在Linux平台上开发,因此需要使用Linux环境开发,要想... 查看详情

openharmony相机开发(代码片段)

1、OpenHarmony相机开发简介         OpenHarmony相机模块支持相机业务的开发,开发者可以通过已开放的接口实现相机硬件的访问、操作和新功能开发,最常见的操作如:预览、拍照和录像等。开发者也可以通过合适... 查看详情

openharmony音频开发(代码片段)

1、OpenHarmony音频开发简介        音频播放开发的主要工作是将音频数据转码为可听见的音频模拟信号,并通过输出设备进行播放,同时对播放任务进行管理,包括开始播放、暂停播放、停止播放、释放资源、设... 查看详情

openharmony音频录制开发(代码片段)

1、OpenHarmony音频录制开发简介        音频录制的主要工作是捕获音频信号,完成音频编码并保存到文件中,帮助开发者轻松实现音频录制功能。该模块允许调用者指定音频录制的采样率、声道数、编码格式、封装格... 查看详情

openharmony应用开发实例(代码片段)

开发环境:开发系统:Ubuntu20.04开发板:Pegasus物联网开发板MCU:Hi3861OpenHarmony版本:3.0.1-LTS4.1新建工程及配置1.新建工程及源码新建目录$mkdirhello在applications/sample/myapp中新建src目录以及myapp.c文件,代码如下... 查看详情

#dayu200#openharmony视频播放器(代码片段)

作者:徐建国Video由于使用本地视频文件会影响App的包大小,所以通常我们的视频文件来源于网络地址,需要在config或者module.json对应的"abilities"中添加网络使用权限ohos.permission.INTERNET。"abilities":["permissi... 查看详情

#dayu200#openharmony视频播放器(代码片段)

作者:徐建国Video由于使用本地视频文件会影响App的包大小,所以通常我们的视频文件来源于网络地址,需要在config或者module.json对应的"abilities"中添加网络使用权限ohos.permission.INTERNET。"abilities":["permissi... 查看详情

openharmony源码编译与下载(代码片段)

开发环境:开发系统:Ubuntu20.04开发板:Pegasus物联网开发板MCU:Hi3861OpenHarmony版本:3.0.1-LTS3.1OpenHarmony源码编译Pegasus物联网开发板基于华为海思Hi3861芯片,对应的产品名字是wifiiot_hispark_pegasus。接下来编译wi... 查看详情

openharmony源码编译与下载(代码片段)

开发环境:开发系统:Ubuntu20.04开发板:Pegasus物联网开发板MCU:Hi3861OpenHarmony版本:3.0.1-LTS3.1OpenHarmony源码编译Pegasus物联网开发板基于华为海思Hi3861芯片,对应的产品名字是wifiiot_hispark_pegasus。接下来编译wi... 查看详情

openharmony数据转码应用开发实战(下)(代码片段)

背景对于刚入门OpenHarmony开发的小伙伴来说,如果有一个合适的实战项目来练手,对自身的技术能力提升是非常有帮助的,本文将以一个小项目——数据转码应用,来讲解应用开发全流程。在《OpenHarmony数据转码应用开发实战(... 查看详情

openharmony-基于arkui(ts)开发颜色选择器(代码片段)

作者:梁青松项目介绍本项目基于OpenHarmony的ArkUI框架:TS扩展的声明式开发范式,关于语法和概念直接看官网官方文档地址:基于TS扩展的声明式开发范式,因为OpenHarmony的API相对于HarmonyOS的API,功能上比较完善和成熟的,有些... 查看详情

#打卡不停更#openharmony-应用开发入门指南(代码片段)

作者:余香鑫前言了解OpenHarmony能够开发一些简单的OpenHarmony应用一、了解OpenHarmonyOpenHarmony是由开放原子开源基金会(OpenAtomFoundation)孵化及运营的开源项目,目标是面向全场景、全连接、全智能时代,搭建一个智能终端设备操作系统... 查看详情

openharmony游戏开发探索之军棋翻翻棋实现(代码片段)

openharmony游戏开发探索之军棋翻翻棋实现一,引言大家也经常看到市面上有斗地主,麻将,飞行棋等不是很复杂的棋类游戏;然后作为没有开发过游戏的我,在思考一款游戏是如何开发的?于是就想在openharmony上尝试一下。最近... 查看详情