HarmonyOS中如何实现录音

1.申请录音权限

requestPermissions() {
  permissionManager.requestPermissions(['ohos.permission.MICROPHONE'])
}

2.录音的准备工作

需要配置的参数:

audioCapturer: audio.AudioCapturer | null = null
// ---- 音频采集器参数,从文档中 CV 即可 ----
// 如果项目中对参数有其他要求,再按需调整参数
// 数据流配置:音频渲染器和音频采集器,数据流的格式需要一致
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 // 编码格式
};
// 音频采集器配置
audioCapturerInfo: audio.AudioCapturerInfo = {
  source: audio.SourceType.SOURCE_TYPE_MIC, // 麦克风
  capturerFlags: 0  // 采集器标识
};
audioCapturerOptions: audio.AudioCapturerOptions = {
  streamInfo: this.audioStreamInfo, // 音频流配置信息
  capturerInfo: this.audioCapturerInfo  // 音频采集器配置信息
};
// 音频渲染器配置
audioRendererInfo: audio.AudioRendererInfo = {
  // usage: audio.StreamUsage.STREAM_USAGE_VOICE_COMMUNICATION, // 听筒
  usage: audio.StreamUsage.STREAM_USAGE_MOVIE, // MOVIE/MUSIC 外放喇叭,MOVIE 播放会相对流畅
  rendererFlags: 0 // 渲染器标识
}
audioRenderOptions: audio.AudioRendererOptions = {
  streamInfo: this.audioStreamInfo, // 音频流配置信息
  rendererInfo: this.audioRendererInfo // 音频渲染器配置
};
// ---- 音频采集器参数,从文档中 CV 即可 ----
// 录音文件
filePath: string = ''

3.开始录音流程

1.准备一个新文件用于存储采集的音频数据流

// 1. 准备一个新的文件,用于存放采集的音频数据流(模拟器能测试)
const context = getContext()
// 找到 files 文件夹的路径(files 是应用可读可写的持久化文件夹)
const filePath = context.filesDir + '/' + Date.now() + '.wav'
// 保存路径变全局,用于播放
this.filePath = filePath
// 创建并打开文件,设置打开模式为可读可写
const file = fileIo.openSync(filePath, fileIo.OpenMode.CREATE | fileIo.OpenMode.READ_WRITE)
promptAction.showToast({ message: '文件创建并打开成功:' + file.fd })

2.创建音频采集器(模拟器不支持)

// 2. 创建音频采集器(模拟器不支持)
const audioCapturer = await audio.createAudioCapturer(this.audioCapturerOptions)
// 保存成全局变量,方便其他地方调用
this.audioCapturer = audioCapturer

// 用于存放 offset 偏移量,避免数据覆盖
let bufferSize: number = 0;

3.调用on(‘readData’)方法,订阅监听音频数据读入回调

// 3. 调用on('readData')方法,订阅监听音频数据读入回调
audioCapturer.on('readData', (arrayBuffer) => {
  // 往打开的文件写入数据流,通过指定 offset 偏移量,在不覆盖源数据的基础上,追加新采集的音频数据
  fileIo.writeSync(file.fd, arrayBuffer, { length: arrayBuffer.byteLength, offset: bufferSize })
  // 偏移量累加,避免数据写入时覆盖
  bufferSize += arrayBuffer.byteLength
  // 测试代码用的,界面中输出数据流大小
  promptAction.showToast({ message: formatByteLength(bufferSize) })
});

4.调用开始采集

audioCapturer.start()

5.停止采集(使用状态进行判断)

// 运行中可以停止录音,如果已经 release 释放了资源,再调用停止录音会报错 system error
if (audio.AudioState.STATE_RUNNING === this.audioCapturer?.state) {
  await this.audioCapturer?.stop()
  promptAction.showToast({ message: '停止录音成功' })
}

6.释放资源

// 多种状态判断,建议使用 includes 方式
  if ([audio.AudioState.STATE_STOPPED,
    audio.AudioState.STATE_PREPARED].includes(this.audioCapturer?.state)) {
    await this.audioCapturer?.release()
    promptAction.showToast({ message: '释放资源成功' })
  }
})

4.播放录音流程(创建音频渲染器)

状态图

img

1.调用已经准备好的音频文件

// 1. 准备一个新的文件,用于存放采集的音频数据流(模拟器能测试)
const file = fileIo.openSync(this.filePath)
const stat = fileIo.statSync(file.fd)

2.创建音频渲染器

// 1. 创建音频渲染器
const audioRenderer = await audio.createAudioRenderer(this.audioRenderOptions)
//用于判断数组流的大小
    let bufferSize: number = 0;

3.往音频渲染器(播放器)写入数据,播放声音

// 2. 往音频渲染器(播放器)写入数据,让声音播放
audioRenderer.on('writeData', async (arrayBuffer) => {
  // 读取文件信息,写入音频采集器
  fileIo.readSync(file.fd, arrayBuffer, { length: arrayBuffer.byteLength, offset: bufferSize })
  // 控制偏移量
  bufferSize += arrayBuffer.byteLength
  // 如果超过文件大小,停止播放
  if (bufferSize >= stat.size) {
    await audioRenderer.stop() // 停止播放
    audioRenderer.release() // 释放硬件,释放资源
    fileIo.close(file.fd) // 关闭打开的文件,释放资源
  }
  // 测试代码用的,界面中输出数据流大小
  promptAction.showToast({ message: formatByteLength(bufferSize) })
})

4.启动音频渲染器

// 3. 启动音频渲染器
audioRenderer.start()

5.封装类的完整代码

(三连获取源码)

  • 10
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值