当前位置:   article > 正文

鸿蒙自定义Video播放器

鸿蒙自定义Video播放器

前言

DevEco Studio版本:4.0.0.600

使用效果

如何使用

参考文档:OpenHarmony Video使用说明

1、module创建

File-->New-->Module,选择Static Library

2、相关类创建

PlayControl:视频播放控制类

PlayProgress:视频播放器进度条

VideoConstant:视频播放状态配置类

VideoPlayer:视频播放器管理类

然后在VideoLibraryIndex.ets类中添加对外输出的引用

export { VideoPlayer } from './src/main/ets/VideoPlayer'

PlayControl类:

  1. import { VideoConstant } from './VideoConstant';
  2. /**
  3. * 播放控制器
  4. */
  5. @Component
  6. export struct PlayControl {
  7. private playVideoModel?: VideoController;
  8. @Link videoStatus: number
  9. build() {
  10. Row() {
  11. Image(this.videoStatus == VideoConstant.STATUS_START ? $r('app.media.start_press') : $r('app.media.video_play_press'))
  12. .width('92px')
  13. .height('92px')
  14. .margin({ left: '156px', right: '156px' })
  15. .onClick(() => {
  16. if (this.videoStatus == VideoConstant.STATUS_START) {
  17. this.videoStatus = VideoConstant.STATUS_PAUSE
  18. if (this.playVideoModel != undefined) {
  19. this.playVideoModel.pause()
  20. }
  21. } else {
  22. this.videoStatus = VideoConstant.STATUS_START
  23. if (this.playVideoModel != undefined) {
  24. this.playVideoModel.start()
  25. }
  26. }
  27. })
  28. }
  29. }
  30. }

PlayProgress类:

  1. /**
  2. * 播放进度条
  3. */
  4. @Component
  5. export struct PlayProgress {
  6. @Prop currentTime: number
  7. @Prop totalTime: number
  8. private playVideoModel?: VideoController;
  9. build() {
  10. Row() {
  11. Text(this.formatTime(this.currentTime))
  12. .fontSize('14px')
  13. .fontColor(Color.White)
  14. .margin({ left: '16px', right: '12px' })
  15. Slider({
  16. value: this.currentTime, //当前进度值
  17. max: this.totalTime, //最大值,默认值100
  18. step: 1, //设置Slider滑动步长
  19. style: SliderStyle.OutSet //设置Slider的滑块与滑轨显示样式。
  20. })
  21. .blockColor(Color.White)//设置滑块的颜色。
  22. .trackColor($r('app.color.track_color'))//设置滑轨的背景颜色
  23. .selectedColor(Color.White)//设置滑轨的已滑动部分颜色
  24. .trackThickness(2)//设置滑轨的粗细
  25. .layoutWeight(1)
  26. .height('60px')
  27. .onChange((value: number, mode: SliderChangeMode) => {
  28. if (this.playVideoModel != undefined) {
  29. this.playVideoModel.setCurrentTime(value, SeekMode.Accurate) // 精准跳转到视频的10s位置
  30. }
  31. })
  32. Text(this.formatTime(this.totalTime))
  33. .fontSize('14px')
  34. .fontColor(Color.White)
  35. .margin({ left: '12px', right: '16px' })
  36. }
  37. .width('100%')
  38. .backgroundColor('#88000000')
  39. }
  40. /**
  41. * 格式化时间
  42. */
  43. private formatTime(time: number): string {
  44. if (time < 60) {
  45. if (time > 9) {
  46. return '00:' + time
  47. } else {
  48. return '00:0' + time
  49. }
  50. } else {
  51. let timeStr = ''
  52. let hours = Number.parseInt((time / 60).toString())
  53. let seconds = time % 60
  54. if (hours > 9) {
  55. timeStr = hours.toString()
  56. } else {
  57. timeStr = '0' + hours
  58. }
  59. if (seconds > 9) {
  60. timeStr = timeStr + ':' + seconds
  61. } else {
  62. timeStr = timeStr + ':0' + seconds
  63. }
  64. return timeStr
  65. }
  66. }
  67. }

VideoConstant类:

  1. export class VideoConstant {
  2. /**
  3. * 开始播放
  4. */
  5. static readonly STATUS_START: number = 1;
  6. /**
  7. * 暂停播放
  8. */
  9. static readonly STATUS_PAUSE: number = 2;
  10. /**
  11. * 停止播放
  12. */
  13. static readonly STATUS_STOP: number = 3;
  14. }

