【中工开发者】——视频播放器

wx6750378cdfa69
发布于 2024-12-18 16:26
浏览
0收藏

视频播放器

介绍

我是中工的一名学生,本学期学习了鸿蒙开发,下面一个视频播放器的程序设计。视频播放的主要工作是将视频数据转码并输出到设备进行播放,同时管理播放任务。本文将对视频播放全流程、视频切换、视频循环播放等场景开发进行介绍说明。 本示例主要展示了播放本地视频和网络视频相关功能,使用 @ohos.multimedia.media, @ohos.resourceManager,@ohos.wifiManager等接口,实现了视频播放、暂停、调节倍速、切换视频的功能;实现效果如下;

效果预览

【中工开发者】——视频播放器-鸿蒙开发者社区

使用说明

1.点击视频界面,唤起视频操作面板,再次点击操作面板消失,如果不做任何操作操作界面会5s自动消失;
2.点击暂停/播放按钮,控制视频暂停播放;
3.滑动视频进度条,视频跳转到指定位置,在视频中间会出现时间进度方便用户查看视频进度;
4.点击倍速,可以选择1.0、1.25、1.75、2.0进行倍速调节;
5.点击下方视频名称,可以选择视频进行切换。注意:network是网络视频,没有连接网络无法切换到网络视频,有网络能在本地视频和网络视频进行切换;
6.点击左上角退出箭头,退出应用。

目录结构

【中工开发者】——视频播放器-鸿蒙开发者社区

具体实现

• 视频倍速切换、暂停、播放、切换视频、视频跳转的功能接口都封装在AvPlayManager.ets,源码参考:​​AvPlayManager.ets​​;
• 使用media.createAVPlayer()来获取AVPlayer对象;
• 倍速切换:选择不同的倍速时调用avPlayer.setSpeed(speed: PlaybackSpeed);
• 暂停、播放:点击暂停、播放时调用avPlayer.pause()、avPlayer.play();
• 切换视频:在切换视频前要先调用avPlayer.reset()重置资源,再通过avPlayer.fdSrc为fdSrc赋值触发initialized状态机上报;
• 视频跳转:在拖动滑动条时调用avPlayer.seek()

相关权限

ohos.permission.INTERNET
ohos.permission.GET_NETWORK_INFO

依赖

不涉及。

约束与限制

1.本示例仅支持标准系统上运行,支持设备:华为手机。
2.HarmonyOS系统:HarmonyOS 5.0.0 Release及以上。
3.DevEco Studio版本:DevEco Studio 5.0.0 Release及以上。
4.HarmonyOS SDK版本:HarmonyOS 5.0.0 Release SDK及以上

相关代码

界面主要代码实现

