赞
踩
DevEco Studio版本:4.0.0.600
File-->New-->Module,选择Static Library
PlayControl:视频播放控制类
PlayProgress:视频播放器进度条
VideoConstant:视频播放状态配置类
VideoPlayer:视频播放器管理类
然后在VideoLibrary的Index.ets类中添加对外输出的引用
export { VideoPlayer } from './src/main/ets/VideoPlayer'
PlayControl类:
- import { VideoConstant } from './VideoConstant';
-
- /**
- * 播放控制器
- */
- @Component
- export struct PlayControl {
- private playVideoModel?: VideoController;
- @Link videoStatus: number
-
- build() {
- Row() {
- Image(this.videoStatus == VideoConstant.STATUS_START ? $r('app.media.start_press') : $r('app.media.video_play_press'))
- .width('92px')
- .height('92px')
- .margin({ left: '156px', right: '156px' })
- .onClick(() => {
- if (this.videoStatus == VideoConstant.STATUS_START) {
- this.videoStatus = VideoConstant.STATUS_PAUSE
- if (this.playVideoModel != undefined) {
- this.playVideoModel.pause()
- }
- } else {
- this.videoStatus = VideoConstant.STATUS_START
- if (this.playVideoModel != undefined) {
- this.playVideoModel.start()
- }
- }
- })
- }
- }
- }
PlayProgress类:
- /**
- * 播放进度条
- */
- @Component
- export struct PlayProgress {
- @Prop currentTime: number
- @Prop totalTime: number
- private playVideoModel?: VideoController;
-
- build() {
- Row() {
- Text(this.formatTime(this.currentTime))
- .fontSize('14px')
- .fontColor(Color.White)
- .margin({ left: '16px', right: '12px' })
- Slider({
- value: this.currentTime, //当前进度值
- max: this.totalTime, //最大值,默认值100
- step: 1, //设置Slider滑动步长
- style: SliderStyle.OutSet //设置Slider的滑块与滑轨显示样式。
- })
- .blockColor(Color.White)//设置滑块的颜色。
- .trackColor($r('app.color.track_color'))//设置滑轨的背景颜色
- .selectedColor(Color.White)//设置滑轨的已滑动部分颜色
- .trackThickness(2)//设置滑轨的粗细
- .layoutWeight(1)
- .height('60px')
- .onChange((value: number, mode: SliderChangeMode) => {
- if (this.playVideoModel != undefined) {
- this.playVideoModel.setCurrentTime(value, SeekMode.Accurate) // 精准跳转到视频的10s位置
- }
- })
- Text(this.formatTime(this.totalTime))
- .fontSize('14px')
- .fontColor(Color.White)
- .margin({ left: '12px', right: '16px' })
- }
- .width('100%')
- .backgroundColor('#88000000')
- }
-
- /**
- * 格式化时间
- */
- private formatTime(time: number): string {
- if (time < 60) {
- if (time > 9) {
- return '00:' + time
- } else {
- return '00:0' + time
- }
- } else {
- let timeStr = ''
- let hours = Number.parseInt((time / 60).toString())
- let seconds = time % 60
- if (hours > 9) {
- timeStr = hours.toString()
- } else {
- timeStr = '0' + hours
- }
- if (seconds > 9) {
- timeStr = timeStr + ':' + seconds
- } else {
- timeStr = timeStr + ':0' + seconds
- }
- return timeStr
- }
- }
- }
VideoConstant类:
- export class VideoConstant {
- /**
- * 开始播放
- */
- static readonly STATUS_START: number = 1;
-
- /**
- * 暂停播放
- */
- static readonly STATUS_PAUSE: number = 2;
-
- /**
- * 停止播放
- */
- static readonly STATUS_STOP: number = 3;
- }
VideoPlayer类:
- import router from '@ohos.router'
- import { PlayControl } from './video/PlayControl'
- import { PlayProgress } from './video/PlayProgress'
- import { VideoConstant } from './video/VideoConstant'
-
- @Preview
- @Component
- export struct VideoPlayer {
- private videoWidth: Length = '1024px'
- private videoHeight: Length = '550px'
- //视频未播放时的预览图片路径,默认不显示图片
- private previewUris?: Resource
- //视频播放源的路径,支持本地视频路径和网络路径
- @Prop innerResource: Resource
- //设置是否循环播放
- private isLoop: boolean = false
- //设置是否静音
- private isMuted: boolean = false
- //设置是否自动播放
- private isAutoPlay: boolean = true
- //视频控制器,可以控制视频的播放状态
- private controller: VideoController = new VideoController()
- //是否显示控制视图
- @State isShowController: boolean = true
- //视频播放状态
- @State videoStatus: number = VideoConstant.STATUS_STOP
- //视频时长,单位:秒(S)
- @State duration: number = 0
- //视频播放当前时间,单位:秒(S)
- @State currentTime: number = 0
-
- build() {
- Stack() {
- Video({
- src: this.innerResource,
- previewUri: this.previewUris,
- controller: this.controller
- })
- .muted(this.isMuted)//设置是否静音
- .loop(this.isLoop)//设置是否循环播放
- .autoPlay(this.isAutoPlay)//设置是否自动播放
- .controls(false)//设置是否显示默认控制条
- .objectFit(ImageFit.Contain)//设置视频适配模式
- .width('100%')
- .height('100%')
- .onTouch((event) => {
- if (event.type == TouchType.Up) {
- this.isShowController = true
- }
- })
- .onStart(() => { //播放时触发该事件。
- console.info('VideoCreateComponent--- onStart')
- this.videoStatus = VideoConstant.STATUS_START
- })
- .onPause(() => { //播放时触发该事件。
- console.info('VideoCreateComponent--- onPause')
- this.videoStatus = VideoConstant.STATUS_PAUSE
- })
- .onFinish(() => { //播放结束时触发该事件。
- console.info('VideoCreateComponent--- onFinish')
- this.videoStatus = VideoConstant.STATUS_STOP
- })
- .onError(() => { //播放失败时触发该事件。
- console.info('VideoCreateComponent--- onError')
- })
- .onPrepared((e) => { //视频准备完成时触发该事件,通过duration可以获取视频时长,单位为秒(s)
- console.info('VideoCreateComponent--- onPrepared is ' + e.duration)
- this.duration = e.duration
- })
- .onSeeking((e) => { //操作进度条过程时上报时间信息,单位为s。
- console.info('VideoCreateComponent--- onSeeking is ' + e.time)
- })
- .onSeeked((e) => { //操作进度条完成后,上报播放时间信息,单位为s
- console.info('VideoCreateComponent--- onSeeked is ' + e.time)
- })
- .onUpdate((e) => { //播放进度变化时触发该事件,单位为s。
- console.info('VideoCreateComponent--- onUpdate is ' + e.time)
- this.currentTime = e.time
- })
-
- RelativeContainer() {
- Image($r('app.media.video_back'))
- .width('48px')
- .height('48px')
- .alignRules({
- top: { anchor: '__container__', align: VerticalAlign.Top },
- left: { anchor: '__container__', align: HorizontalAlign.Start }
- })
- .margin({ left: '48px', top: '24px' })
- .id('imageBack')
- .onClick(() => {
- router.back()
- })
-
- PlayControl({ playVideoModel: this.controller, videoStatus: $videoStatus })
- .id('playControl')
- .alignRules({
- middle: { anchor: '__container__', align: HorizontalAlign.Center },
- center: { anchor: '__container__', align: VerticalAlign.Center }
- })
-
- PlayProgress({ playVideoModel: this.controller, totalTime: this.duration, currentTime: this.currentTime })
- .id('playProgress')
- .alignRules({
- middle: { anchor: '__container__', align: HorizontalAlign.Center },
- bottom: { anchor: '__container__', align: VerticalAlign.Bottom }
- })
-
- }.width('100%')
- .height('100%')
- .visibility(this.isShowController ? Visibility.Visible : Visibility.None)
- .onTouch((event) => {
- if (event.type == TouchType.Up) {
- this.isShowController = false
- }
- })
- }
- .width(this.videoWidth)
- .height(this.videoHeight)
- }
- }
资源引用:
start_press.png
video_back.png
video_play_press.png
参考链接:静态har共享包
在Entry目录下的oh-package.json5文件中添加对VideoLibaray的引用,详细操作参考之前文章。
- "dependencies": {
- "@app/videoLibrary": "file:../VideoLibrary"
- }
- import { VideoPlayer } from "@app/videoLibrary"
-
- @Entry
- @Component
- struct Index {
- build() {
- Stack() {
- VideoPlayer({
- // previewUris: $r('app.media.preview'), //未播放时的封面
- innerResource: $rawfile('adv_test_video.mp4')
- })
- }
- .width('100%')
- .height('100%')
- }
- }
属性 | 是否必须 | 描述 |
videoWidth | 非必须 | 视频播放器宽度 |
videoHeight | 非必须 | 视频播放器高度 |
previewUris | 非必须 | 视频未播放时的预览图片路径,默认不显示图片 |
innerResource | 必须 | 视频播放源的路径,支持本地视频路径和网络路径 |
isLoop | 非必须 | 设置是否循环播放 |
isMuted | 非必须 | 设置是否静音 |
isAutoPlay | 非必须 | 设置是否自动播放 |
因为我们的视频是横屏播放的,所以需要配置下界面横屏显示
可以参考之前的文章:OpenHarmony 实现屏幕横竖屏_openharmony 屏幕旋转-CSDN博客
横屏配置:在Entry目录下src/main/module.json5中的abilities添加orientation属性
其实鸿蒙官方提供了两种方式播放视频:Video组件、AVPlayer,上面的示例是以Video组件进行封装的,感兴趣的同学可以尝试用AVPlayer进行封装下。
我在尝试用AVPlayer进行视频播放时发现,其seek方法定位不准,大家在调用时也可以关注下这个问题。如果你这边解决了,可以在下方留言说明下如何解决的,感谢!!!
参考文档:OpenHarmony 视频播放
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。