手把手教你使用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 })

  }
}
相关推荐
Csvn7 小时前
WASM
前端
修己xj8 小时前
我用 AI 给自己写了一个 Markdown 编辑器,然后把它开源了
前端
行者-全栈开发9 小时前
【鸿蒙心迹】三方库移植(二)——CMake 交叉编译与符号冲突排查实录(HarmonyOS 7.x)
harmonyos·cmake·交叉编译·三方库移植·ohos·符号冲突
FRing039 小时前
vue2干货总结2(v-bind、v-for、v-model、指令修饰符、v-bind操作class和style)
开发语言·前端·vue.js·vue2
幸运小猿9 小时前
模拟慢上传-处理超时重试image 丢失线上问题
前端·javascript·html
锋行天下10 小时前
Langgraph-cli 本地构建失败,改用服务器docker构建的流程
人工智能·前端框架·全栈
梦想不只是梦与想10 小时前
鸿蒙三方库源码调试
harmonyos·断点调试·三方源码调试
moshuying11 小时前
网购能买Token了!
前端
h_654321011 小时前
echarts实现柱状图加一条横线
前端·echarts
风骏时光牛马11 小时前
生成一个后端标题,只需要一个标题,不需要其他的任何文本。
前端