build() {
  Stack() {
    Column() {
      this.CoverXComponent()
    }
    .align(Alignment.TopStart)
    .margin({ top: $r('app.float.size_80') })
    .id('Video')
    .justifyContent(FlexAlign.Center)

    Text()
      .height(`${this.sufaceH}px`)
      .width(`${this.sufaceW}px`)
      .margin({ top: $r('app.float.size_80') })
      .backgroundColor(Color.Black)
      .opacity($r('app.float.size_zero_five'))
      .visibility(this.isSwiping ? Visibility.Visible : Visibility.Hidden)

    VideoPanel({ show: $show, videoSelect: $videoSelect })
      .zIndex(3)

    Row() {
      Text(timeConvert(this.currentTime))
        .fontSize($r('app.float.size_24'))
        .opacity($r('app.float.size_1'))
        .fontColor($r("app.color.slider_selected"))
      Text("/" + timeConvert(this.durationTime))
        .fontSize($r('app.float.size_24'))
        .opacity($r('app.float.size_1'))
        .fontColor(Color.White)
    }
    .margin({ top: $r('app.float.size_80') })
    .visibility(this.isSwiping ? Visibility.Visible : Visibility.Hidden)

    Column() {
      Row() {
        ExitVideo()
      }
      .width('100%')
      .justifyContent(FlexAlign.Start)

      Blank()

      Column() {
        // Progress bar
        VideoOperate({
          flag: $flag,
          avPlayManage: $avPlayManage,
          currentTime: $currentTime,
          durationTime: $durationTime,
          isSwiping: $isSwiping,
          XComponentFlag: $XComponentFlag
        })
          .width('100%')

        Row() {
          Image($r('app.media.ic_video_view_list'))
            .width($r('app.float.size_32'))
            .height($r('app.float.size_32'))
            .margin({ left: $r('app.float.size_30') })
          Text(this.videoName)
            .fontSize($r('app.float.size_20'))
            .fontColor(Color.White)
            .fontWeight(FontWeight.Regular)
            .margin({ left: $r('app.float.size_10') })
          Blank()
          Column() {
            Image($r('app.media.ic_video_list_up'))
              .width($r('app.float.size_30'))
              .height($r('app.float.size_20'))
          }
          .margin({ right: $r('app.float.size_25') })
        }
        .id('Choose')
        .margin({ top: $r('app.float.size_10') })
        .width('100%')
        .height($r('app.float.size_50'))
        .backgroundColor($r('app.color.video_play'))
        .borderRadius({ topLeft: $r('app.float.size_45'), topRight: $r('app.float.size_45') })
        .alignItems(VerticalAlign.Center)
        .onClick(() => {
          this.show = !this.show;
          this.videoSelect = this.videoIndex;
        })
      }
      .justifyContent(FlexAlign.Center)
    }
    .onTouch((event: TouchEvent) => {
      if (event.type == TouchType.Down) {
        this.isClickScreen = true;
        this.clearTimer();
      } else if (event.type == TouchType.Up) {
        this.setTimer();
      } else if (event.type == TouchType.Move) {
        this.isClickScreen = true;
        this.clearTimer();
      }
    })
    .visibility(this.isClickScreen ? Visibility.Visible : Visibility.Hidden)
    .width('100%')
    .height('100%')
  }
  .onClick(() => {
    this.isClickScreen = !this.isClickScreen;
    if (this.isClickScreen) {
      this.setTimer();
    } else {
      this.clearTimer();
    }
  })
  .backgroundColor(Color.Black)
  .height('100%')
  .width('100%')
  .padding({ top: '36vp', bottom: '28vp'})
}
}

退出应用组件

build() {
  Row() {
    // Exit
    Image($r("app.media.ic_video_back"))
      .id('Exit')
      .width($r('app.float.size_35'))
      .height($r('app.float.size_35'))

    Text(this.videoName)
      .fontColor(Color.White)
      .fontWeight(FontWeight.Medium)
      .fontSize($r('app.float.size_24'))
      .margin({ left: $r('app.float.size_16') })
  }
  .margin({ top: $r('app.float.size_20'), left: $r('app.float.size_25') })
  .onClick(() => {
    (GlobalContext.getContext().getObject('context') as (common.UIAbilityContext)).terminateSelf();
  })
}
}

视频倍速弹窗

build() {
   Column() {
     Text($r('app.string.dialog_play_speed'))
       .fontSize($r('app.float.size_20'))
       .width("90%")
       .fontColor(Color.Black)
       .textAlign(TextAlign.Start)
       .margin({ top: $r('app.float.size_20'), bottom: $r('app.float.size_12') })

     List() {
       ForEach(this.speedList, (item: Resource, index) => {
         ListItem() {
           Column() {
             Row() {
               Text(item)
                 .fontSize($r('app.float.size_16'))
                 .fontColor(Color.Black)
                 .fontWeight(FontWeight.Medium)
                 .textAlign(TextAlign.Center)
               Blank()
               Image(this.speedSelect == index ? $r('app.media.ic_radio_selected') : $r('app.media.ic_radio'))
                 .width($r('app.float.size_24'))
                 .height($r('app.float.size_24'))
                 .objectFit(ImageFit.Contain)
             }
             .width('100%')

             if (index != this.speedList.length - ONE) {
               Divider()
                 .vertical(false)
                 .strokeWidth(1)
                 .margin({ top: $r('app.float.size_10') })
                 .color($r('app.color.speed_dialog'))
                 .width('100%')
             }
           }
           .width("90%")
         }
         .width("100%")
         .height($r('app.float.size_48'))
         .onClick(() => {
           this.speedSelect = index;
           AppStorage.setOrCreate('speedName', this.speedList[this.speedSelect]);
           AppStorage.setOrCreate('speedIndex', this.speedSelect);
           this.controller.close();
           switch (this.speedSelect) {
             case ZERO:
               this.avPlayManage.videoSpeedOne();
               break;
             case ONE:
               this.avPlayManage.videoSpeedOnePointTwentyFive();
               break;
             case TWO:
               this.avPlayManage.videoSpeedOnePointSeventyFive();
               break;
             case THREE:
               this.avPlayManage.videoSpeedTwo();
               break;
           }
         })
       })
     }
     .width("100%")
     .margin({
       top: $r('app.float.size_12')
     })

     Row() {
       Text($r('app.string.dialog_cancel'))
         .fontSize($r('app.float.size_16'))
         .fontColor('#0A59F7')
         .fontWeight(FontWeight.Medium)
         .layoutWeight(1)
         .textAlign(TextAlign.Center)
         .onClick(() => {
           this.controller.close()
         })
     }
     .alignItems(VerticalAlign.Center)
     .height($r('app.float.size_50'))
     .padding({ bottom: $r('app.float.size_5') })
     .width("100%")
   }
   .alignItems(HorizontalAlign.Center)
   .width("90%")
   .borderRadius($r('app.float.size_24'))
   .backgroundColor(Color.White)
 }
}

