华为官方这边提供了两种视频播放的方式,一种是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;
}