鸿蒙5.0&next开发【视频播放开发】媒体开发

[复制链接]
发表于 2025-4-30 16:10:05 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
概述

本文适用于视频播放类应用的开发,针对市场上主流视频播放类应用的常见场景,介绍了如何基于HarmonyOS能力快速实现视频播放应用。
从用户交互和音频流状态变更两个维度,指导开发者基于HarmonyOS提供的媒体和ArkUI等能力,实现视频前后台播放控制、播放形态切换、音频焦点切换、播放装备切换等场景,可以为视频播放应用提供机动的交互体验和良好的观看效果。
场景分析

    场景名称   子场景名称   描述   实现方案         与用户交互   [播放进度控制]   进度条控制。   使用[Slider组件]实现进度条,在其onChange回调中触发进度调节。       手势调节播放进度。   通过给组件[绑定手势辨认],来实现手势调节播放进度。             显示进度条弹窗。   给进度条添加[Popup弹窗]。             [播放形态切换]   横竖屏切换。   基于[窗口能力]实现全屏播放。          悬浮窗播放。   [应用布局适配聪明多窗]。             [播控中心控制视频状态]   应用相应播控中心关照,向播控中心同步视频信息状态。   [监听AVSession播放状态事件]。          [视频后台播放]   应用至于后台时可以继续播放。   基于[AVSession Kit]和[Background Tasks Kit]申请长时任务。          [滑动调节音量及亮度]   视频全屏播放时,可以滑动屏幕调节音量及亮度。   使用[AVVolumePanel组件]控制音量,使用[Slider组件]及[setWindowBrightness]方法控制亮度。          音频流状态变更   [多音频并发打断]   视频应用被其他应用的音频打断做出对应的举动。   [AVPlayer监听音频打断事件]。       [播放装备切换]   视频应用毗连的播放装备状态发生变更时做出对应的举动。   [AVPlayer监听装备音频流输出变革]。      与用户交互

播放进度控制

进度条控制
进度条作为视频应用的一个根本能力,可以通过点击或拖动进度条来调节视频播放进度。采用[Slider组件]实现进度条功能,根据Slider组件属性设置进度条样式,并在其onChange()事件中触发视频播放器AVPlayer的seek()方法,实现视频进度的控制。
  1. Slider({
  2.   value: this.isSliderGesture ? this.panEndTime : this.avPlayerController.currentTime,
  3.   step: 0.1,
  4.   min: 0,
  5.   max: this.avPlayerController.durationTime,
  6.   style: this.sliderStyle
  7. })
  8.   // ...
  9.   .trackColor($r('app.color.white_opacity_1_color')) // 滑轨背景颜色
  10.   .showSteps(false) // 是否显示步长刻度
  11.   .blockSize({ width: this.blockSize, height: this.blockSize }) // 滑块大小
  12.   .blockColor($r('sys.color.background_primary')) // 滑块颜色
  13.   .trackThickness(this.trackThicknessSize) // 滑轨粗细
  14.   .trackBorderRadius(2) // 底板圆角半径
  15.   .selectedBorderRadius(2) // 已滑动部分圆角半径
  16.   // ...
  17.   .onChange((value: number, mode: SliderChangeMode) => {
  18.     this.sliderOnchange(value, mode); // 进度条变化接口
  19.   })
  20. sliderOnchange(seconds: number, mode: SliderChangeMode) {
  21.   let seekTime: number = seconds * this.avPlayerController.duration / this.avPlayerController.durationTime;
  22.   this.currentStringTime = secondToTime(Math.floor(seekTime / 1000));
  23.   this.avPlayerController.setCurrentStringTime(this.currentStringTime);
  24.   switch (mode) {
  25.     case SliderChangeMode.Begin:
  26.       break;
  27.     case SliderChangeMode.Click:
  28.       break;
  29.     case SliderChangeMode.Moving:
  30.       // ...
  31.       break;
  32.     case SliderChangeMode.End:
  33.       this.avPlayerController.seek(seekTime); // 调用AVPlayer的seek方法控制播放进度
  34.       // ...
  35.       break;
  36.     default:
  37.       break;
  38.   }
  39. }
