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

  }
}
相关推荐
星之卡比*4 分钟前
前端知识点---库和包的概念
前端·harmonyos·鸿蒙
灵感__idea6 分钟前
Vuejs技术内幕:数据响应式之3.x版
前端·vue.js·源码阅读
烛阴10 分钟前
JavaScript 构造器进阶:掌握 “new” 的底层原理,写出更优雅的代码!
前端·javascript
Alan-Xia11 分钟前
使用jest测试用例之入门篇
前端·javascript·学习·测试用例
浪遏12 分钟前
面试官😏 :文本太长,超出部分用省略号 ,怎么搞?我:🤡
前端·面试
昕er14 分钟前
CefSharp 文件下载和保存功能-监听前端事件
前端
@PHARAOH19 分钟前
WHAT - Tree Shaking 的前提是 ES Module
前端·webpack·ecmascript
鱼樱前端26 分钟前
📚 Vue Router 4 核心知识点(Vue3技术栈)面试指南
前端·javascript·vue.js
食指Shaye32 分钟前
Chrome 中清理缓存的方法
前端·chrome·缓存
午后书香43 分钟前
一天三场面试,口干舌燥要晕倒(二)
前端·javascript·面试