基础功能

本文为您介绍如何创建鸿蒙HarmonyOS NEXT播放器实例并提供设置音量、设置拖拽播放、监听播放状态、设置循环播放、设置倍速播放等基础播放功能的使用示例。

创建播放器

本节介绍如何用简单的方式通过鸿蒙HarmonyOS NEXT播放器SDK播放视频,按照播放方式的不同可以分为手动播放和自动播放。

  1. 创建播放器。

    // 推荐下载Demo工程,参阅ReadMe.md了解最佳实践方式,帮助您快速集成。
    
    // 从SDK har包中import播放器相关定义
    import { AliPlayerFactory, AliPlayer } from 'premierlibrary';
    
    // 创建播放器实例
    const player: AliPlayer = AliPlayerFactory.createAliPlayer(getContext(), traceId);
    
    // 创建列表播放器(滑动播放场景)
    const listPlayer: AliListPlayer = AliPlayerFactory.createAliListPlayer(getContext(), traceId);
    
    // getContext()为鸿蒙系统函数; traceId由业务指定独特的会话ID,可以为空字符串''或null
  2. 设置播放器回调监听。

    // 推荐下载Demo工程,参阅ReadMe.md了解最佳实践方式,帮助您快速集成。
    
    // 按需 引入播放器事件回调类型定义
    import { OnPreparedListener, OnCompletionListener, OnAudioInterruptEventListener,OnErrorListener,OnInfoListener,OnLoadingStatusListener, AudioStatus } from 'premierlibrary/src/main/ets/com/aliyun/player/IPlayer';
    
    // 播放器实例
    const player: AliPlayer = AliPlayerFactory.createAliPlayer(getContext(), traceId);
    
    // 定义回调监听
    const mPreparedEventHandler: OnPreparedListener = { // prepare完成
      onPrepared: () => {
        console.log("prepared");
      }
    };
    const mCompletionEventHandler: OnCompletionListener = { // 播放完成
      onCompletion: () => {
        console.log("play complete");
      }
    }
    const mOnAudioInterruptListener: OnAudioInterruptEventListener = { // 音频打断
      onAudioInterruptEvent: (audioStatus: AudioStatus) => {
        if (player) {
          console.log("[HOS DEMO] [AUDIO INTERRUPT]: " + audioStatus);
          let statusInfo: string = "";
          switch (audioStatus) {
            case AudioStatus.AUDIO_STATUS_DEFAULT:
              statusInfo = "AUDIO_STATUS_DEFAULT"
              break;
            case AudioStatus.AUDIO_STATUS_RESUME:
              statusInfo = "AUDIO_STATUS_RESUME"
              player.start(); // 继续播放
              break;
            case AudioStatus.AUDIO_STATUS_PAUSE:
              statusInfo = "AUDIO_STATUS_PAUSE"
              player.pause(); // 暂停播放
              break;
            case AudioStatus.AUDIO_STATUS_STOP:
              statusInfo = "AUDIO_STATUS_STOP"
              player.stop(); // 停止播放
              break;
            case AudioStatus.AUDIO_STATUS_DUCK:
              statusInfo = "AUDIO_STATUS_DUCK"
              break;
            case AudioStatus.AUDIO_STATUS_UNDUCK:
              statusInfo = "AUDIO_STATUS_UNDUCK"
              break;
            default:
              break;
          }
          showToast("CALLBACK: onAudioInterrupt " + statusInfo);
        }
      }
    }
    const mOnErrorEventListener: OnErrorListener = { // 错误回调
      onError:(errorInfo) => {
        let errorCode:PlayerErrorCode = errorInfo.getCode(); //错误码
        let errorMsg:string = errorInfo.getMsg(); //错误描述
        //errorExtra为额外错误信息,形式为json字符串,示例如下,需要注意ModuleCode并不完全等同于errorCode
        // { "Url": "xxx",
     		//	"Module": "NetWork",
      	//	"ModuleCode": "-377",
     		//  "ModuleMessage": "Redirect to a url that is not a media"}
        let errorExtra:string = errorInfo.getExtra();
        
        //出错后需要停止掉播放器。
        player.stop();
      }
    }
    const mOnVideoInfo: OnInfoListener = { // 视频信息回调
      //播放器中的一些信息,包括:当前进度、缓存位置等等。
      onInfo: (bean: InfoBean) => {
        //当前进度:InfoCode.CurrentPosition
        //当前缓存位置:InfoCode.BufferedPosition
        if (bean.getCode() === InfoCode.CurrentPosition) {
          this.videoProgress = bean.getExtraValue() / this.mVideoDuration * 100;
          this.mDuration = CommonUtils.getDurationString(this.mVideoDuration, bean.getExtraValue());
        } else if (bean.getCode() === InfoCode.BufferedPosition) {
          this.buffer = CommonUtils.secondToTime(Math.floor(bean.getExtraValue() / 1000));
          this.bufferedProgress = bean.getExtraValue() / this.mVideoDuration * 100;
        }
      }
    }
    const mOnLoadingProgressEventListener: OnLoadingStatusListener = { // 加载、卡顿状态下回调
      onLoadingBegin: () => {
          //开始加载。画面和声音不足以播放。
          //一般在此处显示圆形加载
      },
      onLoadingProgress: (percent: number, netSpeed: number) => {
         //加载进度。百分比和网速。
      },
      onLoadingEnd: () => {
          //结束加载。画面和声音可以播放。
          //一般在此处隐藏圆形加载。
      }
    }
    
    // 将监听注册到播放器实例中
    player.setOnPreparedListener(mPreparedEventHandler);
    player.setOnCompletionListener(mCompletionEventHandler);
    player.setOnAudioInterruptEventListener(mOnAudioInterruptListener);
    player.setOnErrorListener(mOnErrorEventListener);
    player.setOnInfoListener(mOnVideoInfo);
    player.setOnLoadingStatusListener(mOnLoadingProgressEventListener);
  3. 设置播放方式。

    • 鸿蒙HarmonyOS NEXT版播放器SDK支持4种点播播放方式,包括:UrlSource播放、VidAuth播放(视频点播用户推荐使用)、VidSts播放、加密播放。

    • 鸿蒙HarmonyOS NEXT版播放器SDK仅支持1种直播播放方式,UrlSource播放。

    说明
    • UrlSource是直接通过URL播放,VidSts,VidAuth是通过Vid进行播放。

    • 接入地域Region的设置,请参见点播地域标识

    点播视频播放

    点播UrlSource播放

    使用点播UrlSource播放方式播放点播视频,需要将播放器的setUrl属性设置为播放地址。

    • 阿里云视频点播服务中的播放地址:可以调用GetPlayInfo接口获取。建议您集成点播服务端SDK来获取音视频播放地址,免去自签名的麻烦。调用接口获取音视频播放地址的示例请参见开发者门户

    • 本地视频地址:请确保有访问权限,可以通过系统API获取到可访问的本地视频文件完整路径,例如:/sdcard/xxx/xxx/xxx.mp4content://xxx/xxx/xx.mp4

    import { AliPlayerFactory, AliPlayer } from 'premierlibrary';
    import { UrlSource } from 'premierlibrary/src/main/ets/com/aliyun/player/source/UrlSource';
    @Preview
    @Component
    export struct MyPlayerComponent {
      private videoUrl: string = 'http播放地址';
      private aliPlayer: AliPlayer = AliPlayerFactory.createAliPlayer(getContext(), '');
      playByUrl() {
        let urlSource: UrlSource = new UrlSource();
        urlSource.setUri(this.videoUrl);// 必选参数,播放地址,可以是第三方点播地址,或阿里云视频点播服务中的播放地址,也可以是本地视频地址。
        this.aliPlayer.setUrlDataSource(urlSource);
      }
    }

    点播VidAuth播放(推荐)

    使用VidAuth播放方式播放点播视频,需要将播放器的vid属性设置为音视频ID,将playauth属性设置为音视频播放凭证。

    • 音视频ID:可以在音视频上传完成后通过控制台(路径:媒资库>音/视频。)或服务端接口(SearchMedia)获取。

    • 音视频播放凭证:可以调用GetVideoPlayAuth接口获取。建议您集成点播服务端SDK来获取音视频播放凭证,免去自签名的麻烦。调用接口获取音视频播放凭证的示例请参见开发者门户

    推荐视频点播用户采用此播放方式。相比STS播放方式,PlayAuth播放方式在易用性和安全性上更有优势,对比详情请参见凭证方式与STS方式对比

    import { AliPlayerFactory, AliPlayer, VidAuth } from 'premierlibrary';
    interface IAuthInfo { videoId: string, playAuth: string }
    @Preview
    @Component
    export struct MyPlayerComponent {
      private authInfo: IAuthInfo = {
        videoId: '点播vid',
        playAuth: 'playauth',
      };
      private aliPlayer: AliPlayer = AliPlayerFactory.createAliPlayer(getContext(), '');
      playByVidAndAuth() {
        const vidAuthSource: VidAuth = new VidAuth();
        vidAuthSource.setVid(this.authInfo.videoId);// 必选参数,视频ID(VideoId)。
        vidAuthSource.setPlayAuth(this.authInfo.playAuth);// 必选参数,播放凭证,需要调用点播服务的GetVideoPlayAuth接口生成。
        this.aliPlayer.setVidAuthDataSource(vidAuthSource);
      }
    }

    点播VidSts播放

    使用点播VidSts播放方式播放点播视频是指用STS临时凭证而非点播音视频播放凭证播放。STS安全令牌和STS临时AK对(AccessKeyId和AccessKeySecret)需要提前获取,获取方式请参见使用STS临时授权方案上传视频

    import { AliPlayerFactory, AliPlayer, VidSts } from 'premierlibrary';
    interface ISTSInfo { videoId: string, accessKeyId: string, securityToken: string, accessKeySecret: string, region: string }
    @Preview
    @Component
    export struct MyPlayerComponent {
      private stsInfo: ISTSInfo = {
        videoId: '点播vid',
        accessKeyId: 'STS-accessKeyId',
        securityToken: 'STS-token',
        accessKeySecret: 'STS-accessKeySecret',
        region: 'regionId'
      };
      private aliPlayer: AliPlayer = AliPlayerFactory.createAliPlayer(getContext(), '');
      playByVidAndSTS() {
        const vidStsSource: VidSts = new VidSts();
        vidStsSource.setVid(this.stsInfo.videoId);// 必选参数,视频ID(VideoId)。
        vidStsSource.setAccessKeyId(this.stsInfo.accessKeyId);// 必选参数,STS临时AK对的访问密钥ID,需要调用STS服务的AssumeRole接口生成。
        vidStsSource.setAccessKeySecret(this.stsInfo.accessKeySecret);// 必选参数,STS临时AK对的访问密钥,需要调用STS服务的AssumeRole接口生成。
        vidStsSource.setSecurityToken(this.stsInfo.securityToken);// 必选参数,STS安全令牌,需要调用STS服务的AssumeRole接口生成。
        vidStsSource.setRegion(this.stsInfo.region);// 必选参数,点播服务的接入地域,默认为cn-shanghai。
        this.aliPlayer.setVidStsDataSource(vidStsSource);
      }
    }

    点播加密播放

    点播视频支持HLS标准加密、阿里云私有加密。加密播放请参见如何播放加密视频

    直播视频播放

    直播UrlSource播放

    使用UrlSource播放方式播放直播视频,需要将播放器的setUrl属性设置为直播拉流地址。播放地址可以是第三方直播地址或阿里云直播服务中的拉流地址。

    阿里云直播拉流地址可以通过直播控制台的地址生成器生成。详情请参见直播地址生成器

    import { AliPlayerFactory, AliPlayer } from 'premierlibrary';
    import { UrlSource } from 'premierlibrary/src/main/ets/com/aliyun/player/source/UrlSource';
    @Preview
    @Component
    export struct MyPlayerComponent {
      private videoUrl: string = '直播播放地址';
      private aliPlayer: AliPlayer = AliPlayerFactory.createAliPlayer(getContext(), '');
      playByUrl() {
        let urlSource: UrlSource = new UrlSource();
        urlSource.setUri(this.videoUrl);// 播放地址,可以是第三方直播地址,或阿里云直播服务中的拉流地址。
        this.aliPlayer.setUrlDataSource(urlSource);
      }
    }
  4. 绑定播放器与鸿蒙XComponent组件,实现视频画面渲染。

    // 推荐下载并查看Demo最佳实践中,原子接入方案
    // 以下代码为鸿蒙arkTs环境@Component组件示例
    
    /**
     * 原子接入 鸿蒙播放器SDK
     * 基于最底层鸿蒙XC能力,最简单方式集成,为客户自制开发提供高自由度
     * 三步 - 实现视频播放
     */
    
    import { AliPlayerFactory, AliPlayer } from 'premierlibrary';
    import { UrlSource } from 'premierlibrary/src/main/ets/com/aliyun/player/source/UrlSource';
    
    @Preview
    @Component
    export struct MyPlayerComponent {
    
      private videoUrl: string = 'http播放地址';
      private xComponentController = new XComponentController();
      private aliPlayer: AliPlayer = AliPlayerFactory.createAliPlayer(getContext(), '');
    
      build() {
        XComponent({
          id: '0', // unique XC id
          type: XComponentType.SURFACE,
          libraryname: 'premierlibrary',
          controller: this.xComponentController
        })
        .onLoad(async () => {
    
          // 准备URL对象
          let urlSource: UrlSource = new UrlSource();
          urlSource.setUri(this.videoUrl);
    
          // 绑定URL & XC_SurfaceId
          this.aliPlayer.setUrlDataSource(urlSource);
          this.aliPlayer.setSurfaceId('0'); // surface ID 对应 XC ID
    
          // 播放视频
          this.aliPlayer.setAutoPlay(true);
          this.aliPlayer.prepare();
        })
        .width('100%')
        .height(200)
      }
    
      aboutToDisappear(): void {
        if (this.aliPlayer) {
          this.aliPlayer.stop();
          this.aliPlayer.release();
        }
      }
    }
    重要

    XComponent需要通过libraryname: 'premierlibrary'来加载播放器SO,同时需要指定唯一的id来区分不同的XComponent,以避免视频渲染出现冲突问题。

  5. 可选:开启自动播放,默认为关闭状态。

    // player为播放器实例
    player.setAutoPlay(true);
  6. 准备播放,调用prepare()开始读取并解析数据。若开启自动播放,数据解析完成后将开始自动播放视频。

    // player为播放器实例
    player.prepare();
  7. 开始播放。通过调用start方法主动开始播放视频。

    // player为播放器实例
    player.start();