复制代码
手势调节播放进度
通常视频播放应用还可以支持手势滑动来调节播放的进度,可以给组件绑定手势辨认,来实现在视频界面左右滑动调节视频播放进度的能力,手势类型选择[PanGesture](平移手势)。

  • onActionStart()阶段使用本地变量纪录当前视频播放的位置,并更新进度条状态变量,重新渲染UI界面;
  • onActionUpdate()阶段根据滑动的隔断,盘算滑动后视频应跳转的播放位置,并渲染UI界面进度条动效;
  • onActionEnd()阶段将终极盘算出的播放位置传给AVPlayer控制器,调用AVPlayer的seek()方法让视频跳转到指定播放位置,并更新进度条状态变量,重新渲染UI界面。
  1. build() {
  2.   Stack({ alignContent: Alignment.BottomEnd }) {
  3.     // ...
  4.     XComponent({
  5.       id: 'XComponent',
  6.       type: XComponentType.SURFACE,
  7.       controller: this.xComponentController
  8.     })
  9.     // ...
  10.   }
  11.    // ...
  12.   .gesture(
  13.     PanGesture({ direction: PanDirection.Horizontal })
  14.       .onActionStart((event: GestureEvent) => {
  15.         this.isSliderGesture = true;
  16.         this.panStartX = event.offsetX;
  17.         this.panStartTime = this.avPlayerController.currentTime;
  18.         this.sliderOnchange(this.panStartTime, SliderChangeMode.Begin);
  19.       })
  20.       .onActionUpdate((event: GestureEvent) => {
  21.         this.isSliderGesture = true;
  22.         let panTime =
  23.           this.panStartTime +
  24.             (this.panStartX + event.offsetX) / this.slideWidth * this.avPlayerController.durationTime;
  25.         this.panEndTime = Math.min(Math.max(0, panTime), this.avPlayerController.durationTime);
  26.         this.sliderOnchange(this.panEndTime, SliderChangeMode.Moving);
  27.       })
  28.       .onActionEnd(() => {
  29.         this.sliderOnchange(this.panEndTime, SliderChangeMode.End);
  30.         this.isSliderGesture = false;
  31.       })
  32.   )
  33. }
复制代码
显示进度条弹窗
在正常欣赏视频的过程中,应用会记任命户的欣赏历史,当再次切换到原视频时,根据历史数据在进度条上以弹窗的情势显示相干信息。并且让弹窗跟随滑块位置移动,弹窗保留1秒后消散。同时历史数据的保留跟随视频组件的生命周期存亡。
由于Slider自带的showTips无法对弹窗样式进行自界说,只支持圆形气泡,且无法自界说控制弹窗的显示时长和出现机会。所以我们通过创建一个和Slider滑块巨细一致的透明Stack,并盘算滑块在屏幕中的位置,将盘算的位置数据同步设置给Stack,并给Stack绑定Popup弹窗跟随Slider滑块运动。

关键代码:
通过给Slider组件绑定地区变革事件onAreaChange(),盘算滑动位置信息。
  1. // Slider进度条
  2. Slider({
  3.   value: this.isSliderGesture ? this.panEndTime : this.avPlayerController.currentTime,
  4.   step: 0.1,
  5.   min: 0,
  6.   max: this.avPlayerController.durationTime,
  7.   style: this.sliderStyle
  8. })
  9.   // ...
  10.   .blockSize({ width: this.blockSize, height: this.blockSize })
  11.   // 计算滑块位置
  12.   .onAreaChange(() => {
  13.     let videoSlider: componentUtils.ComponentInfo = componentUtils.getRectangleById('video_slider')
  14.     this.slideWidth = px2vp(videoSlider.size.width);
  15.     // 计算offsetY:Slider滑块位置的纵坐标
  16.     this.offsetY = px2vp(videoSlider.localOffset.y);
  17.     this.beginX = px2vp(videoSlider.localOffset.x);
  18.   })
  19.   // 进度条变化时最终会调用avPlayer.seek()接口
  20.   .onChange((value: number, mode: SliderChangeMode) => {
  21.     this.sliderOnchange(value, mode);// 进度条变化时会调用avPlayer.seek()接口
  22.   })
复制代码
Stack透明块巨细、位置设置以及给Stack绑定Popup弹窗。
  1. // 设置和Slider大小一样的透明stack块
  2. Stack() {
  3. }
  4. .backgroundColor($r('sys.color.background_primary'))
  5. .width(this.b
复制代码
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表