鸿蒙 HarmonyOS--视频播放Video

华为官方这边提供了两种视频播放的方式,一种是Video组件,它是已经封装好的视频播放组件,提供了一些比较基础的能力,一些比较复杂的能力建议使用AVPlayer。这篇文章介绍的是Video视频播放。

Video组件支持播放本地视频、沙箱路径视频和网络视频。本地视频放在resource里的rawfile目录下,使用的时候用$rawfile()来引用视频资源,如果是网络视频需要配置网络权限。

默认控制器

Video默认控制器支持视频的开始、暂停、进度调整、全屏显示四项基本功能,但是进度条样式是黑色的,不够美观,也不能通过点击视频区域暂停视频,如果想要更好的体验感,可以自定义控制器。

less 复制代码
@Entry
@Component
struct VideoGuide {
  private controller: VideoController | undefined;
  //视频资源
  @State videoSrc: Resource = $rawfile('waku.mp4')
  //预览图,这里我用的是网络图片
  @State previewUri: string = 'https://i1.hdslb.com/bfs/archive/b31a7e4bd8a1ffb142d0a6ace259a2efe5ac1088.jpg'
  //视频速度
  @State curRate: PlaybackSpeed = PlaybackSpeed.Speed_Forward_1_00_X
  @State showControls: boolean = true

  build() {
    Row() {
      Column() {
        Video({
          src: this.videoSrc,
          previewUri: this.previewUri,
          currentProgressRate: this.curRate,
          controller: this.controller
        })
          .objectFit(ImageFit.Contain)//设置视频适配模式
          .height(400)
          .controls(this.showControls) //是否显示进度控制条
      }
      .width('100%')
    }
    .height('100%')
  }
}

自定义控制器

使用自定义控制器需要先把默认控制器关了,然后用slider组件控制视频的样式和滑动播放效果,还增加了倍速控制。

kotlin 复制代码
@Entry
@Component
struct VideoGuide {
  controller: VideoController = new VideoController()
  //视频资源
  @State videoSrc: Resource = $rawfile('waku.mp4')
  //预览图,这里我用的是网络图片
  @State previewUri: string = 'https://i1.hdslb.com/bfs/archive/b31a7e4bd8a1ffb142d0a6ace259a2efe5ac1088.jpg'
  //视频速度
  @State curRate: PlaybackSpeed = PlaybackSpeed.Speed_Forward_1_00_X
  //当前播放时长
  @State currentTime: number = 0;
  //视频时长
  @State durationTime: number = 0;
  //播放状态
  @State isPlay: boolean = false

  //时间处理函数
  myDate(num: number) {
    let hour = Math.floor(num / 60 / 60)
    let minute = Math.floor(num / 60 % 60)
    let second = Math.floor(num % 60)
    if (num < 3600) {
      return `${minute.toString().padStart(2, '0')} : ${second.toString().padStart(2, '0')}`
    } else {
      return `${hour.toString().padStart(2, '0')} : ${minute.toString().padStart(2, '0')} : ${second.toString()
        .padStart(2, '0')}`
    }
  }

  //进度条
  @Builder
  sliderBar() {
    Row({ space: 8 }) {
      Image(this.isPlay ? $r('app.media.pause') : $r('app.media.start'))
        .width(20)

      Text(this.myDate(this.currentTime))
        .fontSize(12)

      Slider({
        value: this.currentTime,
        min: 0,
        max: this.durationTime,
      })
        .onChange((value) => {
          this.currentTime = value
          this.controller.setCurrentTime(this.currentTime)
        })//设置滑动块的大小
        .blockSize({ width: 10, height: 10 })
        .trackColor(Color.Gray)
        .selectedColor(Color.Pink)
        .layoutWeight(1)
        .height(50)

      Text(this.myDate(this.durationTime))
        .fontSize(12)

      Text('倍速')
        .fontSize(14)//倍数弹窗
        .bindMenu([
          {
            value: 'x0.75',
            action: () => {
              this.curRate = PlaybackSpeed.Speed_Forward_0_75_X
            }
          },
          {
            value: 'x1.00',
            action: () => {
              this.curRate = PlaybackSpeed.Speed_Forward_1_00_X
            }
          },
          {
            value: 'x1.75',
            action: () => {
              this.curRate = PlaybackSpeed.Speed_Forward_1_75_X
            }
          },
          {
            value: 'x2.00',
            action: () => {
              this.curRate = PlaybackSpeed.Speed_Forward_2_00_X
            }
          }
        ])
    }
    .padding(10)
  }

  build() {
    Column() {
      Stack() {
        Video({
          src: this.videoSrc,
          previewUri: this.previewUri,
          currentProgressRate: this.curRate,
          controller: this.controller
        })
          .objectFit(ImageFit.Contain)//设置视频适配模式
          .height(400)
          .controls(false)//不显示默认进度控制条
          .onPrepared((event?: DurationObject) => {
            if (event) {
              this.durationTime = event.duration
            }
          })
          .onUpdate((event?: TimeObject) => {
            if (event) {
              this.currentTime = event.time
            }
          })
        if (!this.isPlay) {
          Image($r('app.media.startVideo'))
            .fillColor(Color.White)
            .opacity(0.8)
            .width(100)
        }
      }

      //滑动控制条
      this.sliderBar()
    }
    .width('100%')
    .height('100%')

    .onClick(() => {
      // 点击视频任意位置实现开始暂停
      if (this.isPlay) {
        this.controller.pause()
      } else {
        this.controller.start()
      }
      this.isPlay = !this.isPlay
    })
  }
}

interface DurationObject {
  duration: number;
}

interface TimeObject {
  time: number;
}
相关推荐
森之鸟3 小时前
flutter项目适配鸿蒙
flutter·华为·harmonyos
奶糖不太甜4 小时前
鸿蒙图片资源加载全攻略:从基础到性能优化
harmonyos·图片资源
小小小小小星4 小时前
鸿蒙多端适配开发指南:从入门到实战
harmonyos
鸿蒙小灰4 小时前
鸿蒙开发之仿抖音APP教程:方法论与技术探索
harmonyos
CC__xy5 小时前
04 类型别名type + 检测数据类型(typeof+instanceof) + 空安全+剩余和展开(运算符 ...)简单类型和复杂类型 + 模块化
开发语言·javascript·harmonyos·鸿蒙
鸿蒙先行者5 小时前
鸿蒙开发ArkUI框架布局与适配难题丛生之响应式布局实现艰难
harmonyos·arkui
ajassi20006 小时前
开源 Arkts 鸿蒙应用 开发(十七)通讯--http多文件下载
华为·开源·harmonyos
前端世界6 小时前
在鸿蒙里优雅地处理网络错误:从 Demo 到实战案例
网络·华为·harmonyos
changsanjiang6 小时前
鸿蒙 音视频边播放边缓存
harmonyos
Georgewu10 小时前
【HarmonyOS】应用调用相机功能(扫码,自定义相机,人脸活体检测等)显示黑屏
harmonyos