控制播放

鸿蒙HarmonyOS NEXT播放器SDK支持从指定时间点播放、开始、暂停、停止播放等操作。

开始播放

指开始播放视频,由start接口实现。示例如下:

aliyunVodPlayer.start();

从指定时间开始播放

指跳转到某个时刻进行播放,由seekTo接口实现。适用于用户拖拽进度条,或续播等需要从指定时间点开始播放的场景。示例如下:

// posotion为指定的时间,单位:毫秒。
aliyunVodPlayer.seekTo(long position);

暂停播放

指暂停播放视频,由pause接口实现。示例如下:

aliyunVodPlayer.pause();

停止播放

指停止播放视频,由stop接口实现。示例如下:

aliyunVodPlayer.stop();

设置显示模式

鸿蒙HarmonyOS NEXT播放器SDK支持填充、旋转、镜像等显示设置。

填充

支持设置宽高比适应、宽高比填充和拉伸填充这3种画面填充模式,由setScaleMode接口实现。示例如下:

// 设置宽高比适应(将按照视频宽高比等比缩小到view内部,不会有画面变形)
aliyunVodPlayer.setScaleMode(ScaleMode.SCALE_ASPECT_FIT);
// 设置宽高比填充(将按照视频宽高比等比放大,充满view,不会有画面变形)
aliyunVodPlayer.setScaleMode(ScaleMode.SCALE_ASPECT_FILL);
// 设置拉伸填充(如果视频宽高比例与view比例不一致,会导致画面变形)
aliyunVodPlayer.setScaleMode(ScaleMode.SCALE_TO_FILL);

