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

相关推荐
benbenAItalk5 小时前
数字人口播视频的批量生产实践:素材规范、任务编排与质量验收
java·前端·音视频
AI创界者8 小时前
前沿多模态大模型 MiniMax-H3无审查 本地部署与深度实测指南
人工智能·aigc·音视频
世岩清上13 小时前
展厅数字内容同质化严重,怎样打造专属叙事风格?
大数据·前端·javascript·人工智能·html·音视频·展厅改造
LCG元14 小时前
STM32F407 I2S驱动WM8978音频播放实战:PLLI2S时钟整定、DMA双缓冲防爆音与WAV采样率实测
stm32·嵌入式硬件·音视频
jbk331115 小时前
PixiuCut「视频批量分割」支持智能镜头分割、按时长、按数量分割,可定义最小时长避免无效片段等多可选参数可设置
人工智能·音视频·剪辑软件·剪映自动化软件
投票竞赛15 小时前
作品投票版权注意事项,线上评选上传图片视频须知
python·音视频
byte轻骑兵18 小时前
【AVDTP】规范精讲[13]: 吃透内容保护机制,打通蓝牙音视频版权加密全流程
人工智能·音视频·avrcp·蓝牙耳机·蓝牙音频
世岩清上20 小时前
文旅历史展厅纪录片式视频,怎样弱化说教感提升自主观看欲?
人工智能·音视频·宣传片·展厅改造
言乐620 小时前
Python加速器2视频网页加速器
前端·javascript·css·python·音视频