AVPlayer API同样适用于视频播放,与音频播放的区别仅在于是否提供surfaceId(相当于给视频播放选择一个容器)。鸿蒙官网描述,surfaceId指视频窗口ID,只允许在initialized状态下设置,在视频播放时要指定窗口进行渲染,纯音频播放不用设置。所以首先来获取窗口Id。
通过XComponent创建surfaceId
@Entry
@Component
struct Index {
private context = getContext(this) as common.UIAbilityContext;
private audio = new AudioPlayer();
private surfaceId: string = ''
private xComponentContext: Record<string, () => void> = {}
xComponentController: XComponentController = new XComponentController()
@State message: string = 'Hello Harmony';
build() {
Row() {
Column() {
Row(){
// 视频播放窗口
XComponent({
id: 'xcomponent',
type: XComponentType.SURFACE,
controller: this.xComponentController
})
.onLoad(() => {
this.xComponentController.setXComponentSurfaceSize({surfaceWidth: 1080, surfaceHeight: 936})
this.surfaceId = this.xComponentController.getXComponentSurfaceId()
this.xComponentContext = this.xComponentController.getXComponentContext() as Record<string, () => void>
})
.width('100%')
.height('40%')
}
}
}
}
AVPlayer初始化
在XComponent的onLoad事件中,调用初始化方法,同时将surfaceId、urlList、index传入。
this.audio.AudioInit(this.surfaceId, this.urlList, this.index)
AvdioPlayer.ets
修改了音频播放的代码,在导出类中新定义了初始化方法,并且接受三个参数:surfaceId(可有可无,音视频通用)、avdioList(播放源列表)、index(当前播放序号)
import media from '@ohos.multimedia.media';
import { BusinessError } from '@ohos.base';
let TAG = 'audio===='
let avPlayer: media.AVPlayer;
let surfaceID: string = '';
let urlList: string[] = []
let index = 0;
media.createAVPlayer().then((video: media.AVPlayer) => {
if (video != null) {
avPlayer = video;
console.info(TAG + avPlayer.state.toString())
console.info('createAVPlayer success');
} else {
console.error('createAVPlayer fail');
}
}).catch((error: BusinessError) => {
console.error(`AVPlayer catchCallback, error message:${error.message}`);
});
function setAVPlayerCallback(avPlayer: media.AVPlayer) {
// seek操作结果回调函数
avPlayer.on('seekDone', (seekDoneTime: number) => {
console.info(`AVPlayer seek succeeded, seek time is ${seekDoneTime}`);
})
// error回调监听函数,当avPlayer在操作过程中出现错误时调用 reset接口触发重置流程
avPlayer.on('error', (err: BusinessError) => {
console.error(`Invoke avPlayer failed, code is ${err.code}, message is ${err.message}`);
avPlayer.reset(); // 调用reset重置资源,触发idle状态
})
// 状态机变化回调函数
avPlayer.on('stateChange', async (state: string, reason: media.StateChangeReason) => {
switch (state) {
case 'idle': // 成功调用reset接口后触发该状态机上报
console.info('AVPlayer state idle called.');
break;
case 'initialized': // avplayer 设置播放源后触发该状态上报
console.info('AVPlayer state initialized called.');
avPlayer.surfaceId = surfaceID
avPlayer.prepare();
break;
case 'prepared': // prepare调用成功后上报该状态机
console.info('AVPlayer state prepared called.');
avPlayer.play(); // 调用播放接口开始播放
break;
case 'playing': // play成功调用后触发该状态机上报
console.info('AVPlayer state playing called.');
break;
case 'paused': // pause成功调用后触发该状态机上报
console.info('AVPlayer state paused called.');
break;
case 'completed': // 播放结束后触发该状态机上报
console.info('AVPlayer state completed called.');
avPlayer.stop(); //调用播放结束接口
break;
case 'stopped': // stop接口成功调用后触发该状态机上报
console.info('AVPlayer state stopped called.');
avPlayer.reset(); // 调用reset接口初始化avplayer状态
break;
case 'released':
console.info('AVPlayer state released called.');
break;
default:
console.info('AVPlayer state unknown called.');
break;
}
})
}
export class AudioPlayer {
public AudioInit(ID:string, avdioList:string[], index:number){
surfaceID = ID
urlList = avdioList
index = index
avPlayer.url = urlList[index];
console.info(TAG + 'init successfully!')
setAVPlayerCallback(avPlayer)
}
public AudioPlay(){
avPlayer.play().then(() => {
console.info('play success');
}, (err: BusinessError) => {
console.error('play filed,error message is :' + err.message)
})
}
public AudioPause(){
avPlayer.pause().then(() => {
console.info('pause success');
}, (err: BusinessError) => {
console.error('pause filed,error message is :' + err.message)
})
}
public AudioReset() {
avPlayer.reset().then(() => {
console.info('reset success');
index = (index + 1)%2;
avPlayer.url = urlList[index]
}, (err: BusinessError) => {
console.error('reset filed,error message is :' + err.message)
})
}
}
bug:由于没有虚拟机,在预览器上AVPlayer.state一直无法识别,所以具体实现可能有偏差,还请大家多多指正~
更新~~
虚拟机搞定,视频可以播放啦