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.播放录音流程(创建音频渲染器)
状态图
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.封装类的完整代码
(三连获取源码)