VideoPlayer类:

  1. import router from '@ohos.router'
  2. import { PlayControl } from './video/PlayControl'
  3. import { PlayProgress } from './video/PlayProgress'
  4. import { VideoConstant } from './video/VideoConstant'
  5. @Preview
  6. @Component
  7. export struct VideoPlayer {
  8. private videoWidth: Length = '1024px'
  9. private videoHeight: Length = '550px'
  10. //视频未播放时的预览图片路径,默认不显示图片
  11. private previewUris?: Resource
  12. //视频播放源的路径,支持本地视频路径和网络路径
  13. @Prop innerResource: Resource
  14. //设置是否循环播放
  15. private isLoop: boolean = false
  16. //设置是否静音
  17. private isMuted: boolean = false
  18. //设置是否自动播放
  19. private isAutoPlay: boolean = true
  20. //视频控制器,可以控制视频的播放状态
  21. private controller: VideoController = new VideoController()
  22. //是否显示控制视图
  23. @State isShowController: boolean = true
  24. //视频播放状态
  25. @State videoStatus: number = VideoConstant.STATUS_STOP
  26. //视频时长,单位:秒(S)
  27. @State duration: number = 0
  28. //视频播放当前时间,单位:秒(S)
  29. @State currentTime: number = 0
  30. build() {
  31. Stack() {
  32. Video({
  33. src: this.innerResource,
  34. previewUri: this.previewUris,
  35. controller: this.controller
  36. })
  37. .muted(this.isMuted)//设置是否静音
  38. .loop(this.isLoop)//设置是否循环播放
  39. .autoPlay(this.isAutoPlay)//设置是否自动播放
  40. .controls(false)//设置是否显示默认控制条
  41. .objectFit(ImageFit.Contain)//设置视频适配模式
  42. .width('100%')
  43. .height('100%')
  44. .onTouch((event) => {
  45. if (event.type == TouchType.Up) {
  46. this.isShowController = true
  47. }
  48. })
  49. .onStart(() => { //播放时触发该事件。
  50. console.info('VideoCreateComponent--- onStart')
  51. this.videoStatus = VideoConstant.STATUS_START
  52. })
  53. .onPause(() => { //播放时触发该事件。
  54. console.info('VideoCreateComponent--- onPause')
  55. this.videoStatus = VideoConstant.STATUS_PAUSE
  56. })
  57. .onFinish(() => { //播放结束时触发该事件。
  58. console.info('VideoCreateComponent--- onFinish')
  59. this.videoStatus = VideoConstant.STATUS_STOP
  60. })
  61. .onError(() => { //播放失败时触发该事件。
  62. console.info('VideoCreateComponent--- onError')
  63. })
  64. .onPrepared((e) => { //视频准备完成时触发该事件,通过duration可以获取视频时长,单位为秒(s)
  65. console.info('VideoCreateComponent--- onPrepared is ' + e.duration)
  66. this.duration = e.duration
  67. })
  68. .onSeeking((e) => { //操作进度条过程时上报时间信息,单位为s。
  69. console.info('VideoCreateComponent--- onSeeking is ' + e.time)
  70. })
  71. .onSeeked((e) => { //操作进度条完成后,上报播放时间信息,单位为s
  72. console.info('VideoCreateComponent--- onSeeked is ' + e.time)
  73. })
  74. .onUpdate((e) => { //播放进度变化时触发该事件,单位为s。
  75. console.info('VideoCreateComponent--- onUpdate is ' + e.time)
  76. this.currentTime = e.time
  77. })
  78. RelativeContainer() {
  79. Image($r('app.media.video_back'))
  80. .width('48px')
  81. .height('48px')
  82. .alignRules({
  83. top: { anchor: '__container__', align: VerticalAlign.Top },
  84. left: { anchor: '__container__', align: HorizontalAlign.Start }
  85. })
  86. .margin({ left: '48px', top: '24px' })
  87. .id('imageBack')
  88. .onClick(() => {
  89. router.back()
  90. })
  91. PlayControl({ playVideoModel: this.controller, videoStatus: $videoStatus })
  92. .id('playControl')
  93. .alignRules({
  94. middle: { anchor: '__container__', align: HorizontalAlign.Center },
  95. center: { anchor: '__container__', align: VerticalAlign.Center }
  96. })
  97. PlayProgress({ playVideoModel: this.controller, totalTime: this.duration, currentTime: this.currentTime })
  98. .id('playProgress')
  99. .alignRules({
  100. middle: { anchor: '__container__', align: HorizontalAlign.Center },
  101. bottom: { anchor: '__container__', align: VerticalAlign.Bottom }
  102. })
  103. }.width('100%')
  104. .height('100%')
  105. .visibility(this.isShowController ? Visibility.Visible : Visibility.None)
  106. .onTouch((event) => {
  107. if (event.type == TouchType.Up) {
  108. this.isShowController = false
  109. }
  110. })
  111. }
  112. .width(this.videoWidth)
  113. .height(this.videoHeight)
  114. }
  115. }

资源引用:

start_press.png

video_back.png

video_play_press.png

3、在Entry中引用HttpLibaray

参考链接:静态har共享包

Entry目录下的oh-package.json5文件中添加对VideoLibaray的引用,详细操作参考之前文章。

  1. "dependencies": {
  2. "@app/videoLibrary": "file:../VideoLibrary"
  3. }

4、代码调用

  1. import { VideoPlayer } from "@app/videoLibrary"
  2. @Entry
  3. @Component
  4. struct Index {
  5. build() {
  6. Stack() {
  7. VideoPlayer({
  8. // previewUris: $r('app.media.preview'), //未播放时的封面
  9. innerResource: $rawfile('adv_test_video.mp4')
  10. })
  11. }
  12. .width('100%')
  13. .height('100%')
  14. }
  15. }
属性是否必须描述
videoWidth非必须视频播放器宽度
videoHeight非必须视频播放器高度
previewUris非必须视频未播放时的预览图片路径,默认不显示图片
innerResource必须视频播放源的路径,支持本地视频路径和网络路径
isLoop非必须设置是否循环播放
isMuted非必须设置是否静音
isAutoPlay非必须设置是否自动播放

因为我们的视频是横屏播放的,所以需要配置下界面横屏显示

可以参考之前的文章OpenHarmony 实现屏幕横竖屏_openharmony 屏幕旋转-CSDN博客

横屏配置:在Entry目录下src/main/module.json5中的abilities添加orientation属性

其实鸿蒙官方提供了两种方式播放视频:Video组件、AVPlayer,上面的示例是以Video组件进行封装的,感兴趣的同学可以尝试用AVPlayer进行封装下。

我在尝试用AVPlayer进行视频播放时发现,其seek方法定位不准,大家在调用时也可以关注下这个问题。如果你这边解决了,可以在下方留言说明下如何解决的,感谢!!!

参考文档OpenHarmony 视频播放

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/580390
推荐阅读
相关标签
  

闽ICP备14008679号