旋转

指画面按指定角度旋转,由setRotateMode接口实现。设置后还可查询旋转角度。示例如下:

// 设置画面顺时针旋转0度
aliyunVodPlayer.setRotateMode(RotateMode.ROTATE_0);
// 设置画面顺时针旋转90度
aliyunVodPlayer.setRotateMode(RotateMode.ROTATE_90);
// 设置画面顺时针旋转180度
aliyunVodPlayer.setRotateMode(RotateMode.ROTATE_180);
// 设置画面顺时针旋转270度
aliyunVodPlayer.setRotateMode(RotateMode.ROTATE_270);
// 获取旋转角度
aliyunVodPlayer.getRotateMode();

镜像

指画面按不同镜像效果显示,支持水平镜像、垂直镜像和无镜像,由setMirrorMode接口实现。示例如下:

// 设置无镜像
aliyunVodPlayer.setMirrorMode(MirrorMode.MIRROR_MODE_NONE);
// 设置水平镜像
aliyunVodPlayer.setMirrorMode(MirrorMode.MIRROR_MODE_HORIZONTAL);
// 设置垂直镜像
aliyunVodPlayer.setMirrorMode(MirrorMode.MIRROR_MODE_VERTICAL);

获取播放信息

鸿蒙HarmonyOS NEXT播放器SDK支持获取当前的播放进度、播放时长和缓冲进度等信息。