视频操作组件

build() {
  Column() {
    Text($r('app.string.dialog_play_speed'))
      .fontSize($r('app.float.size_20'))
      .width("90%")
      .fontColor(Color.Black)
      .textAlign(TextAlign.Start)
      .margin({ top: $r('app.float.size_20'), bottom: $r('app.float.size_12') })

    List() {
      ForEach(this.speedList, (item: Resource, index) => {
        ListItem() {
          Column() {
            Row() {
              Text(item)
                .fontSize($r('app.float.size_16'))
                .fontColor(Color.Black)
                .fontWeight(FontWeight.Medium)
                .textAlign(TextAlign.Center)
              Blank()
              Image(this.speedSelect == index ? $r('app.media.ic_radio_selected') : $r('app.media.ic_radio'))
                .width($r('app.float.size_24'))
                .height($r('app.float.size_24'))
                .objectFit(ImageFit.Contain)
            }
            .width('100%')

            if (index != this.speedList.length - ONE) {
              Divider()
                .vertical(false)
                .strokeWidth(1)
                .margin({ top: $r('app.float.size_10') })
                .color($r('app.color.speed_dialog'))
                .width('100%')
            }
          }
          .width("90%")
        }
        .width("100%")
        .height($r('app.float.size_48'))
        .onClick(() => {
          this.speedSelect = index;
          AppStorage.setOrCreate('speedName', this.speedList[this.speedSelect]);
          AppStorage.setOrCreate('speedIndex', this.speedSelect);
          this.controller.close();
          switch (this.speedSelect) {
            case ZERO:
              this.avPlayManage.videoSpeedOne();
              break;
            case ONE:
              this.avPlayManage.videoSpeedOnePointTwentyFive();
              break;
            case TWO:
              this.avPlayManage.videoSpeedOnePointSeventyFive();
              break;
            case THREE:
              this.avPlayManage.videoSpeedTwo();
              break;
          }
        })
      })
    }
    .width("100%")
    .margin({
      top: $r('app.float.size_12')
    })

    Row() {
      Text($r('app.string.dialog_cancel'))
        .fontSize($r('app.float.size_16'))
        .fontColor('#0A59F7')
        .fontWeight(FontWeight.Medium)
        .layoutWeight(1)
        .textAlign(TextAlign.Center)
        .onClick(() => {
          this.controller.close()
        })
    }
    .alignItems(VerticalAlign.Center)
    .height($r('app.float.size_50'))
    .padding({ bottom: $r('app.float.size_5') })
    .width("100%")
  }
  .alignItems(HorizontalAlign.Center)
  .width("90%")
  .borderRadius($r('app.float.size_24'))
  .backgroundColor(Color.White)
}
}

参考文献

​​https://gitee.com/harmonyos_samples/video-play

分类
收藏
回复
举报
回复
    相关推荐