You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native安卓外呼录音问题:通话过程无法录制音频

安卓通话录音问题解决思路

问题现状

用React Native开发的安卓外呼录音APP,在Nokia C31(Android 12)上只能录到拨号前后的声音,通话过程完全无录音。尝试将音频源换成VOICE_CALL,但因需要CAPTURE_AUDIO_OUTPUT权限(该权限为系统专属,第三方APP无法获取),直接报错无法启动录音。

问题原因

  1. 当前使用的VOICE_COMMUNICATION音频源,在Android 12系统下无法捕获通话双方的音频流,仅能录制设备麦克风的声音;进入通话状态后,系统会限制第三方APP访问通话音频通道。
  2. VOICE_CALL是专门针对通话场景的音频源,但它依赖的CAPTURE_AUDIO_OUTPUT权限属于系统级权限,谷歌明确禁止第三方APP使用,因此直接调用会触发权限错误。

可行解决办法

办法1:通过MediaProjection捕获系统音频

Android 5.0及以上版本支持MediaProjection API,可捕获系统播放的音频,结合麦克风录制用户声音,最后合并两个音频流实现双向录音:

  • 操作步骤:
    1. 在现有权限基础上,新增MEDIA_CONTENT_CONTROL权限,同时引导用户手动开启屏幕录制权限(MediaProjection必须由用户主动授权)。
    2. 启动MediaProjection录制系统音频,同时开启麦克风录制用户声音,后期通过音频处理工具合并两个流。
  • 注意事项:需要用户同意屏幕录制授权,部分设备存在兼容性差异,且需自行实现音频合并逻辑。

办法2:更换音频源+抢占音频焦点

尝试切换到VOICE_RECOGNITION或MIC音频源,配合音频焦点管理提升录音权限优先级:

  • 先修改音频源配置:
const audioSet: AudioSet = {
  AudioEncoderAndroid: AudioEncoderAndroidType.DEFAULT,
  AudioSourceAndroid: AudioSourceAndroidType.VOICE_RECOGNITION,
};
  • 启动录音时抢占音频焦点(需安装react-native-audio-manager库):
import { AudioManager } from 'react-native-audio-manager';

const startRecording = async () => {
  // 原有文件名、路径设置逻辑...
  try {
    await AudioManager.requestAudioFocus(); // 先抢占音频焦点
    setIsRecording(true);
    const result = await audioRecorderPlayer.current.startRecorder(
      fileName,
      audioSet,
      true,
    );
    console.log('start recording', result);
  } catch (error) {
    console.error('Error starting recording:', error);
    await AudioManager.abandonAudioFocus(); // 启动失败则释放焦点
  }
};
  • 注意事项:这种方式仅能录制用户侧声音,对方声音需开启免提模式才能通过麦克风录入。

办法3:集成第三方通话SDK

直接使用自带录音功能的第三方通话SDK(如阿里云通话、容联云等),这类SDK已处理好系统权限和录音逻辑,集成后可直接实现双向录音,无需自行处理底层权限问题。

代码调整示例(办法2)

以下是调整后的录音相关代码参考:

import AudioRecorderPlayer, {
  AudioEncoderAndroidType,
  AudioSet,
  AudioSourceAndroidType,
  OutputFormatAndroidType,
} from 'react-native-audio-recorder-player';
import dayjs from 'dayjs';
import RNFetchBlob from 'rn-fetch-blob';
import { AudioManager } from 'react-native-audio-manager';
const dirs = RNFetchBlob.fs.dirs;

// 更换为AAC编码和MPEG_4格式,提升兼容性
const audioSet: AudioSet = {
  AudioEncoderAndroid: AudioEncoderAndroidType.AAC,
  AudioSourceAndroid: AudioSourceAndroidType.VOICE_RECOGNITION,
  OutputFormatAndroid: OutputFormatAndroidType.MPEG_4,
};

export default function Dialer() {
  const audioRecorderPlayer = useRef(new AudioRecorderPlayer());

  const startRecording = async () => {
    const formattedDate = dayjs().format('DD-MMM-YYYY_hh-mm-ss-A');
    // 改用m4a格式,比mp3兼容性更好
    const fileName = `${dirs.CacheDir}/call-record_${formattedDate}.m4a`;
    setAudioPath(fileName);
    try {
      // 先请求音频焦点
      await AudioManager.requestAudioFocus();
      setIsRecording(true);
      const result = await audioRecorderPlayer.current.startRecorder(
        fileName,
        audioSet,
        true,
      );
      console.log('start recording', result);
    } catch (error) {
      console.error('Error starting recording:', error);
      // 启动失败释放焦点
      await AudioManager.abandonAudioFocus();
    }
  };

  const handleCall = () => {
    if (!isRecording) {
      // 等待录音启动成功后再拨号
      startRecording().then(() => {
        Linking.openURL(`tel:${number}`);
      });
    }
  };

  // 停止录音时释放音频焦点
  const stopRecording = async () => {
    try {
      await audioRecorderPlayer.current.stopRecorder();
      await AudioManager.abandonAudioFocus();
      setIsRecording(false);
    } catch (error) {
      console.error('Error stopping recording:', error);
    }
  };

  // ...其他业务代码
}

权限补充

需要在权限列表中新增MEDIA_CONTENT_CONTROL:

const permissions = [
  PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
  PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE,
  PermissionsAndroid.PERMISSIONS.RECORD_AUDIO,
  PermissionsAndroid.PERMISSIONS.CALL_PHONE,
  PermissionsAndroid.PERMISSIONS.MEDIA_CONTENT_CONTROL,
];

内容的提问来源于stack exchange,提问作者Hao.Le

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 18:20:56