使用AVPlayer播放音频文件的几种方式实现

使用AVPlayer接口播放音频,应用只需要提供流媒体来源,不负责数据解析和解码就可达成播放效果,可以播放在线音频地址,本地音频文件,沙箱路径音频文件等。

HarmonyOS
2024-05-28 20:12:59
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
退休的程序员

1. 创建实例createAVPlayer(),AVPlayer初始化idle状态。

2. 设置业务需要的监听事件,搭配全流程场景使用。支持的监听事件。

3. 设置资源:设置属性url,AVPlayer进入initialized状态。

4. 准备播放:调用prepare(),AVPlayer进入prepared状态。

5. 音频播控:播放play(),暂停pause(),跳转seek(),停止stop() 等操作。

6. 更换资源:调用reset()重置资源,AVPlayer重新进入idle状态,允许更换资源url。

7. 退出播放:调用release()销毁实例,AVPlayer进入released状态,退出播放。

核心代码如下:

import media from '@ohos.multimedia.media'; 
import fs from '@ohos.file.fs'; 
import common from '@ohos.app.ability.common'; 
import { BusinessError } from '@ohos.base'; 
 
@Entry 
@Component 
struct Index { 
  @State message: string = 'Hello World'; 
  private avPlayer: media.AVPlayer | null = null; 
  private count: number = 0; 
  private isSeek: boolean = true; // 用于区分模式是否支持seek操作 
  private fileSize: number = -1; 
  private fd: number = 0; 
 
  async aboutToAppear(): Promise<void> { 
    // 创建avPlayer实例对象 
    this.avPlayer = await media.createAVPlayer(); 
    console.log('666660' + this.avPlayer.state) 
    // 创建状态机变化回调函数 
    this.setAVPlayerCallback(this.avPlayer); 
    if (this.avPlayer != null) { 
      // this.avPlayerFdSrcDemo(); 
      this.avPlayerUrlDemo(); 
    } 
  } 
 
  // 以下demo为使用资源管理接口获取打包在HAP内的媒体资源文件并通过fdSrc属性进行播放示例 
  async avPlayerFdSrcDemo() { 
    // 通过UIAbilityContext的resourceManager成员的getRawFd接口获取媒体资源播放地址 
    // 返回类型为{fd,offset,length},fd为HAP包fd地址,offset为媒体资源偏移量,length为播放长度 
    let context = getContext(this) as common.UIAbilityContext; 
    let fileDescriptor = await context.resourceManager.getRawFd('123.mp3'); 
    let avFileDescriptor: media.AVFileDescriptor = 
      { fd: fileDescriptor.fd, offset: fileDescriptor.offset, length: fileDescriptor.length }; 
    this.isSeek = false; // 支持seek操作 
    // 为fdSrc赋值触发initialized状态机上报 
    if (this.avPlayer != null) { 
      this.avPlayer.fdSrc = avFileDescriptor; 
      console.log('666661' + this.avPlayer.state) 
      console.log('666662' + this.avPlayer.state) 
    } 
  } 
 
  async avPlayerLiveDemo() { 
    // 创建avPlayer实例对象 
    this.avPlayer = await media.createAVPlayer(); 
    // 创建状态机变化回调函数 
    this.setAVPlayerCallback(this.avPlayer); 
    this.isSeek = false; // 不支持seek操作 
    this.avPlayer.url = 'https://www.cambridgeenglish.org/images/153149-movers-sample-listening-test-vol2.mp3' 
  } 
 
  async avPlayerUrlDemo() { 
    // 创建avPlayer实例对象 
    // 创建状态机变化回调函数 
    const resourceManager = getContext(this).resourceManager 
    const imageArray = await resourceManager.getMediaContent($r("app.media.dx")); 
    let fdPath = 'fd://'; 
    let path: string = getContext().filesDir + "/01.mp3"; 
    console.log("yuv_path is:" + path); 
    let file = fs.openSync(path, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); 
    fs.write(file.fd, imageArray.buffer).then(async (writeLen) => { 
      console.info("write data to file succeed and size is:" + writeLen); 
      fs.closeSync(file); 
      let file1 = await fs.open(path); 
      fdPath = fdPath + '' + file1.fd; 
      if (this.avPlayer != null) { 
        this.avPlayer.url = fdPath; 
        console.log('666661' + this.avPlayer.state) 
      } 
    }).catch((err: BusinessError) => { 
      console.info("write data to file failed with error message: " + err.message + ", error code: " + err.code); 
    }); 
  } 
 
