HarmonyOS7 音视频播放:AVPlayer 实战

文章目录

前言

做个能播放音视频的 app,听起来高大上,其实 HarmonyOS 已经把最难的编解码封装好了,你只要学会 AVPlayer 这个播放器对象怎么用就行。

这篇文章我带你实现一个"播放/暂停/进度"俱全的本地视频播放器。网络视频套路一样,只是地址不同。

AVPlayer 是什么

AVPlayer 是系统提供的多媒体播放器,负责"拿到资源 → 解码 → 输出到界面"。你不用懂编解码,只要:设置数据源、准备、播放、控制。

代码实现

typescript 复制代码
import { media } from '@kit.MediaKit'

let player: media.AVPlayer

async function initPlayer(surfaceId: string, url: string) {
  player = await media.createAVPlayer()
  player.url = url                       // 设置播放地址
  player.surfaceId = surfaceId           // 绑定到 XComponent 的渲染表面
}

要点:

  • createAVPlayer() 异步创建播放器。
  • player.url:本地或网络媒体地址。
  • player.surfaceId:播放画面要"贴"在哪个渲染表面上,这个表面由 XComponent 提供(见下)。

画面载体:XComponent

视频画面不能直接用普通组件显示,得用 XComponent 提供一块"原生渲染表面":

核心代码

typescript 复制代码
@Local surfaceId: string = ''

build() {
  Column() {
    XComponent({
      id: 'video',
      type: XComponentType.SURFACE,
      controller: this.xcCtrl
    })
    .onLoad((surfaceId: string) => {
      this.surfaceId = surfaceId        // 拿到表面 id
    })
    .width('100%')
    .height(240)
  }
}
  • XComponentonLoad 回调会给你一个 surfaceId,把它存起来传给 player.surfaceId,画面就出来了。
  • 必须先有 surfaceId,才能初始化播放器------所以初始化要等 onLoad 之后。

播放控制

播放器有几个核心状态,控制就围绕它们:

完整示例

typescript 复制代码
function play() { player.play() }       // 播放
function pause() { player.pause() }     // 暂停
function seekTo(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 事件:持续回调当前时间和总时长,用来更新进度条。

完整播放器骨架

typescript 复制代码
@Entry
@ComponentV2
struct VideoPlayer {
  @Local surfaceId: string = ''
  @Local progress: number = 0
  @Local playing: boolean = false
  private xcCtrl: XComponentController = new XComponentController()
  private player?: media.AVPlayer

  build() {
    Column() {
      XComponent({ id: 'v', type: XComponentType.SURFACE, controller: this.xcCtrl })
        .onLoad(async (id) => {
          this.surfaceId = id
          this.player = await media.createAVPlayer()
          this.player.url = 'file:///data/storage/el2/base/haps/entry/files/demo.mp4'
          this.player.surfaceId = id
          this.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 播放一段网络音频,带播放/暂停控制。

代码解析

typescript 复制代码
// AVPlayer 播放网络音频
import { media } from '@kit.MediaKit'

@Entry
@Component
struct AudioPlayer {
  private avp?: media.AVPlayer
  @State playing: boolean = false

  aboutToAppear() {
    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 事件,做一个进度条。
  • aboutToDisappearthis.avp?.release(),避免资源泄漏。

写在最后

AVPlayer 的套路:建播放器 → 绑 surfaceId → 设 url → 监听进度 → 控制播放 。画面靠 XComponent 出,控制靠 play/pause/seek

音频播放更简单------不需要 XComponent,直接 createAVPlayer 设 url 播放即可。做音乐 app 的话,把视频那套 surface 部分去掉就行。

相关推荐
做萤石二次开发的哈哈5 小时前
萤石开放平台如何拉取 RTC 房间成员列表?
音视频·萤石开放平台
离离原上草776 小时前
Pavo AI Agent 源码深度解析:从自然语言故事到视频分镜的 Multi-Agent 工程实践
人工智能·音视频
YWamy8 小时前
播放器类音视频 SDK 选型指南:主流产品对比与适配建议
音视频
大师兄66689 小时前
HarmonyOS7 手势系统:Tap/LongPress/Pan 组合拳
手势·longpress·harmonyos7
weixin_446260859 小时前
HumanForge:基于多智能体伪造推理的以人为中心深度伪造视频基准
人工智能·音视频
美狐美颜SDK开放平台9 小时前
从RTC到AI美颜:直播APP开发中的直播美颜SDK技术架构解析
人工智能·音视频·实时音视频·美颜sdk·视频美颜sdk·美颜api
潜创微科技9 小时前
一根网线传 4K60:基于 IT9205 的网线延长方案,把 HDMI 送到 100 米外
音视频
蓝田~10 小时前
AI 图片与视频处理 — 从原理到实践
网络·人工智能·音视频
乐橙开放平台12 小时前
巡店系统笔记:乐橙 listDeviceDetailsByPage 台账 + bindDeviceLive 辅码流最小闭环
网络·笔记·物联网·自动化·音视频·智能家居