Android使用CameraX能否同时实现语音识别与视频采集功能
安卓端语音识别与带音频视频录制同时运行的实现方案
问题根源
安卓系统默认对麦克风等音频输入硬件做了独占访问限制,同一时间仅允许一个功能模块持有音频输入焦点。当前实现中系统原生SpeechRecognizer、视频录制模块会独立申请麦克风权限,后启动的模块会直接抢占前序模块的音频焦点,导致仅最后调用的功能可以正常获取音频流工作,和调用顺序无关。
可行落地方案
核心逻辑是仅保留一个麦克风采集入口,将同一份采集到的音频流分发给两个业务模块使用,从根源上避免音频焦点抢占,具体有两种实现路径:
- 统一音频采集+流分发(全版本兼容,稳定性最高,推荐使用)
单独初始化AudioRecord作为唯一的麦克风采集入口,拿到原始PCM音频数据后做两路分发:- 一路送入视频录制模块,和摄像头采集的视频帧做音视频同步、编码封装,生成带完整音轨的录制文件
- 另一路送入语音识别模块,替代识别SDK默认的自主麦克风采集逻辑
- 高版本系统音频共享(仅适配安卓11+,不推荐作为主方案)
安卓11(API 等级30)及以上版本开放了普通应用的音频输入共享能力,两个模块启动时都配置共享模式的AudioAttributes即可同时获取音频流,但该方案不支持安卓10及以下版本,且多数国产定制ROM会阉割该特性,覆盖范围有限。
现有代码适配注意点
你当前使用的系统原生SpeechRecognizer默认封装了自主申请麦克风、采集音频的逻辑,没有开放外部传入音频流的公开API,无法直接复用统一采集的音频数据,需要做如下调整:
- 语音识别部分替换为支持外部PCM音频流输入的识别实现,可选方案包括:适配系统
SpeechRecognizer的自定义音频源配置、集成Vosk/Whisper.cpp等支持流输入的离线识别引擎、接入支持流推送的在线识别服务 - 视频录制部分不要使用高层封装的
MediaRecorder(该API默认自主接管麦克风采集),改用CameraX+MediaCodec的低阶录制实现,支持直接接收外部传入的PCM音频数据做编码、封装。
核心实现参考
// 初始化全局唯一的麦克风采集实例 val sampleRate = 16000 // 语音识别通用采样率,若视频录制需要44100/48000采样率可在分发前做重采样处理 val channelConfig = AudioFormat.CHANNEL_IN_MONO val audioFormat = AudioFormat.ENCODING_PCM_16BIT val bufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat) val audioRecorder = AudioRecord( MediaRecorder.AudioSource.MIC, sampleRate, channelConfig, audioFormat, bufferSize * 2 ) // 启动独立采集线程做音频流分发 val collectThread = Thread { Process.setThreadPriority(Process.THREAD_PRIORITY_AUDIO) val audioBuffer = ByteArray(bufferSize) audioRecorder.startRecording() while (isTaskRunning) { val readLength = audioRecorder.read(audioBuffer, 0, bufferSize) if (readLength > 0) { val validData = audioBuffer.copyOf(readLength) // 分发音频数据给语音识别模块 speechRecognitionEngine.feedAudio(validData) // 分发音频数据给视频录制的音频编码模块 videoRecordEngine.feedAudio(validData) } } // 任务结束释放资源 audioRecorder.stop() audioRecorder.release() } collectThread.start()
注意:如果需要同时满足语音识别的16k采样率要求和视频录制的44.1k/48k采样率要求,可以在音频分发前对原始PCM数据做重采样处理,避免两个模块采样率参数冲突。
内容的提问来源于stack exchange,提问作者SHUBHASAI MOHAPATRA
相关产品推荐
相关产品推荐

