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)
  }
}
  • XComponent 的 onLoad 回调会给你一个 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 事件,做一个进度条。
  • 在 aboutToDisappear 里 this.avp?.release(),避免资源泄漏。

写在最后

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

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

相关推荐
每天死循环8 分钟前
ComfyUI MiniMax H3文生视频(t2v)提示词教程:四段式写法+5秒768p实测(附模板和参数)
音视频·文生视频·comfyui·ai视频·minimax
企业数字化笔记2 小时前
视频像素分割怎么选?HSV 阈值、传统掩膜、语义分割和实例分割的效果与代价
opencv·音视频
youdexiang2 小时前
AI 生成会议纪要好用吗?多款 APP 功能分析
java·人工智能·音视频
AI创界者3 小时前
【开源实战】MiniMax-H3 本地离线高自由度 ComfyUI 工作流搭建指南(含规则松绑与提示词映射)
人工智能·aigc·音视频
hai3152475433 小时前
文本矩阵化拆解与视频矩阵化构建
线性代数·矩阵·音视频
昨日之日20063 小时前
Visual Enhancer:一键让模糊照片视频变清晰,升分辨率、插帧、转HDR,一键搞定素材修复
计算机视觉·音视频
李子红了时3 小时前
阿狸舞台APP(安卓端手机EncFS解密+压缩包解压+视频播放)
android·音视频
程序猿老A4 小时前
云服务器怎么配置视频存储?
运维·服务器·音视频
开开心心就好4 小时前
以图搜图找重复图片,本地工具离线就能用
javascript·智能手机·ffmpeg·c#·ocr·word·音视频
企业数字化笔记4 小时前
视频局部合成怎么做得自然?掩膜修复、边缘羽化、时序稳定与背景替换
java·javascript·音视频