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 部分去掉就行。

相关推荐
淡淡的香烟1 天前
Android Camera开发详解
android·音视频
笨笨饿1 天前
#109_BK7258 蓝牙 A2DP 音频数据通路深度解析
python·stm32·单片机·mcu·物联网·编辑器·音视频
≮傷£≯√1 天前
图片合并成视频 img2video ffmpeg
ffmpeg·音视频
A13345551 天前
视频特效字幕怎么翻译?保姆级AI字幕与外挂字幕教程
人工智能·音视频
ViiTor_AI2 天前
从去字幕到 AI 配音:完整视频本地化流程
人工智能·音视频
明德扬2 天前
多路MIPI摄像头如何同步聚合?一文看懂FPGA视频汇聚方案
fpga开发·音视频
折枝吖2 天前
音视频开发-PCM 原理与 AI 模块实战
音视频·pcm
HySpark2 天前
熙瑾·会悟 ASR 实战:Qwen-ASR 漏字导致转写不完整,如何从音频分段到二次校验解决?
音视频·熙瑾会悟
大鹅办公2 天前
酷狗音乐怎么转换MP3格式?4种方法亲测对比+避坑指南(附FFmpeg命令行教程)
ffmpeg·音视频·音频格式
小妖同学学AI2 天前
AI视频生成难在提示词?这个Claude插件让Seedance 2.0效率翻倍,附超全示例!
人工智能·开源·github·音视频