【高心星出品】

AVPlayer播放视频

场景描述

通过AVPlayer实现核心视频播放控制能力,包括视频资源加载、播放、暂停、停止及退出等操作。

实现原理

本开发指导将介绍如何使用AVPlayer开发视频播放功能,以完整地播放一个视频作为示例,实现端到端播放原始媒体资源。

播放的全流程包含:创建AVPlayer,设置播放资源和窗口,设置播放参数(音量/倍速/缩放模式),播放控制(播放/暂停/跳转/停止),重置,销毁资源。在进行应用开发的过程中,开发者可以通过AVPlayer的state属性主动获取当前状态或使用on(‘stateChange’)方法监听状态变化。如果应用在视频播放器处于错误状态时执行操作,系统可能会抛出异常或生成其他未定义的行为。

开发步骤

  1. 创建实例:调用createAVPlayer()接口创建AVPlayer实例,初始化进入idle状态。
  2. 设置视频资源:设置AVPlayer实例的url或者fdSrc属性值,进入initialized状态。
  3. 准备播放:调用prepare()接口,进入prepared状态。
  4. 播放:调用play()接口,进入playing状态。
  5. 暂停:调用pause()接口,进入paused状态。
  6. 停止:调用stop()接口,进入stopped状态。
  7. 销毁实例:调用release()接口销毁实例,AVPlayer进入released状态,退出播放。

跳转播放

场景描述

进度条是视频应用的一个基础能力,可以通过点击或拖动进度条精准跳转到指定时间进行播放。

2B29B5ED0AC7B529.gif

实现原理

基于Slider组件和视频播放器AVPlayer的seek()方法实现跳转播放。

开发步骤

采用Slider组件实现进度条功能,根据Silder组件属性设置进度条样式,并在其onChange()事件中触发视频播放器AVPlayer的seek()方法跳转到指定播放位置,实现视频进度的控制。

/**
 * Progress slider
 */
Slider({
  value: this.currentTime,
  min: 0,
  max: this.durationTime,
  style: SliderStyle.OutSet
})
  .id('Slider')
  .blockColor(Color.White)
  .trackColor(Color.Gray)
  .selectedColor($r('app.color.slider_selected'))
  .showTips(false)
  .onChange((value: number, mode: SliderChangeMode) => {
    if (mode === SliderChangeMode.Begin) {
      this.isSwiping = true;
      this.avPlayerController.videoPause();
    }
    this.avPlayerController.videoSeek(value);
    this.currentTime = value;
    if (mode === SliderChangeMode.End) {
      this.isSwiping = false;
      this.flag = true;
      this.avPlayerController.videoPlay();
    }
  })

代码逻辑走读:

  1. 初始化滑块
    • 使用 Slider组件创建一个滑块,设置其初始值 value为当前时间 this.currentTime
    • 定义滑块的最小值 min为 0,最大值 max为总时长 this.durationTime
    • 设置滑块的样式为 SliderStyle.OutSet
  2. 设置滑块属性
    • 使用 id('Slider')为滑块设置唯一标识符。
    • 设置滑块的块颜色为白色 Color.White
    • 设置滑块的轨道颜色为灰色 Color.Gray
    • 设置滑块选中部分的颜色为应用中定义的颜色 $r('app.color.slider_selected')
    • 隐藏滑块的提示信息 showTips(false)
  3. 滑块事件处理
    • 使用 onChange方法监听滑块值的变化,并根据变化模式 mode执行不同的操作。
    • 当模式为SliderChangeMode.Begin时,表示用户开始拖动滑块:
      • this.isSwiping设置为 true,表示正在滑动。
      • 调用 this.avPlayerController.videoPause()暂停视频播放。
    • 调用 this.avPlayerController.videoSeek(value)将视频跳转到当前滑块所代表的时间点。
    • 更新当前时间 this.currentTime为滑块的当前值 value
    • 当模式为SliderChangeMode.End时,表示用户结束拖动滑块:
      • this.isSwiping设置为 false,表示滑动结束。
      • this.flag设置为 true,可能用于标记某种状态。
      • 调用 this.avPlayerController.videoPlay()恢复视频播放。

静音播放

场景描述

通过界面按钮快捷切换视频播放静音状态,实现一键开启或关闭静音,提升媒体播放的交互便捷性。

在这里插入图片描述

实现原理

