文章目录
- 前言
- AVPlayer 是什么
- 代码实现
- 画面载体:XComponent
- 核心代码
- 播放控制
- 完整示例
- 完整播放器骨架
- 常见误区(小白必踩)
- 完整可运行示例:AVPlayer 播音频
- 代码解析
- 写在最后
前言
做个能播放音视频的 app,听起来高大上,其实 HarmonyOS 已经把最难的编解码封装好了,你只要学会AVPlayer这个播放器对象怎么用就行。
这篇文章我带你实现一个"播放/暂停/进度"俱全的本地视频播放器。网络视频套路一样,只是地址不同。
AVPlayer 是什么
AVPlayer是系统提供的多媒体播放器,负责"拿到资源 → 解码 → 输出到界面"。你不用懂编解码,只要:设置数据源、准备、播放、控制。
代码实现
import{media}from'@kit.MediaKit'letplayer:media.AVPlayerasyncfunctioninitPlayer(surfaceId:string,url:string){player=awaitmedia.createAVPlayer()player.url=url// 设置播放地址player.surfaceId=surfaceId// 绑定到 XComponent 的渲染表面}要点:
createAVPlayer()异步创建播放器。player.url:本地或网络媒体地址。player.surfaceId:播放画面要"贴"在哪个渲染表面上,这个表面由XComponent提供(见下)。
画面载体:XComponent
视频画面不能直接用普通组件显示,得用XComponent提供一块"原生渲染表面":
核心代码
@LocalsurfaceId:string=''build(){Column(){XComponent({id:'video',type:XComponentType.SURFACE,controller:this.xcCtrl}).onLoad((surfaceId:string)=>{this.surfaceId=surfaceId// 拿到表面 id}).width('100%').height(240)}}XComponent的onLoad回调会给你一个surfaceId,把它存起来传给player.surfaceId,画面就出来了。- 必须先有
surfaceId,才能初始化播放器——所以初始化要等onLoad之后。
播放控制
播放器有几个核心状态,控制就围绕它们:
完整示例
functionplay(){player.play()}// 播放functionpause(){player.pause()}// 暂停functionseekTo(ms:number){player.seek(ms)}// 拖到指定毫秒// 监听状态与进度player.on('stateChange',(state)=>{console.info('播放器状态:'+state)// 'playing' / 'paused' / 'completed'})player.on('timeUpdate',(cur:number,dur:number)=>{this.progress=cur/dur// 计算播放进度比例})play()/pause():最基础的播放暂停。seek(ms):跳转到指定时间,做进度条拖动用。timeUpdate事件:持续回调当前时间和总时长,用来更新进度条。
完整播放器骨架
@Entry@ComponentV2struct VideoPlayer{@LocalsurfaceId:string=''@Localprogress:number=0@Localplaying:boolean=falseprivatexcCtrl:XComponentController=newXComponentController()privateplayer?:media.AVPlayerbuild(){Column(){XComponent({id:'v',type:XComponentType.SURFACE,controller:this.xcCtrl}).onLoad(async(id)=>{this.surfaceId=idthis.player=awaitmedia.createAVPlayer()this.player.url='file:///data/storage/el2/base/haps/entry/files/demo.mp4'this.player.surfaceId=idthis.player.on('timeUpdate',(c,d)=>{this.progress=d?c/d:0})}).width('100%').height(240)Row(){Button(this.playing?'暂停':'播放').onClick(()=>{if(this.playing){this.player?.pause();this.playing=false}else{this.player?.play();this.playing=true}})Slider({value:this.progress*100,min:0,max:100}).onChange((v)=>{this.player?.seek(v/100*1000)})}}.padding(12)}}这是一个能播、能暂停、能拖进度的播放器雏形。
常见误区(小白必踩)
| 误区 | 说明 |
|---|---|
surfaceId没拿到就初始化播放器 | 必须先等XComponent.onLoad拿到表面 id,再创建 AVPlayer 绑定。 |
不监听timeUpdate | 进度条要的当前/总时长都从这里来,不监听就做不了进度条。 |
| 音频也套 XComponent | 纯音频不需要画面载体,直接createAVPlayer设 url 播放即可。 |
下面这段代码可以直接复制到 DevEco Studio 里运行。建议你边读边敲,改一改文末「动手改一改」里的参数,亲眼看看效果。
完整可运行示例:AVPlayer 播音频
用AVPlayer播放一段网络音频,带播放/暂停控制。
代码解析
// AVPlayer 播放网络音频import{media}from'@kit.MediaKit'@Entry@Componentstruct AudioPlayer{privateavp?:media.AVPlayer@Stateplaying:boolean=falseaboutToAppear(){media.createAVPlayer().then((p)=>{this.avp=p p.url='https://example.com/song.mp3'// 设置数据源p.on('stateChange',(s)=>{if(s==='playing'){this.playing=true}if(s==='paused'){this.playing=false}})})}build(){Column({space:16}){Text(this.playing?'播放中':'已暂停').fontSize(20)Button(this.playing?'暂停':'播放').onClick(()=>{if(this.playing){this.avp?.pause()}else{this.avp?.play()}})}.padding(20)}}你会看到什么:进入页面后点「播放」,文字变「播放中」并听到声音;点「暂停」停止。状态由stateChange事件驱动 UI。
动手改一改:
- 把
url换成你自己的音频地址验证。 - 监听
timeUpdate事件,做一个进度条。 - 在
aboutToDisappear里this.avp?.release(),避免资源泄漏。
写在最后
AVPlayer 的套路:建播放器 → 绑 surfaceId → 设 url → 监听进度 → 控制播放。画面靠XComponent出,控制靠play/pause/seek。
音频播放更简单——不需要XComponent,直接createAVPlayer设 url 播放即可。做音乐 app 的话,把视频那套 surface 部分去掉就行。