获取当前播放进度

指获取当前的播放时刻,需要在onInfo回调中获取,由getExtraValue接口实现。示例如下:

private mOnVideoInfo: OnInfoListener = {
    //播放器中的一些信息,包括:当前进度、缓存位置等等。
    onInfo: (bean: InfoBean) => {
      if (bean.getCode() === InfoCode.CurrentPosition) {
        // extraValue为当前播放进度,单位为毫秒
        let extraValue: number = bean.getExtraValue();
      } 
    }
  }

获取播放时长

指获取视频总时长。需要在视频加载完成以后才可以获取到,可以在onPrepared事件后获取。由getDuration接口实现。示例如下:

let duration:number = mAliPlayer.getDuration();

获取缓冲进度

指获取视频当前的缓冲进度,需要在onInfo回调中获取,由getExtraValue接口实现。示例如下:

private mOnVideoInfo: OnInfoListener = {
  //播放器中的一些信息,包括:当前进度、缓存位置等等。
  onInfo: (bean: InfoBean) => {
    if (bean.getCode() === InfoCode.BufferedPosition) {
      // extraValue为当前缓冲进度,单位为毫秒
      let extraValue: number = bean.getExtraValue();
    } 
  }
}

获取实时渲染帧率、音视频码率、网络下行码率

