《聊天页-语音转文字》四、使用AudioCapturer开发音频录制功能指南
HarmonyOS 使用 AudioCapturer 开发音频录制功能ArkTS完整指南效果一、概述AudioCapturer是 HarmonyOS 音频框架中的音频采集器用于录制 PCMPulse Code Modulation格式的音频数据。它适合有音频开发经验的开发者实现更灵活的录制功能是语音识别、实时音频处理等场景的基础组件。核心特点录制原始 PCM 音频数据支持多种采样率、声道数、采样格式配置支持麦克风、语音识别等多种音频源提供状态机管理可控的生命周期通过回调方式实时获取音频数据与 AudioRecorder 的区别对比项AudioCapturerAudioRecorder输出格式PCM 原始数据M4A/AAC 等编码格式灵活性高可自定义处理低系统自动处理适用场景语音识别、实时音频处理普通录音、语音备忘录开发难度较高较低二、AudioCapturer 状态机AudioCapturer 有明确的状态流转机制理解状态变化对正确使用至关重要createAudioCapturer ↓ ┌──────────────┐ │ PREPARED │ ← 初始创建状态 └──────┬───────┘ │ start() ↓ ┌──────────────┐ │ RUNNING │ ← 正在录制 └──────┬───────┘ │ stop() ↓ ┌──────────────┐ │ STOPPED │ ← 已停止 └──────┬───────┘ │ start() │ release() ↓ ↓ ┌──────────┐ ┌──────────┐ │ RUNNING │ │ RELEASED │ └──────────┘ └──────────┘AudioState 枚举值状态值说明STATE_PREPARED1实例已创建准备就绪STATE_RUNNING2正在录制的运行状态STATE_STOPPED3已停止录制STATE_RELEASED4实例已释放STATE_PAUSED5已暂停仅AudioPlayer支持三、开发环境准备3.1 导入模块import{audio}fromkit.AudioKit;import{fileIoasfs}fromkit.CoreFileKit;import{BusinessError}fromkit.BasicServicesKit;import{abilityAccessCtrl,common,Permissions}fromkit.AbilityKit;3.2 权限配置当音频源为麦克风类型时SOURCE_TYPE_MIC、SOURCE_TYPE_VOICE_RECOGNITION、SOURCE_TYPE_VOICE_COMMUNICATION等需要申请麦克风权限。module.json5 配置{ module: { requestPermissions: [ { name: ohos.permission.MICROPHONE, reason: $string:mic_reason, usedScene: { abilities: [EntryAbility], when: always } } ] } }运行时权限申请functionrequestPermission(context:common.UIAbilityContext):void{constatManagerabilityAccessCtrl.createAtManager();atManager.requestPermissionsFromUser(context,[ohos.permission.MICROPHONEasPermissions]).then((){console.info(麦克风权限获取成功);}).catch((err:BusinessError){console.error(权限申请失败:${err.code}${err.message});});}四、核心开发步骤4.1 第一步配置音频采集参数// 音频流配置constaudioStreamInfo:audio.AudioStreamInfo{samplingRate:audio.AudioSamplingRate.SAMPLE_RATE_16000,// 采样率16kHzchannels:audio.AudioChannel.CHANNEL_1,// 单声道sampleFormat:audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE,// 16位小端格式encodingType:audio.AudioEncodingType.ENCODING_TYPE_RAW// 原始PCM编码};// 采集器配置constaudioCapturerInfo:audio.AudioCapturerInfo{source:audio.SourceType.SOURCE_TYPE_MIC,// 麦克风音频源capturerFlags:0// 扩展标志位};// 组合配置constaudioCapturerOptions:audio.AudioCapturerOptions{streamInfo:audioStreamInfo,capturerInfo:audioCapturerInfo};常用采样率采样率枚举值适用场景8000 HzSAMPLE_RATE_8000电话语音16000 HzSAMPLE_RATE_16000语音识别推荐22050 HzSAMPLE_RATE_22050一般音频44100 HzSAMPLE_RATE_44100CD音质音频48000 HzSAMPLE_RATE_48000高保真音频常用音频源类型源类型说明SOURCE_TYPE_MIC麦克风通用录音SOURCE_TYPE_VOICE_RECOGNITION语音识别专用SOURCE_TYPE_VOICE_COMMUNICATIONVoIP通话SOURCE_TYPE_VOICE_MESSAGE语音消息SOURCE_TYPE_CAMCORDER摄像录制4.2 第二步创建 AudioCapturer 实例letaudioCapturer:audio.AudioCapturer|undefinedundefined;audio.createAudioCapturer(audioCapturerOptions,(err:BusinessError,capturer:audio.AudioCapturer){if(err){console.error(创建失败: code${err.code}, msg${err.message});return;}audioCapturercapturer;console.info(AudioCapturer 创建成功);});4.3 第三步设置数据回调并录制到文件// 创建 PCM 文件constcontextgetContext(this)ascommon.UIAbilityContext;constfilePath${context.cacheDir}/recording.pcm;constfilefs.openSync(filePath,fs.OpenMode.READ_WRITE|fs.OpenMode.CREATE);letbufferSize0;// 注册数据回调 — 每当采集器获取到音频数据时触发constreadDataCallback(buffer:ArrayBuffer):void{constoptions{offset:bufferSize,length:buffer.byteLength};fs.writeSync(file.fd,buffer,options);bufferSizebuffer.byteLength;};audioCapturer.on(readData,readDataCallback);4.4 第四步监听状态变化audioCapturer.on(stateChange,(state:audio.AudioState){console.info(状态变化:${state});switch(state){caseaudio.AudioState.STATE_PREPARED:console.info(准备就绪);break;caseaudio.AudioState.STATE_RUNNING:console.info(正在录制);break;caseaudio.AudioState.STATE_STOPPED:console.info(录制已停止);break;caseaudio.AudioState.STATE_RELEASED:console.info(资源已释放);fs.close(file);// 释放后关闭文件break;}});4.5 第五步开始录制audioCapturer.start((err:BusinessError){if(err){console.error(启动失败:${err.code}${err.message});}else{console.info(录制已开始);}});4.6 第六步停止录制audioCapturer.stop((err:BusinessError){if(err){console.error(停止失败:${err.code}${err.message});}else{console.info(录制已停止);}});4.7 第七步释放资源audioCapturer.release((err:BusinessError){if(err){console.error(释放失败:${err.code}${err.message});}else{console.info(资源已释放);}});audioCapturerundefined;五、完整示例录音并保存为 PCM 文件import{audio}fromkit.AudioKit;import{fileIoasfs}fromkit.CoreFileKit;import{abilityAccessCtrl,common,Permissions}fromkit.AbilityKit;import{BusinessError}fromkit.BasicServicesKit;EntryComponentstruct AudioRecorderDemo{StateisRecording:booleanfalse;StaterecordDuration:string0.0 秒;StatefilePath:string;privatecapturer:audio.AudioCapturer|undefinedundefined;privatetimerId:number-1;privatestartTime:number0;privatefileSize:number0;aboutToAppear():void{constctxgetContext(this)ascommon.UIAbilityContext;abilityAccessCtrl.createAtManager().requestPermissionsFromUser(ctx,[ohos.permission.MICROPHONEasPermissions]);}startRecording():void{conststreamInfo:audio.AudioStreamInfo{samplingRate:audio.AudioSamplingRate.SAMPLE_RATE_16000,channels:audio.AudioChannel.CHANNEL_1,sampleFormat:audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE,encodingType:audio.AudioEncodingType.ENCODING_TYPE_RAW};constcapturerInfo:audio.AudioCapturerInfo{source:audio.SourceType.SOURCE_TYPE_MIC,capturerFlags:0};constoptions:audio.AudioCapturerOptions{streamInfo:streamInfo,capturerInfo:capturerInfo};audio.createAudioCapturer(options,(err:BusinessError,capturer:audio.AudioCapturer){if(err){console.error(创建失败:${err.code});return;}this.capturercapturer;constctxgetContext(this)ascommon.UIAbilityContext;this.filePath${ctx.cacheDir}/my_recording.pcm;constfilefs.openSync(this.filePath,fs.OpenMode.READ_WRITE|fs.OpenMode.CREATE);letoffset0;this.capturer.on(readData,(buffer:ArrayBuffer){fs.writeSync(file.fd,buffer,{offset:offset,length:buffer.byteLength});offsetbuffer.byteLength;this.fileSizeoffset;});this.capturer.on(stateChange,(state:audio.AudioState){if(stateaudio.AudioState.STATE_RELEASED){fs.close(file);}});this.startTimeDate.now();this.capturer.start();this.isRecordingtrue;// 更新录制时长显示this.timerIdsetInterval((){constelapsed(Date.now()-this.startTime)/1000;this.recordDuration${elapsed.toFixed(1)}秒;},100);});}stopRecording():void{clearInterval(this.timerId);if(this.capturer){this.capturer.stop().then((){this.capturer?.release();this.capturerundefined;});}this.isRecordingfalse;// 计算文件大小constsizeKB(this.fileSize/1024).toFixed(1);this.recordDuration(${sizeKB}KB);}aboutToDisappear():void{clearInterval(this.timerId);if(this.capturer){this.capturer.stop();this.capturer.release();}}build(){Column({space:24}){Text(AudioCapturer 录音示例).fontSize(22).fontWeight(FontWeight.Bold).margin({top:60})Text(this.recordDuration).fontSize(28).fontColor(this.isRecording?#FF6B6B:#333)Text(文件路径:${this.filePath}).fontSize(12).fontColor(#999).width(80%).textAlign(TextAlign.Center)Button(this.isRecording?停止录制:开始录制).width(200).height(48).backgroundColor(this.isRecording?#FF6B6B:#4FC08D).onClick((){if(this.isRecording){this.stopRecording();}else{this.startRecording();}})}.width(100%).height(100%).justifyContent(FlexAlign.Center)}}六、PCM 数据量计算PCM 文件大小的计算公式文件大小字节 采样率 × 声道数 × 采样位深 / 8 × 录制时长秒示例16kHz、单声道、16位、录制10秒16000 × 1 × 16 / 8 × 10 320,000 字节 ≈ 312.5 KB录制时长采样率声道位深文件大小10秒16kHz116~312.5 KB60秒16kHz116~1.88 MB60秒44.1kHz216~10.5 MB300秒16kHz116~9.38 MB七、注意事项权限先行创建 AudioCapturer 前必须已获得麦克风权限否则系统会抛出安全异常状态检查调用start()前确认当前状态为PREPARED、PAUSED或STOPPED资源释放录制结束后务必依次调用stop()→release()并在STATE_RELEASED回调中关闭文件文件关闭时机不要过早关闭文件句柄应在stateChange监听STATE_RELEASED状态值为 4后再关闭采样率匹配如果 PCM 数据后续用于语音识别采样率必须为 16kHz单声道16位缓冲区大小readData回调中的 buffer 大小由系统决定通常为几百字节到几千字节并发限制同一时刻只能有一个录音线程在工作fs.writeSync offset 语义HarmonyOS 的fileIo.writeSync中offset参数表示文件写入位置与 Node.js 的缓冲区偏移不同即数据写入文件的起始位置ArkTS 对象字面量类型检查ArkTS 要求对象字面量必须对应已声明的类或接口不能直接使用未类型化的{ offset: xxx, length: xxx }需声明WriteOptions类八、PCM 文件播放验证录制的 PCM 文件可以通过AudioRenderer播放验证import{audio}fromkit.AudioKit;functionplayPcm(filePath:string):void{constoptions:audio.AudioRendererOptions{streamInfo:{samplingRate:audio.AudioSamplingRate.SAMPLE_RATE_16000,channels:audio.AudioChannel.CHANNEL_1,sampleFormat:audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE,encodingType:audio.AudioEncodingType.ENCODING_TYPE_RAW},rendererInfo:{usage:audio.StreamUsage.STREAM_USAGE_MUSIC,rendererFlags:0}};audio.createAudioRenderer(options,(err,renderer){if(err)return;constfilefs.openSync(filePath,fs.OpenMode.READ_ONLY);constfileSizefs.statSync(filePath).size;letoffset0;renderer.on(writeData,(buffer:ArrayBuffer){if(offsetfileSize)return;constbytesReadfs.readSync(file.fd,buffer,{offset:offset,length:buffer.byteLength});offsetbytesRead;if(offsetfileSize){fs.close(file);renderer.stop();renderer.release();}});renderer.start();});}九、总结AudioCapturer 是 HarmonyOS 音频开发的基础组件核心使用流程为配置参数 → 创建实例 → 注册 readData 回调 → start() 开始录制 → [录制中...] → stop() 停止 → release() 释放资源掌握 AudioCapturer 的使用是实现语音识别、实时音频处理等高级功能的前提。结合 Core Speech Kit 的speechRecognizer模块可以构建完整的语音转文字功能。