AudioCapturer录音与AudioRenderer播放音频实践
开发手机APP应用,录音与播放音频是很常见的需求,在鸿蒙应用开发中,@kit.AudioKit组件提供支持PCM格式录音的工具AudioCapturer,以及用于播放PCM格式音频的工具AudioRenderer。要想用AudioCapturer实现录音功能,需要先声明一个音频流配置实例,代码如下:
一、AudioCapturer实现录音功能第一步
audioConfig: audio.AudioStreamInfo = { // 采样率,这里设置为44100Hz(标准的CD质量采样率) samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_44100, // 声道数,这里设置为1(单声道) channels: audio.AudioChannel.CHANNEL_1, // 采样格式,这里设置为16位有符号整数,小端序(SAMPLE_FORMAT_S16LE) sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE, // 编码类型,这里设置为原始音频(ENCODING_TYPE_RAW) encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW }
samplingRate参数根据实际录音场景建议:语音通话(16000Hz、节省带宽),音乐录制(44100Hz 或 48000Hz),Hi-Res音频(48000Hz 或更高)。完整samplingRate采样率参数可选项有如下几种:
enum AudioSamplingRate { SAMPLE_RATE_8000 = 8000, // 8kHz SAMPLE_RATE_11025 = 11025, // 11.025kHz SAMPLE_RATE_12000 = 12000, // 12kHz SAMPLE_RATE_16000 = 16000, // 16kHz SAMPLE_RATE_22050 = 22050, // 22.05kHz SAMPLE_RATE_24000 = 24000, // 24kHz SAMPLE_RATE_32000 = 32000, // 32kHz SAMPLE_RATE_44100 = 44100, // 44.1kHz (CD标准) SAMPLE_RATE_48000 = 48000, // 48kHz (专业音频标准) SAMPLE_RATE_64000 = 64000, // 64kHz SAMPLE_RATE_96000 = 96000 // 96kHz (高保真) }
channels参数根据实际录音场景建议:语音记录(单声道、减少文件体积),音乐播放(立体声),影院体验(5.1/7.1环绕声)。完整channels声道数参数可选项有如下几种:
enum AudioChannel { CHANNEL_1 = 1, // 单声道 CHANNEL_2 = 2, // 立体声 CHANNEL_3 = 3, CHANNEL_4 = 4, CHANNEL_5 = 5, CHANNEL_6 = 6, // 5.1环绕声 CHANNEL_7 = 7, CHANNEL_8 = 8 // 7.1环绕声 }
sampleFormat参数根据实际录音场景建议:S16LE(兼容性最好,适合大部分场景),F32LE(专业音频处理保留更高精度),设备兼容性(Android设备主要支持S16LE)。完整sampleFormat采样格式参数可选性有如下几种:
enum AudioSampleFormat { SAMPLE_FORMAT_INVALID = -1, // 无效格式 SAMPLE_FORMAT_U8 = 1, // 8位无符号整型 SAMPLE_FORMAT_S16LE = 2, // 16位有符号整型小端序 SAMPLE_FORMAT_S24LE = 3, // 24位有符号整型小端序 SAMPLE_FORMAT_S32LE = 4, // 32位有符号整型小端序 SAMPLE_FORMAT_F32LE = 5, // 32位浮点小端序 SAMPLE_FORMAT_S24_32LE = 6, // 24位存储为32位小端序 SAMPLE_FORMAT_S16BE = 7, // 16位有符号整型大端序 SAMPLE_FORMAT_S24BE = 8, // 24位有符号整型大端序 SAMPLE_FORMAT_S32BE = 9, // 32位有符号整型大端序 SAMPLE_FORMAT_F32BE = 10, // 32位浮点大端序 SAMPLE_FORMAT_S24_32BE = 11 // 24位存储为32位大端序 }
encodingType参数根据实际录音场景对比PCM格式和MP3格式如下:
RAW(PCM) 优点:原始质量,无延迟 缺点:文件体积大 使用场景:专业音频处理、实时传输 压缩格式(MP3/AAC) 优点:体积小 缺点:有损压缩 使用场景:音乐存储、网络传输。
完整encodingType编码类型参数有如下几种可选:
enum AudioEncodingType { ENCODING_TYPE_INVALID = -1, // 无效类型 ENCODING_TYPE_DEFAULT = 0, // 默认 ENCODING_TYPE_RAW = 1, // 原始PCM数据 ENCODING_TYPE_MP3 = 2, // MP3编码 ENCODING_TYPE_AAC = 3, // AAC编码 ENCODING_TYPE_AAC_LC = 4, // AAC-LC ENCODING_TYPE_AAC_HE = 5, // AAC-HE ENCODING_TYPE_FLAC = 6 // FLAC无损 }
二、AudioCapturer实现录音功能第二步
声明一个音频源信息和采集标志的配置实例,示例代码如下:
audioSourceConfig: audio.AudioCapturerInfo = { // 音频源类型 source: audio.SourceType.SOURCE_TYPE_MIC, // 采集标志位 capturerFlags: 0 }
source音频源类型参数可选项有如下几种:
enum SourceType { SOURCE_TYPE_INVALID = -1, // 无效音源 SOURCE_TYPE_MIC = 0, // 麦克风 SOURCE_TYPE_VOICE_COMMUNICATION, // 语音通话 SOURCE_TYPE_VOICE_RECOGNITION, // 语音识别 SOURCE_TYPE_VOICE_CALL, // 语音呼叫 SOURCE_TYPE_CAMCORDER, // 相机录音(同步视频录制) SOURCE_TYPE_VOICE_PERFORMANCE, // 语音表演(如K歌) SOURCE_TYPE_ULTRASONIC, // 超声波(特殊设备) SOURCE_TYPE_ECHO_REFERENCE, // 回声参考源 SOURCE_TYPE_REMOTE_SUBMIX, // 远程混音 SOURCE_TYPE_UNPROCESSED, // 未处理的原始音频 SOURCE_TYPE_VOIP, // VoIP音频(网络电话) SOURCE_TYPE_HOTWORD, // 唤醒词采集(常亮麦克风) SOURCE_TYPE_ECHO, // 回声消除参考 SOURCE_TYPE_FM_TUNER // FM调谐器 }
source参数根据实际录音场景建议如下:
SOURCE_TYPE_MIC: 普通麦克风采集(默认) SOURCE_TYPE_VOICE_RECOGNITION: 语音识别(设备会优化降噪) SOURCE_TYPE_VOIP: 网络电话(优化网络传输延迟) SOURCE_TYPE_CAMCORDER: 视频录制同步音频 SOURCE_TYPE_HOTWORD: 唤醒词检测(常亮低功耗麦克风)
完整capturerFlags采集标志参数有如下几种可选:
enum AudioCapturerFlags { AUDIO_CAPTURER_FLAG_NONE = 0, // 无标志 AUDIO_CAPTURER_FLAG_PREFER_LOW_LATENCY = 1, // 优先低延迟 AUDIO_CAPTURER_FLAG_STREAMING = 2, // 流式传输(持续采集) AUDIO_CAPTURER_FLAG_DEEP_BUFFER = 4, // 深层缓存(优化功耗) AUDIO_CAPTURER_FLAG_FAST = 8 // 快速模式(低延迟路径) }
三、AudioCapturer实现录音功能第三步
有了上述两个配置实例,就可以初始化一个AudioCapturer录音实例了,示例代码如下:
async initAudioHandler() { this.audioHandler = await audio.createAudioCapturer({ streamInfo: this.audioConfig, capturerInfo: this.audioSourceConfig }) }
四、AudioCapturer实现录音功能第四步
有了AudioCapturer录音实例后,就可以在开始录音按钮的点击事件里调用AudioCapturer实例的start方法开始录音,正常执行的话会在手机右上角显示正在录音的标志,然后AudioCapturer实例的readData监听事件里,通过将接收到的录音buffer数据写到cache沙箱目录下的xxx.wav文件里。示例代码如下:
Button('开始录音') .onClick(() => { try { this.isRecordAudio = true this.fileHandler = SandboxFileUtil.cache.create(util.generateRandomUUID() + '.wav') this.audioAbsPath = this.fileHandler.path this.audioHandler?.start() this.audioHandler?.on('readData', (audioBuffer: ArrayBuffer) => { if (this.isRecordAudio) { SandboxFileUtil.cache.appendWithHandler(this.fileHandler!, audioBuffer) } }) } catch (err) { showDebugV2(err) } })
①、停止录音
当录音完成后,点击停止录音按钮,在停止录音按钮的点击事件里通过调用AudioCapturer录音实例的stop方法实现停止录音。需要注意的是不要调用AudioCapturer实例的off('readData')方法,因为经过真机测试,第二次再次点击开始录音按钮,on('readData', callback)方法的callback无法接收录音buffer。示例代码如下:
Button('停止录音') .onClick(() => { this.isRecordAudio = false this.audioHandler?.stop() fileIo.closeSync(this.fileHandler) // 停止录音不要调用off('readData')方法 // this.audioHandler?.off('readData') })
五、第五步:AudioRenderer实例播放PCM格式音频
声明AudioRenderer实例的第一个参数复用第一步中的audioConfig,第二个参数需要声明一个音频输出参数的配置实例,代码如下:
audioRendererConfig: audio.AudioRendererInfo = {、 // 渲染器标志 rendererFlags: 0, // 音频用途场景 usage: audio.StreamUsage.STREAM_USAGE_MOVIE }
其中rendererFlags(渲染器标志)参数可选值:0(普通模式),1(低延迟模式);低延迟模式(标志为1)仅在某些支持低延迟的硬件设备上有效,若不支持则会回退到普通模式。
usage(音频用途)参数定义了音频流的用途,系统根据用途进行不同的音频处理(如音效、重采样策略等)。完整usage可选项有如下几种:
enum StreamUsage { STREAM_USAGE_DEFAULT = 0, // 默认用途 STREAM_USAGE_MUSIC = 1, // 音乐播放 STREAM_USAGE_VOICE_COMMUNICATION = 2, // 语音通话 STREAM_USAGE_VOICE_ASSISTANT = 3, // 语音助手 STREAM_USAGE_ALARM = 4, // 闹钟 STREAM_USAGE_NOTIFICATION = 5, // 通知音 STREAM_USAGE_RINGTONE = 6, // 铃声 STREAM_USAGE_SYSTEM = 7, // 系统声音 STREAM_USAGE_MOVIE = 8, // 电影(视频播放) STREAM_USAGE_GAME = 9, // 游戏音效 }
usage参数根据实际播放场景建议如下:
普通音频播放:STREAM_USAGE_MUSIC 视频播放:STREAM_USAGE_MOVIE 游戏音效:STREAM_USAGE_GAME 语音通话:STREAM_USAGE_VOICE_COMMUNICATION
六、第六步声明一个用于播放PCM格式音频的AudioRenderer实例
复用第一步中的audioConfig,结合第五步中声明的audioRendererConfig,声明一个用于播放PCM格式音频的AudioRenderer实例。示例代码如下:
audioRendererOptions: audio.AudioRendererOptions = { streamInfo: this.audioConfig, rendererInfo: this.audioRendererConfig } renderHandler = await audio.createAudioRenderer(this.audioRendererOptions)
点击播放录音按钮,在点击事件里调用renderHandler的start方法开始播放PCM格式的录音音频文件。示例代码如下:
Button('播放录音') .onClick(() => { this.renderHandler.start(this.audioAbsPath) })
一定要确保声明AudioCapturer录音实例和AudioRenderer播放音频实例时的第一个参数一定要用相同的audioConfig,否则会出现播放杂音等现象。