示例如下:

// 获取当前渲染的帧率,数据类型为Float。
mAliPlayer.getOption(Option.RenderFPS);
// 获取当前播放的视频码率,数据类型为Float,单位为bps。
mAliPlayer.getOption(Option.VideoBitrate);
// 获取当前播放的音频码率,数据类型为Float,单位为bps。
mAliPlayer.getOption(Option.AudioBitrate);
// 获取当前的网络下行码率,数据类型为Float,单位为bps。
mAliPlayer.getOption(Option.DownloadBitrate);

监听播放状态

指监听播放器的状态,onStateChanged回调参数为当前播放器状态。示例如下:

/**
   * 状态回调
   */
  private mOnStatusChangedListener: OnStateChangedListener = {
    onStateChanged: (status: number) => {
        /*
          int idle = 0;
          int initalized = 1;
          int prepared = 2;
          int started = 3;
          int paused = 4;
          int stopped = 5;
          int completion = 6;
          int error = 7;
      */
    }
  }
  
  mAliPlayer.setOnStateChangedListener(this.mOnStatusChangedListener);

设置音量

设置音量包括音量调节和静音设置。

音量调节

指调节音量大小,支持0~2倍,当音量大于1时,可能出现噪音,不推荐使用。由setVolume接口实现。设置后还可获取音量信息。示例如下:

// volume的值为0~2之间的实数。
aliyunVodPlayer.setVolume(1.0f);
// 获取音量信息。
aliyunVodPlayer.getVolume();

静音设置

指将播放中的视频设置为静音状态,由setMute接口实现。示例如下:

aliyunVodPlayer.setMute(true);

倍速播放

鸿蒙HarmonyOS NEXT播放器SDK提供了倍速播放视频的功能,通过设置setSpeed方法,能够以0.5倍~5倍速去播放视频。同时保持变声不变调。示例如下:

// 设置倍速播放:支持0.5~5倍速的播放,通常按0.5的倍数来设置,例如0.5倍、1倍、1.5倍等
aliyunVodPlayer.setSpeed(1.0f);

多清晰度设置

点播Vid播放方式(VidAuth或VidSts)

如果使用Vid方式(VidAuth或VidSts)播放,无需额外设置。鸿蒙HarmonyOS NEXT播放器SDK会从点播服务获取清晰度列表。

获取清晰度

当视频加载完成后,可以获取视频的清晰度。

let mediaInfo: MediaInfo | null | undefined = player?.getMediaInfo();
let trackInfos: TrackInfo[] | undefined = mediaInfo?.getTrackInfos();
if (trackInfos) {
  for (let i: number = 0; i< trackInfos.length; i++) {
    if(trackInfos[i].getType() == TrackType.TYPE_VOD){
      //获取视频清晰度
      console.log("track vod definition is " + trackInfos[i].getVodDefinition());
    }
  }
}

切换清晰度

通过selectTrack方法切换清晰度,传递对应TrackInfo的index即可。

mAliPlayer.selectTrack(index);

清晰度切换通知

清晰度切换成功与失败回调。

private mOnTrackChange: OnTrackChangedListener = {
  //清晰度切换成功
  onChangedSuccess: (trackInfo: TrackInfo): void => {
    
  }
}
mAliPlayer.setOnTrackChangedListener(this.mOnTrackChange);

循环播放

鸿蒙HarmonyOS NEXT播放器SDK提供了循环播放视频的功能。调用setLoop开启循环播放,播放完成后,将会自动从头开始播放视频。示例如下:

aliyunVodPlayer.setLoop(true);

同时循环开始的回调将会使用onInfo中通知。示例如下:

private mOnVideoInfo: OnInfoListener = {
  //播放器中的一些信息,包括:当前进度、缓存位置等等。
  onInfo: (bean: InfoBean) => {
    if (bean.getCode() === InfoCode.LoopingStart) {
      //循环播放开始事件
    } 
  }
}