手把手教你使用AVRecorder完成鸿蒙录音

前言

录音功能是手机常见的功能,在HarmonyOS中应该如何实现这一功能呢?

获取权限

向系统权限

由于鸿蒙操作系统的安全性的问题首先需要在module.json5中配置允许使用麦克风功能。

没啥好说的直接上代码

js 复制代码
"requestPermissions": [
      {
        "name":"ohos.permission.MICROPHONE",
        "usedScene": {},
        "reason":"$string:EntryAbility_desc"
      }
    ],

向用户请求

首次请求

由于上一步操作只是向系统请求麦克风权限,下一步还需要向用户也就是手机哦持有者申请权限。

核心API 使用到了abilityAccessCtrl

js 复制代码
import { abilityAccessCtrl } from '@kit.AbilityKit'
@Entry
@Component
struct myTest {
  async aboutToAppear() {
    // 向用户发起麦克风的授权提示
    let mgr = abilityAccessCtrl.createAtManager()
    //  利用mgr对象向用户发起麦克风的授权
    let result = await mgr.requestPermissionsFromUser(getContext(), ['ohos.permission.MICROPHONE'])
  }

  build() {
    Column() {

    }
    .height('100%')
    .width('100%')
    .backgroundColor(Color.Pink)

  }
}

res打印能发现当选择了允许和不允许时authResults分别对应0和-1,dialogShownResults分别对应true和false

二次请求

当用户选择不允许时,可以通过直接跳转want来管理开启麦克风的权限

主要使用Want API 来完成,Want是对象间信息传递的载体, 可以用于应用组件间的信息传递。

首先配置Want的参数

js 复制代码
const want: Want = {
  bundleName: 'com.huawei.hmos.settings',
  abilityName: 'com.huawei.hmos.settings.MainAbility',
  uri: 'application_info_entry',
  parameters: {
    // 可以在AppScope下的app.json5中对应的bundleName查看
    pushParams: '改成自己的包名'
  }
}

利用Want配合第一次请求的参数判断完成直接跳转到系统权限的设置界面

js 复制代码
let ctx = getContext() as common.UIAbilityContext
      ctx.startAbility(want)

获取录音文件

准备文件

我们需要提前准备好一个文件用来存放录音的信息

使用了fs.openSync来创建和打开文件, getContext().filesDir 用来获取当前上下文的路径,使用时间戳获得唯一标识符作为文件名字。fd代表着文件的操作符,后续对文件的操作只需调用fd即可。

js 复制代码
const filePath = getContext().filesDir + '/' + Date.now() + '.m4a'
const file = fs.openSync(filePath, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE)
const fd = file.fd 

配置录音对象

配置一些录音的基本信息,从官方文档参考即可

js 复制代码
const config: media.AVRecorderConfig = {
  audioSourceType: media.AudioSourceType.AUDIO_SOURCE_TYPE_MIC,  //音频采集源为麦克风
  profile: {
    audioBitrate: 100000, // 音频比特率
    audioChannels: 1, // 音频声道数
    audioCodec: media.CodecMimeType.AUDIO_AAC, // 音频编码格式,当前只支持aac
    audioSampleRate: 48000, // 音频采样率
    fileFormat: media.ContainerFormatType.CFT_MPEG_4A, // 封装格式,当前只支持m4a
  },
  url: `fd://${file.fd}`  //第一步中的文件地址
}

开始录音与结束录音

首先实例化AVRecorder,调用AVRecorder上自带的方法即可。使用完毕记得销毁对象。

js 复制代码
// 创建录音对象
const avRecorder = await media.createAVRecorder()
// 设置录制参数
await avRecorder.prepare(config)  
// 开启录音
await avRecorder.start() 
// 停止录制
await avRecorder.stop()
// 销毁实例,退出录制。
await avRecorder.release()

播放录音

使用了avPlayer创建的实力,调用方法对stateChange进行监听,当其处于prepare状态时,使用.play进行播放。打开之前存好的录音的文件地址,进行播放即可。

js 复制代码
          const file = fs.openSync(this.filePath, fs.OpenMode.READ_ONLY) //以只读方式打开录音文件
          // 创建播放对象 AVPlayer
          const avPlayer = await media.createAVPlayer()
          // 注册stateChange监听
          avPlayer.on('stateChange', (state) => {
            if (state == 'initialized') {
              avPlayer.prepare()
            }
            if (state == 'prepared') {
              avPlayer.play()
            }
          })
          // 赋值播放源
          avPlayer.url = `fd://${file.fd}`

完整代码参考

js 复制代码
import { abilityAccessCtrl, common, Want } from '@kit.AbilityKit'
import fs from '@ohos.file.fs';
import { media } from '@kit.MediaKit';

@Entry
@Component
struct myTest {
  @StorageProp('topHeight') topHeight: number = 0
  avRecorder: media.AVRecorder = Object()  // 初始化空对象

  async aboutToAppear() {
    let mgr = abilityAccessCtrl.createAtManager()
    let result = await mgr.requestPermissionsFromUser(getContext(), ['ohos.permission.MICROPHONE'])
    if (result.authResults[0] == -1) {

      const want: Want = {
        bundleName: 'com.huawei.hmos.settings',
        abilityName: 'com.huawei.hmos.settings.MainAbility', 
        uri: 'application_info_entry',
        parameters: {

          pushParams: 'com.itcast.interview_bjhm4App' 
        }
      }


      let ctx = getContext() as common.UIAbilityContext
      ctx.startAbility(want)
    }
  }

  build() {
    Column() {

      Button('开始录制').onClick(async () => {

        let filePath = getContext().filesDir + '/' + Date.now() + '.m4a'

        let file = fs.openSync(filePath, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE)

        const config: media.AVRecorderConfig = {
          audioSourceType: media.AudioSourceType.AUDIO_SOURCE_TYPE_MIC, //音频采集源为麦克风
          profile: {
            audioBitrate: 100000, // 音频比特率
            audioChannels: 1, // 音频声道数
            audioCodec: media.CodecMimeType.AUDIO_AAC, // 音频编码格式,当前只支持aac
            audioSampleRate: 48000, // 音频采样率
            fileFormat: media.ContainerFormatType.CFT_MPEG_4A, 
          },
          url: `fd://${file.fd}` 
        }

        const avRecorder = await media.createAVRecorder()
        this.avRecorder = avRecorder

        await avRecorder.prepare(config)
        await avRecorder.start()
        AlertDialog.show({ message: JSON.stringify('录音开始') })
      })

      Button('停止录制').onClick(async () => {
        await this.avRecorder.stop() //停止录音
        await this.avRecorder.release() //销毁和释放录音对象
      })
      Button('播放').onClick(async () => {
        const avPlayer = await media.createAVPlayer()
        avPlayer.on('stateChange', (state) => {
          if (state == 'initialized') {
            avPlayer.prepare()
          }
          if (state == 'prepared') {
            avPlayer.play()
          }
        })
        //   3. 设置播放源 fd://句柄
        const file = fs.openSync(item, fs.OpenMode.READ_ONLY)
        avPlayer.url = `fd://${file.fd}`
      })

    }
    .height('100%')
    .width('100%')
    .padding({ top: this.topHeight })

  }
}
相关推荐
一只大侠的侠7 小时前
Flutter开源鸿蒙跨平台训练营 Day 10特惠推荐数据的获取与渲染
flutter·开源·harmonyos
崔庆才丨静觅9 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby606110 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了10 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅10 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅11 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅11 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment11 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅11 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊12 小时前
jwt介绍
前端