通过视频播放器AVPlayer的setMediaMuted()方法,实现控制视频静音状态。

开发步骤

  1. 在底部操作栏添加Button组件,按钮显示为icon图标;根据Button组件属性设置按钮样式,并在其onClick()事件中触发视频管理接口AvPlayerController.ets文件中封装的videoMuted()方法。

    /**
     * Video Muted Button
     */
    Button() {
      Image(this.isMuted ? $r('app.media.ic_video_speaker_slash') : $r('app.media.ic_video_speaker'))
        .width($r('app.float.size_30'))
        .height($r('app.float.size_30'))
    }
    .type(ButtonType.Normal)
    .width($r('app.float.size_30'))
    .height($r('app.float.size_30'))
    .borderRadius($r('app.float.size_20'))
    .backgroundColor('rgba(0, 0, 0, 0)')
    .margin({ left: $r('app.float.size_5') })
    .fontColor(Color.White)
    .onClick(() => {
      this.isMuted = !this.isMuted;
      this.avPlayerController.videoMuted(this.isMuted)
    })
    

    代码逻辑走读:

    1. 定义了一个按钮组件,按钮内部包含一个图像组件。
    2. 图像组件的图标根据this.isMuted的值动态切换,如果视频静音则显示未静音图标,否则显示静音图标。
    3. 图像组件的宽度和高度设置为$r('app.float.size_30')
    4. 按钮组件的宽度、高度、圆角、背景色、左边距、字体颜色等样式属性也进行了设置。
    5. 为按钮添加了点击事件处理函数,点击时会切换this.isMuted的值,并调用this.avPlayerController.videoMuted(this.isMuted)方法来更新视频的静音状态。
  2. videoMuted()方法中调用了视频播放器AVPlayer的setMediaMuted()方法,实现控制视频静音状态,其中第一个参数mediaType选择媒体类型为MEDIA_TYPE_AUD表示音频,第二个参数是静音开关。

    /**
     * Video muted
     * @param isMuted
     * @returns
     */
    async videoMuted(isMuted: boolean): Promise<void> {
      if (this.avPlayer) {
        try {
          this.isMuted = isMuted;
          await this.avPlayer!.setMediaMuted(media.MediaType.MEDIA_TYPE_AUD, isMuted)
        } catch (err) {
          hilog.error(CommonConstants.LOG_DOMAIN, TAG,
            `videoMuted failed, code is ${err.code}, message is ${err.message}`);
        }
      }
    }
    

    代码逻辑走读:

    1. 函数定义与参数接收
      • 定义了一个名为 videoMuted的异步函数,接收一个布尔类型的参数 isMuted
    2. 条件检查
      • 检查 this.avPlayer是否存在。如果存在,则继续执行静音操作;否则,函数直接返回。
    3. 设置静音状态
      • 将传入的 isMuted参数赋值给 this.isMuted,用于记录当前的静音状态。
    4. 调用静音方法
      • 使用 await调用 this.avPlayer.setMediaMuted方法,传入媒体类型 MEDIA_TYPE_AUD和静音状态 isMuted
    5. 错误处理
      • 如果在设置静音过程中发生错误,捕获异常并使用 hilog.error记录错误信息,包括错误代码和错误消息。

循环播放

场景描述

本功能可以用于在视频播放结束后自动将播放器重置至初始状态,使用户能够立即重新开始播放视频内容,实现无缝循环观看体验。

开发步骤

在视频prepared状态下,设置视频播放器AVPlayer的loop属性值为true,实现视频循环播放。

// Callback function for state machine changes
this.avPlayer.on('stateChange', async (state) => {
  if (!this.avPlayer) {
    return;
  }
  switch (state) {
    // ...
    case 'prepared': // This state machine is reported after the prepare interface is successfully invoked.
      this.isReady = true;
      this.avPlayer.loop = true
      // ...
      break;
    // ...
  }
});

代码逻辑走读:

  1. 监听状态变化事件:通过this.avPlayer.on('stateChange', async (state) => {...})监听播放器状态变化事件。
  2. 状态检查:在回调函数内部,首先检查this.avPlayer是否存在,如果不存在则直接返回,不执行后续逻辑。
  3. 状态判断:使用switch语句判断当前状态state
  4. 状态处理:
    • 当状态为'prepared'时,设置this.isReadytrue,表示播放器已准备好播放。
    • 设置播放器的loop属性为true,启用循环播放功能。
Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