在iOS音频开发中,后台持续播放音乐或音效的同时又需要开启麦克风做通话或录音,是许多社交、教育和会议类应用都要面对的场景。一旦启用了系统的语音隔离(Voice Isolation)麦克风模式,原本通过AVAudioSessionCategoryOptionMixWithOthers实现的后台混音往往会被打断,导致其他App的声音被静音,或者本端采集的人声变得异常干净却失去了环境反馈。要理清这个冲突,必须先理解AVAudioSession的分类、选项与麦克风模式三者之间的约束关系。

音频会话分类与MixWithOthers的基础机制
AVAudioSession是iOS管理音频行为的中枢,每一个App在使用音频前都需要通过setCategory:withOptions:error:来声明自己的播放或录制意图。常见的分类如AVAudioSessionCategoryPlayback用于纯后台播放,AVAudioSessionCategoryPlayAndRecord用于边播边录。当我们在播放分类中加入AVAudioSessionCategoryOptionMixWithOthers这个选项时,系统允许当前App的音频与其他App的音频混合输出,而不是打断或替换它们,这正是后台音乐不被微信、电话等中断的关键。
需要注意的是,MixWithOthers仅对输出链路有效,并且要求分类本身支持混音。例如AVAudioSessionCategorySoloAmbient默认就会打断其他声音,而Playback加上该选项后,即便进入后台,只要App声明了后台音频模式,其他App的音乐就能继续播放。下面的代码展示了最基础的后台混音配置:
NSError *error = nil;
// 使用播放分类并允许与其他App混音
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback
withOptions:AVAudioSessionCategoryOptionMixWithOthers
error:&error];
if (error) {
NSLog(@"设置分类失败:%@", error.localizedDescription);
}
// 激活会话
[[AVAudioSession sharedInstance] setActive:YES error:&error];
如果此时再叠加录音需求,就必须切换到PlayAndRecord。但该分类默认是不混音的,需要同样加上MixWithOthers以及AVAudioSessionCategoryOptionDefaultToSpeaker等辅助选项,否则一旦开启录制,后台其他App的声音就会被系统策略静音。很多团队在接入RTC SDK时忽略了这一点,导致用户反馈“一进房间音乐就没了”,其实就是分类切换时丢掉了混音选项。
语音隔离麦克风模式的底层行为与冲突点
语音隔离是iOS在通话或录音场景下提供的一种麦克风模式(AVAudioSessionMicrophoneMode),对应AVAudioSessionMicrophoneModeVoiceIsolation。它的原理是在音频输入通路上插入一道系统级降噪与波束成形处理,只保留正对麦克风的人声,压制背景噪声与其他声源。从系统资源调度看,语音隔离要求输入流具有较高优先级和独占性,因此当App将麦克风模式设为语音隔离时,系统会重新评估当前的音频路由与混音状态。
冲突就发生在这里:语音隔离通常依附于AVAudioSessionModeVoiceChat或AVAudioSessionModeVideoChat这类会话模式,而这些模式在设计上倾向于提供清晰的双向通信,并不鼓励与其他App做输出混音。即使你之前用MixWithOthers保住了后台音乐,一旦调用setMicrophoneMode:error:切到语音隔离,系统可能主动停用与其他App的混合,以保证降噪算法有足够干净的参考信号。下面代码演示了如何在通话模式中尝试设置语音隔离:
AVAudioSession *session = [AVAudioSession sharedInstance];
NSError *err = nil;
// 切换到支持通话的模式
[session setCategory:AVAudioSessionCategoryPlayAndRecord
withOptions:AVAudioSessionCategoryOptionMixWithOthers
mode:AVAudioSessionModeVoiceChat
error:&err];
// 尝试开启语音隔离
if (@available(iOS 15.0, *)) {
[session setMicrophoneMode:AVAudioSessionMicrophoneModeVoiceIsolation error:&err];
}
[session setActive:YES error:&err];
实际测试中可以发现,在部分系统版本上上述配置仍能保留背景音,但在蜂窝通话或某些蓝牙设备中,语音隔离会强制收回混音权限。这是因为硬件音频单元在隔离模式下只开放单路上行,无法同时把其他App的音频回采进上行链路。开发者若强行在语音隔离下播放本地背景音乐并通过麦克风采集,会出现回声抵消异常或对方完全听不到背景音的情况。理解这一约束,才能决定是放弃隔离、改用标准模式,还是通过应用内混音绕过系统限制。
兼顾后台播放与清晰人声的实操方案
如果业务要求“用户自己能听到后台音乐,同时通话对方听到清晰人声但不需要听到背景音乐”,那么最稳妥的做法是不要依赖系统的MixWithOthers去混合其他App声音,而是将背景音乐纳入本App的播放流,并使用语音隔离保证上行干净。也就是说,放弃与其他App混音,改为应用内播放,这样语音隔离只会隔离外部噪声,不会干扰本App自身的输出通路。配置时仍使用PlayAndRecord加语音隔离,但不再设置MixWithOthers。
反过来,如果产品明确需要“微信音乐继续响,我们App也能录音”,那就必须牺牲语音隔离,改用默认的AVAudioSessionMicrophoneModeStandard或AVAudioSessionMicrophoneModeWideSpectrum,并保留MixWithOthers。此时可以在应用层做简易降噪,或引导用户到控制中心手动切换麦克风模式。以下代码展示如何主动降级麦克风模式以保住混音:
AVAudioSession *s = [AVAudioSession sharedInstance];
NSError *e = nil;
// 保混音、弃隔离
[s setCategory:AVAudioSessionCategoryPlayAndRecord
withOptions:AVAudioSessionCategoryOptionMixWithOthers | AVAudioSessionCategoryOptionDefaultToSpeaker
mode:AVAudioSessionModeVideoChat
error:&e];
if (@available(iOS 15.0, *)) {
// 明确使用标准模式,避免系统自动选隔离
[s setMicrophoneMode:AVAudioSessionMicrophoneModeStandard error:&e];
}
[s setActive:YES error:&e];
还有一个容易踩的坑是路由切换。当耳机或蓝牙设备接入时,系统可能重置麦克风模式到隔离,开发者需要监听AVAudioSessionRouteChangeNotification,在路由稳定后重新应用一次选项。此外,在Capability中开启Background Modes的Audio、AirPlay and Picture in Picture是后台混音的前提,否则进后台后会话会被挂起。综合来看,解决冲突的核心就是明确优先级:要系统降噪就收拢音频源头,要跨App混音就放过麦克风模式,二者不可在系统层面兼得。
AVAudioSessionVoice_IsolationMixWithOthers修改时间:2026-08-17 20:12:36