Android端如何同时实现实时语音转文本与本地音频录制保存?
Android 同时实现语音转文本与本地音频保存的解决方案
核心问题在于Android的音频输入资源是独占的,AudioRecord和SpeechRecognizer会争抢同一麦克风输入,所以无法同时运行。下面给出两种低成本、无需依赖付费云服务的可行方案:
方案一:复用AudioRecord的音频数据,同时做录制和离线识别
用AudioRecord捕获原始PCM音频数据,一边将数据写入本地文件(可封装为WAV格式),一边把实时数据喂给离线语音识别引擎(比如开源的CMU Sphinx),这样只占用一次音频输入资源。
关键步骤:
- 初始化
AudioRecord,配置统一的音频参数(建议用16kHz单声道16bit PCM,适配多数离线引擎)。 - 在录制循环中,读取PCM数据:
- 将数据写入本地文件(如果要保存为WAV,需要先写入WAV文件头,再追加PCM数据)。
- 将数据传入离线识别引擎的输入流,实时解析识别结果。
代码片段示例:
// 初始化AudioRecord int sampleRate = 16000; int channelConfig = AudioFormat.CHANNEL_IN_MONO; int audioFormat = AudioFormat.ENCODING_PCM_16BIT; int bufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat); AudioRecord audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, sampleRate, channelConfig, audioFormat, bufferSize); // 初始化离线识别引擎(以CMU Sphinx为例) SpeechRecognizer recognizer = SpeechRecognizerSetup.defaultSetup() .setAcousticModel("resource:/edu/cmu/sphinx/models/en-us/en-us") .setDictionary("resource:/edu/cmu/sphinx/models/en-us/cmudict-en-us.dict") .getRecognizer(); recognizer.addListener(new RecognitionListener() { @Override public void onResult(Result result) { // 处理识别结果 String text = result.getHypothesis(); } }); // 开始录制和识别 audioRecord.startRecording(); recognizer.startListening(); byte[] buffer = new byte[bufferSize]; FileOutputStream fos = new FileOutputStream(new File(getExternalFilesDir(null), "recording.pcm")); while (isRecording) { int read = audioRecord.read(buffer, 0, bufferSize); if (read > 0) { // 写入本地文件 fos.write(buffer, 0, read); // 将音频数据喂给识别引擎 recognizer.processRaw(buffer, 0, read, false, false); } } // 停止录制和识别 audioRecord.stop(); audioRecord.release(); recognizer.stopListening(); fos.close();
方案二:通过SpeechRecognizer回调获取音频数据并保存
部分Android设备的SpeechRecognizer支持通过额外参数获取识别过程中的原始音频数据,这样可以省去单独用AudioRecord录制的步骤,直接在识别回调中保存音频。
关键步骤:
- 启动识别时,添加
EXTRA_GET_AUDIO_FORMAT和EXTRA_GET_AUDIO_DATA参数。 - 在
onResults或onPartialResults回调中,获取音频数据并写入本地文件。
代码片段示例:
Intent recognizerIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); recognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); // 添加获取音频数据的参数 recognizerIntent.putExtra(RecognizerIntent.EXTRA_GET_AUDIO_FORMAT, "audio/amr"); recognizerIntent.putExtra(RecognizerIntent.EXTRA_GET_AUDIO_DATA, true); SpeechRecognizer speechRecognizer = SpeechRecognizer.createSpeechRecognizer(context); speechRecognizer.setRecognitionListener(new RecognitionListener() { @Override public void onResults(Bundle results) { // 获取识别结果 ArrayList<String> matches = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION); // 获取音频数据并保存 byte[] audioData = results.getByteArray(SpeechRecognizer.EXTRA_AUDIO_DATA); if (audioData != null) { try { FileOutputStream fos = new FileOutputStream(new File(getExternalFilesDir(null), "recording.amr")); fos.write(audioData); fos.close(); } catch (IOException e) { e.printStackTrace(); } } } // 实现其他回调方法... }); speechRecognizer.startListening(recognizerIntent);
注意事项:
- 该方案的兼容性有限,部分设备或系统版本可能不支持
EXTRA_GET_AUDIO_DATA参数,需要提前做兼容性判断。 - 保存的音频格式由
EXTRA_GET_AUDIO_FORMAT指定,通常支持audio/amr或audio/wav。
额外提示
- 权限:确保已申请
RECORD_AUDIO权限,以及Android 13及以上版本的WRITE_MEDIA_AUDIO/READ_MEDIA_AUDIO权限,Android 12及以下的WRITE_EXTERNAL_STORAGE权限。 - 离线引擎选择:CMU Sphinx完全开源免费,支持多语言,但识别精度可能略低于云服务;也可以尝试设备厂商自带的离线语音识别能力(如小米、华为的内置ASR),需参考各自厂商的开发文档。
- 音频格式一致性:无论是录制还是识别,务必保持采样率、声道数、位深等参数一致,否则会导致识别失败或音频文件损坏。
内容的提问来源于stack exchange,提问作者quannm18
相关产品推荐
相关产品推荐

