【鸿蒙开发】HarmonyOS Next中录音与音频渲染

一、录音实现

使用AudioCapturer录制音频涉及到AudioCapturer实例的创建、音频采集参数的配置、采集的开始与停止、资源的释放等。建议搭配AudioCapturer的API说明阅读。
实现步骤

●在module.json5中配置权限

{
  "module": {
  ...
    "requestPermissions": [
    ...
        // 麦克风
        {
          "name": "ohos.permission.MICROPHONE",
          "reason": '$string:permission_reason_microphone',
          "usedScene": {}
        },
    ]
  }
}

●向用户申请调用麦克风权限

/**
 * 动态申请授权(首次弹窗申请)
 * @param permissions 权限列表
 * @returns 返回授权结果,授权成功为 Promise.resolve(), 拒绝授权为 Promise.reject()
 */
async requestPermissions(permissions: Permissions[]) {
  // 1. 创建应用权限管理器
  const atManager = abilityAccessCtrl.createAtManager()
  // 2. 向用户申请 user_grant 权限(温馨提示:首次申请时会弹窗,后续申请则不会再出现弹窗)
  const requestResult = await atManager.requestPermissionsFromUser(
    getContext(), // 应用上下文
    permissions   // 参数:权限列表(数组)
  )
  // 通过 every 检查权限是否都成功授权
  const isAuth = requestResult.authResults.every(item => item === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED)
  // Promise.resolve()   返回 Promise 成功,await 后续代码,正常执行
  // Promise.reject()    返回 Promise 错误,await 后续代码,不被执行,Promise.reject() 的结果可被 catch 捕获
  return isAuth === true ? Promise.resolve(true) : Promise.reject(false)
}
/**
 * 打开系统设置的权限管理页(处理授权结果)
 */
openPermissionSettingsPage() {
  // 1. 获取应用上下文,并通过 as 断言收窄类型为 UIAbilityContext,否则 context 默认类型无法调用 startAbility 方法
  const context = getContext() as common.UIAbilityContext
  // 2. 获取 bundle 包信息
  const bundleInfo = bundleManager.getBundleInfoForSelfSync(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION)
  // 3. 通过 startAbility 打开 系统设置 页
  context.startAbility({
    bundleName: 'com.huawei.hmos.settings', // 固定写法CV:设置页的包名
    abilityName: 'com.huawei.hmos.settings.MainAbility', // 固定写法CV:设置页的 ability 名
    uri: 'application_info_entry', // 固定写法CV:打开 设置->应用和元服务
    parameters: {
      // 打开指定应用(包)的详情页面
      // pushParams: 'com.itheima.hm_guardian'
      // 应用包名可通过 bundleManager 动态获取
      pushParams: bundleInfo.name
    }

  })
}

// 初始化权限
async requestPermissions() {
  // 申请权限
  try {
    // 申请权限
    await this.requestPermissions(["ohos.permission.MICROPHONE"])
  } catch {
    // 未开启弹窗提示
    promptAction.showDialog({
      alignment: DialogAlignment.Center,
      title: '温馨提示',
      message: '录音功能需要获取权限,请在系统设置中打开麦克风开关',
      buttons: [
        { text: '取消', color: $r('app.color.font_sub') },
        { text: '立即开启', color: $r('app.color.brand') }
      ]
    })
      .then((res) => {
        // 打开设置页
        if (res.index === 1) {
          this.openPermissionSettingsPage()
        }
      })
  }
}

●创建/获取音频采集器
关键API audio.createAudioCapturer

// 音频采集器实例
private audioCapturer: audio.AudioCapturer | null = null
// 音频流配置
private audioStreamInfo: audio.AudioStreamInfo = {
  samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_48000, // 采样率
  channels: audio.AudioChannel.CHANNEL_2, // 通道
  sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE, // 采样格式
  encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW // 编码格式
};
// 音频采集器配置
private audioCapturerInfo: audio.AudioCapturerInfo = {
    source: audio.SourceType.SOURCE_TYPE_MIC, //音源类型:Mic音频源
    capturerFlags: 0//音频采集器标志。0代表普通音频采集器,1代表低时延音频采集器。
};
//创建/获取音频采集器
async getAudioCapturer() {
  //如果有的话直接返回,避免占用系统资源
  if (this.audioCapturer) {
    return this.audioCapturer
  }
  //关键API  audio.createAudioCapturer
  this.audioCapturer = await audio.createAudioCapturer({
    streamInfo: this.audioStreamInfo,
    capturerInfo: this.audioCapturerInfo
  })
  return this.audioCapturer
}

● 开始录音

/**
 * 开始录音采集
 * @param filePath 录音存放路径
 */