  setAVPlayerCallback(avPlayer: media.AVPlayer) { 
    // seek操作结果回调函数 
    avPlayer.on('seekDone', (seekDoneTime: number) => { 
      console.info(`AVPlayer seek succeeded, seek time is ${seekDoneTime}`); 
    }) 
    // error回调监听函数,当avPlayer在操作过程中出现错误时调用 reset接口触发重置流程 
    avPlayer.on('error', (err: BusinessError) => { 
      console.error(`Invoke avPlayer failed, code is ${err.code}, message is ${err.message}`); 
      avPlayer.reset(); // 调用reset重置资源,触发idle状态 
    }) 
    // 状态机变化回调函数 
    avPlayer.on('stateChange', async (state: string, reason: media.StateChangeReason) => { 
      switch (state) { 
        case 'idle': // 成功调用reset接口后触发该状态机上报 
          console.info('AVPlayer state idle called.'); 
        // avPlayer.release(); // 调用release接口销毁实例对象 
          break; 
        case 'initialized': // avplayer 设置播放源后触发该状态上报 
          console.info('666AVPlayer state initialized called.666666666666666'); 
          avPlayer.prepare(); 
          break; 
        case 'prepared': // prepare调用成功后上报该状态机 
          console.info('AVPlayer state prepared called.'); 
        // avPlayer.play(); // 调用播放接口开始播放 
          break; 
        case 'playing': // play成功调用后触发该状态机上报 
          console.info('AVPlayer state playing called.'); 
          break; 
        case 'paused': // pause成功调用后触发该状态机上报 
          console.info('AVPlayer state paused called.'); 
        // avPlayer.play(); // 再次播放接口开始播放 
          break; 
        case 'completed': // 播放结束后触发该状态机上报 
          console.info('AVPlayer state completed called.'); 
          avPlayer.stop(); //调用播放结束接口 
          break; 
        case 'stopped': // stop接口成功调用后触发该状态机上报 
          console.info('AVPlayer state stopped called.'); 
        // avPlayer.reset(); // 调用reset接口初始化avplayer状态 
          break; 
        case 'released': 
          console.info('AVPlayer state released called.'); 
          break; 
        default: 
          console.info('AVPlayer state unknown called.'); 
          break; 
      } 
    }) 
  } 
 
  build() { 
    Row() { 
      Column() { 
        Text(this.message) 
          .fontSize(50) 
          .fontWeight(FontWeight.Bold) 
        Button('play') 
          .margin(10).onClick(async (event: ClickEvent) => { 
          if (this.avPlayer != null) { 
            console.log('6666677' + this.avPlayer.state) 
            this.avPlayer.play(); 
          } 
        }) 
        Button('reset').onClick(async (event: ClickEvent) => { 
          if (this.avPlayer != null) { 
            await this.avPlayer.reset(); 
            let context = getContext(this) as common.UIAbilityContext; 
            let fileDescriptor = await context.resourceManager.getRawFd('稻香.mp3'); 
            let avFileDescriptor1: media.AVFileDescriptor = 
              { fd: fileDescriptor.fd, offset: fileDescriptor.offset, length: fileDescriptor.length }; 
            this.isSeek = false; // 支持seek操作 
            // 为fdSrc赋值触发initialized状态机上报 
            this.avPlayer.fdSrc = avFileDescriptor1; 
          } 
        }) 
      } 
      .width('100%') 
    } 
    .height('100%') 
  } 
}

实现效果

avplayer功能较完善的音频、视频播放 API,集成了流媒体和本地资源解析、媒体资源解封装、音频解码和音频输出功能。可以用于直接播放mp3、m4a等格式的音频文件。

分享
微博
QQ
微信
回复
2024-05-29 21:01:57
相关问题
HarmonyOS 播放本地音频文件
225浏览 • 1回复 待解决
HarmonyOS实现后台播放音频
488浏览 • 1回复 待解决
AVPlayer实现音频播放(c++侧)
1343浏览 • 1回复 待解决
OH _Audio播放音频问题
2145浏览 • 1回复 待解决
AVplayer开发音频播放功能
1217浏览 • 1回复 待解决
基于AVPlayer音频后台播放
593浏览 • 1回复 待解决
AudioCapturer录音+AudioRenderer播放音频
1300浏览 • 1回复 待解决
怎么读取本地音频文件列表?
6337浏览 • 1回复 待解决
鸿蒙Dev远程真机能否播放音频
5502浏览 • 1回复 待解决
使用AVPlayer实现视频播放
1274浏览 • 1回复 待解决
AVPlayer实现视频播放
1033浏览 • 1回复 待解决
鸿蒙如何将音频文件转成文本
4470浏览 • 1回复 待解决