鸿蒙应用开发:AVPlayer 多媒体播放全攻略
AVPlayer是鸿蒙系统的音视频播放组件,支持本地和网络流媒体播放。文章详细介绍了AVPlayer的核心概念、状态机机制和开发步骤:1)创建实例并设置监听器;2)配置播放资源;3)绑定显示窗口;4)控制播放流程;5)释放资源。重点强调了状态机管理、事件监听和资源释放的重要性,并提供了ArkTS代码示例。通过遵循这些步骤和最佳实践,开发者可以高效实现多媒体播放功能。
一、AVPlayer 是什么?
AVPlayer 是鸿蒙系统 @kit.MediaLibraryKit 包中提供的一个功能强大的音视频播放器组件。它是一个端到端的播放解决方案,集成了流媒体协议解析、媒体资源解封装、音视频解码和渲染功能。你可以用它来播放本地文件(如 mp4, mkv, mp3)或网络流媒体(如 HLS, DASH)。
核心特点:
- 功能全面:支持播放、暂停、跳转、倍速、音量调节、音轨切换等。
- 多格式支持:支持广泛的容器格式和编码格式。
- 状态机驱动:通过清晰的状态变化来管理播放生命周期,开发逻辑更清晰。
- 事件监听:提供丰富的事件回调,用于更新UI和处理异常。
二、核心概念:状态机 (State Machine)
理解AVPlayer的状态机是正确使用它的关键!任何操作都需要在合适的状态下调用。
- idle (闲置状态): 调用
createAVPlayer()后的初始状态。 - initialized (初始化状态): 成功设置播放资源(
url或fdSrc)后的状态。 - prepared (准备状态): 调用
prepare()成功后的状态。此时可以获取视频时长(duration)、设置音量、倍速等。 - playing (播放状态): 调用
play()后的状态。 - paused (暂停状态): 调用
pause()后的状态。 - completed (播放完成状态): 播放自然结束的状态。
- stopped (停止状态): 调用
stop()后的状态。 - released (释放状态): 调用
release()后的状态。此时播放器实例已销毁,不可再用。 - error (错误状态): 在任何阶段发生错误时进入此状态。
重要提示: 在 prepared, playing, paused, completed 状态时,播放器引擎处于工作状态,会占用较多系统资源。在不使用时,请及时调用 reset() 或 release() 进行资源回收。
三、开发步骤详解 (ArkTS版)
下面我们以播放一个网络视频为例,分步讲解。
步骤 1:导入模块并声明权限
// 1. 导入必要的模块
import { media } from '@kit.MediaLibraryKit';
import { common } from '@kit.AbilityKit';
import { fileIo } from '@kit.CoreFileKit'; // 如果涉及本地文件操作
// 2. 在 module.json5 中声明网络权限
// "requestPermissions": [
// {
// "name": "ohos.permission.INTERNET"
// }
// ]
步骤 2:创建 AVPlayer 实例
// 在您的组件或类中定义
private avPlayer: media.AVPlayer | null = null;
// 创建播放器的方法
async createAVPlayerInstance() {
try {
this.avPlayer = await media.createAVPlayer();
console.info('AVPlayer 创建成功,当前状态:idle');
// 创建成功后,立即设置监听器!
this.setupAVPlayerListeners();
} catch (error) {
console.error(`创建AVPlayer失败: ${error.code}, ${error.message}`);
}
}
步骤 3:设置事件监听器 (核心)
这是与播放器交互并更新UI的关键。
private setupAVPlayerListeners() {
if (this.avPlayer == null) {
return;
}
// 1. 监听状态变化 (最重要的事件)
this.avPlayer.on('stateChange', (state: media.AVPlayerState) => {
console.info(`状态发生变化: ${state}`);
switch (state) {
case 'prepared':
// 可以在这里获取总时长并更新UI
let duration = this.avPlayer?.duration;
console.info(`视频总时长: ${duration} ms`);
break;
case 'completed':
// 播放完成,可以重置或进行下一步操作
console.info('播放完成');
break;
case 'error':
// 发生错误,需要进行处理
console.error('播放器进入错误状态');
break;
}
});
// 2. 监听错误事件
this.avPlayer.on('error', (err: BusinessError) => {
console.error(`发生错误, code: ${err.code}, message: ${err.message}`);
});
// 3. 监听时间更新 (用于更新进度条)
this.avPlayer.on('timeUpdate', (currentTime: number) => {
// 每秒会触发多次,用于更新UI上的当前播放时间
// this.currentTime = currentTime; // 更新@State变量
});
// 4. 监听时长更新
this.avPlayer.on('durationUpdate', (duration: number) => {
// this.totalDuration = duration; // 更新@State变量
});
// 5. 监听跳转完成
this.avPlayer.on('seekDone', (seekTime: number) => {
console.info(`跳转完成到: ${seekTime} ms`);
// 跳转完成后可以恢复播放
});
// 还有其他事件,如 volumeChange, speedDone, bufferingUpdate 等
}
最佳实践: 监听器应在 idle 状态、设置资源之前就设置好,以确保能捕获到所有状态变化。
步骤 4:设置播放资源 (URL)
async setVideoSource() {
if (this.avPlayer == null) {
return;
}
try {
// 设置网络视频地址
let url = ' https://www.example.com/sample.mp4 '; // 替换为有效地址
this.avPlayer.url = url; // 赋值后,状态会变为 'initialized'
console.info('资源设置成功');
} catch (error) {
console.error(`设置资源失败: ${error.code}, ${error.message}`);
}
}
- 播放本地沙箱文件:使用
fdSrc属性。// 获取应用沙箱内文件的文件描述符 let file = await fs.open('path/in/sandbox/video.mp4'); let avFileDescriptor: media.AVFileDescriptor = { fd: file.fd, offset: 0, // 偏移量 length: 1024 // 文件长度,不知道可设为-1 }; this.avPlayer.fdSrc = avFileDescriptor;
步骤 5:设置显示窗口 (仅视频)
视频播放需要绑定一个 XComponent 提供的 surface。
- 在布局文件中添加 XComponent:
XComponent() .id('xComponentId') // 设置ID .type('surface') // 类型必须为surface .width('100%') .height(300) - 在代码中获取 surfaceID 并设置:
import { UIContext } from '@ohos.arkui.UIContext'; // 在合适的生命周期函数中(如aboutToAppear)或点击事件中 private setSurface() { // 通过ID获取XComponent的UIContext,然后获取surfaceID let uiContext = this.getUIContext('xComponentId') as UIContext; let surfaceID = uiContext.getXComponentSurfaceId(); if (this.avPlayer != null) { this.avPlayer.surfaceId = surfaceID; // 设置显示窗口 } }
步骤 6:准备播放
async preparePlayback() {
if (this.avPlayer == null) {
return;
}
// 确保状态是 initialized
if (this.avPlayer.state === 'initialized') {
try {
await this.avPlayer.prepare();
console.info('Prepare调用成功,状态变为prepared');
} catch (error) {
console.error(`Prepare失败: ${error.code}, ${error.message}`);
}
}
}
步骤 7:播放控制
在 prepared, playing, paused 等状态下进行控制。
// 播放
play() {
this.avPlayer?.play();
}
// 暂停
pause() {
this.avPlayer?.pause();
}
// 跳转 (单位: ms)
seekTo(time: number) {
this.avPlayer?.seek(time);
}
// 停止 (停止后如需再次播放,需重新调用prepare())
stop() {
this.avPlayer?.stop();
}
// 设置音量 (范围 0.0 ~ 1.0)
setVolume(volume: number) {
this.avPlayer?.setVolume(volume);
}
// 设置倍速 (如 0.75, 1.0, 1.5, 2.0)
setSpeed(speed: number) {
this.avPlayer?.setSpeed(speed);
}
步骤 8:资源释放 (非常重要!)
在页面销毁或不再需要播放器时,必须释放资源。
releaseAVPlayer() {
if (this.avPlayer != null) {
// 先停止播放
this.avPlayer.stop();
// 释放资源,实例不可再用
this.avPlayer.release();
this.avPlayer = null;
console.info('AVPlayer 已释放');
}
}
// 在ArkUI组件的 aboutToDisappear 生命周期中调用
aboutToDisappear() {
this.releaseAVPlayer();
}
四、完整代码示例
// 一个极简的播放组件示例
@Entry
@Component
struct SimpleVideoPlayer {
private avPlayer: media.AVPlayer | null = null;
@State currentState: string = '未开始';
aboutToAppear() {
this.initPlayer();
}
async initPlayer() {
this.avPlayer = await media.createAVPlayer();
this.setupListeners();
this.avPlayer.url = ' https://example.com/sample.mp4 ';
}
setupListeners() {
this.avPlayer?.on('stateChange', (state: media.AVPlayerState) => {
this.currentState = state;
console.info(state);
});
}
build() {
Column() {
Text(`当前状态: ${this.currentState}`)
XComponent()
.id('videoSurface')
.type('surface')
.width('100%')
.height(300)
.onLoad(() => {
let uiContext = this.getUIContext('videoSurface') as UIContext;
let surfaceId = uiContext.getXComponentSurfaceId();
this.avPlayer && (this.avPlayer.surfaceId = surfaceId);
})
Row() {
Button('准备').onClick(() => { this.avPlayer?.prepare(); })
Button('播放').onClick(() => { this.avPlayer?.play(); })
Button('暂停').onClick(() => { this.avPlayer?.pause(); })
Button('停止').onClick(() => { this.avPlayer?.stop(); })
}
}.width('100%').height('100%')
}
aboutToDisappear() {
this.avPlayer?.release();
}
}
五、总结与最佳实践
- 状态驱动:任何操作前,先检查
avPlayer.state是否处于合适的状态。 - 提前监听:在
idle状态就设置好所有事件监听器。 - 资源释放:务必在组件销毁时调用
release(),防止内存泄漏。 - 错误处理:一定要监听
error事件,并做好用户提示。 - 网络权限:播放网络视频别忘了在
module.json5中声明ohos.permission.INTERNET权限。 - 后台播放:如果需要应用退到后台后继续播放音频,需要申请长时任务权限并接入
AVSession。
通过本教程,你应该对如何使用鸿蒙的 AVPlayer 有了全面的了解。现在就可以动手实践,在你的应用中集成多媒体播放功能了!
更多推荐



所有评论(0)