async startRecorder(filePath: string) {
  //  1) 打开文件,注意设置模式
  const file = fileIo.openSync(filePath, fileIo.OpenMode.CREATE|fileIo.OpenMode.READ_WRITE)
  // 1. 创建音频采集器
  const audioCapturer = await this.getAudioCapturer()
  // 2. 订阅(读取音频采集器的数据流,写入到打开的文件中)
  audioCapturer.on('readData', (buffer) => {
    //  2) 把 buffer 数据流,写入到打开的文件中
    fileIo.writeSync(file.fd, buffer)
  })
  // 3. 开始
  audioCapturer.start()
}

● 结束录音

// 结束录音采集
async stopRecorder(): Promise<AudioInfo> {
  // 获取音频采集器
  const audioCapturer = await this.getAudioCapturer()
  // 1. 停止录音
  await audioCapturer.stop()
  // 2. 释放资源和硬件占用
  audioCapturer.release()
  // 3. 释放变量,对象重新赋值为 null,可以被 垃圾回收机制 自动清理
  this.audioCapturer = null
}

结束录音函数中最后需要做音频文件和音频数据持久化,以便后续展示和渲染音频。

二、音频渲染

使用AudioRenderer播放音频涉及到AudioRenderer实例的创建、音频渲染参数的配置、渲染的开始与停止、资源的释放等。建议搭配AudioRenderer的API说明阅读。

实现步骤

●配置/获取音频渲染器
关键API audio.createAudioRenderer

// 音频渲染器实例
private audioRenderer: audio.AudioRenderer | null = null
// 音频渲染器配置
private audioRendererInfo: audio.AudioRendererInfo = {
    usage: audio.StreamUsage.STREAM_USAGE_MOVIE, // 播放类型,MOVIE 表示用喇叭播放
    rendererFlags: 0 //音频渲染器标志。0代表普通音频渲染器,1代表低时延音频渲染器
};
// 获取音频渲染器(播放器)
async getAudioRenderer() {
  if (this.audioRenderer) {
    return this.audioRenderer
  }
  this.audioRenderer = await audio.createAudioRenderer({
    streamInfo: this.audioStreamInfo,
    rendererInfo: this.audioRendererInfo
  })
  return this.audioRenderer
}

● 播放器渲染音频

/**
 * 播放
 * @param filePath 音频文件路径
 */
async startRenderer(filePath: string) {
  //  1) 根据路径打开文件,获取文件信息
  const file = fileIo.openSync(filePath)
  const stat = fileIo.statSync(file.fd)
  // 1. 获取音频渲染器(播放器)
  const audioRenderer = await this.getAudioRenderer()
  //  2) 准备累加值,用于自动停止
  let bufferSize: number = 0
  // 2. 调用on('writeData')方法,订阅监听音频数据写入回调
  audioRenderer.on('writeData', async (buffer) => {
    // 3) 把 buffer 信息写入到音频渲染器中
    fileIo.readSync(file.fd, buffer)
    // 获取文件信息,如果读取时已经超出文件大小,自动停止
    bufferSize += buffer.byteLength
    if (bufferSize >= stat.size) {
      await audioRenderer.stop() // 停止渲染器(播放器)
      audioRenderer.release() // 释放资源(硬件)
      this.audioRenderer = null // 释放变量
    }
  })
  // 3. 启动音频渲染器(播放器)
  audioRenderer.start()
}

● 停止播放录音

csharp复制代码// 停止播放录音
async stopRenderer() {
  // 获取音频渲染器(播放器)
  const audioRenderer = await this.getAudioRenderer()
  // RUNNING 和 PAUSED 状态下才能 stop,stop 后自动 release 释放资源(硬件)
  if ([audio.AudioState.STATE_RUNNING, audio.AudioState.STATE_PAUSED].includes(this.audioRenderer!.state)) {
    await audioRenderer.stop() // 停止渲染(播放)
    audioRenderer.release() // 释放资源(硬件)
    this.audioRenderer = null // 释放变量
  }
}

写在最后

有很多小伙伴不知道该从哪里开始学习鸿蒙开发技术?也不知道鸿蒙开发的知识点重点掌握的又有哪些?自学时频繁踩坑,导致浪费大量时间。结果还是一知半解。所以有一份实用的鸿蒙(HarmonyOS NEXT)全栈开发资料用来跟着学习是非常有必要的。

获取完整版高清学习资料,请点击→鸿蒙全栈开发学习资料(安全链接,请放心点击)

这份鸿蒙(HarmonyOS NEXT)资料包含了鸿蒙开发必掌握的核心知识要点,内容包含了

最新鸿蒙全栈开发学习线路在这里插入图片描述

鸿蒙HarmonyOS开发教学视频

在这里插入图片描述
在这里插入图片描述

大厂面试真题

在这里插入图片描述

在这里插入图片描述

鸿蒙OpenHarmony源码剖析

在这里插入图片描述

这份资料能帮住各位小伙伴理清自己的学习思路,更加快捷有效的掌握鸿蒙开发的各种知识。有需要的小伙伴自行领取,,先到先得~无套路领取!!

获取这份完整版高清学习资料,请点击→鸿蒙全栈开发学习资料(安全链接,请放心点击)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值