iOS中如何避免WebRTC语音与Mapbox导航音频相互中断?
问题背景
我正在开发一款iOS应用,集成了WebRTC实时语音通信和Mapbox Navigation SDK的逐向导航功能。核心痛点是:当Mapbox Navigation的NavigationViewController播放导航音频指令时,正在进行的WebRTC语音会被直接中断停止,且导航音频结束后WebRTC无法自动恢复,严重影响用户体验。
我的WebRTC音频会话配置代码如下:
func setupAudioSession() { self.rtcAudioSession.lockForConfiguration() do { print(self.rtcAudioSession.categoryOptions) try self.rtcAudioSession.setCategory(AVAudioSession.Category.playAndRecord.rawValue, with: [.mixWithOthers]) try self.rtcAudioSession.setMode(AVAudioSession.Mode.voiceChat.rawValue) try self.rtcAudioSession.overrideOutputAudioPort(.speaker) } catch let error { debugPrint("Error changing AVAudioSession category: \(error)") } self.rtcAudioSession.unlockForConfiguration() }
单独使用该配置时WebRTC音频工作正常,但Mapbox播放导航音频时会修改AVAudioSession模式为AVAudioSessionModeDefault,覆盖WebRTC设置的voiceChat模式,导致WebRTC音频中断且无法自行恢复。
解决方案
1. 监听AVAudioSession状态变化,主动恢复WebRTC配置
注册AVAudioSession的各类通知,在会话被修改、中断或路由变化时,重新恢复WebRTC的音频设置:
// 在初始化阶段注册通知 func setupAudioNotifications() { NotificationCenter.default.addObserver(self, selector: #selector(audioSessionInterrupted(_:)), name: AVAudioSession.interruptionNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(audioSessionCategoryChanged(_:)), name: .AVAudioSessionCategoryDidChange, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(audioSessionRouteChanged(_:)), name: AVAudioSession.routeChangeNotification, object: nil) } // 处理音频中断结束事件 @objc private func audioSessionInterrupted(_ notification: Notification) { guard let userInfo = notification.userInfo, let typeValue = userInfo[AVAudioSessionInterruptionTypeKey] as? UInt, let type = AVAudioSession.InterruptionType(rawValue: typeValue) else { return } if type == .ended { restoreWebRTCAudio() } } // 处理音频类别变化事件 @objc private func audioSessionCategoryChanged(_ notification: Notification) { restoreWebRTCAudio() } // 处理音频路由变化事件 @objc private func audioSessionRouteChanged(_ notification: Notification) { restoreWebRTCAudio() } // 恢复WebRTC音频会话配置 private func restoreWebRTCAudio() { rtcAudioSession.lockForConfiguration() defer { rtcAudioSession.unlockForConfiguration() } do { try rtcAudioSession.setCategory(AVAudioSession.Category.playAndRecord.rawValue, with: [.mixWithOthers]) try rtcAudioSession.setMode(AVAudioSession.Mode.voiceChat.rawValue) try rtcAudioSession.overrideOutputAudioPort(.speaker) rtcAudioSession.isAudioEnabled = true } catch { debugPrint("Failed to restore WebRTC audio: \(error)") } }
2. 配置Mapbox Navigation音频为混音+压低模式
通过Mapbox的NavigationAudioSession调整音频行为,让导航音频播放时仅压低WebRTC音量而非中断,播放结束后自动恢复:
// 启动导航前配置Mapbox音频会话 func setupMapboxAudioSession() { NavigationAudioSession.shared.setCategory(.playback, options: [.mixWithOthers, .duckOthers]) try? NavigationAudioSession.shared.activate() }
.duckOthers选项会在导航音频播放时降低其他音频的音量,既保证导航指令清晰,又不会完全中断WebRTC通话,体验更友好。
3. 监听Mapbox导航指令结束事件,主动恢复
通过NavigationServiceDelegate监听导航指令播放完成事件,在合适时机触发WebRTC音频恢复:
extension YourViewController: NavigationServiceDelegate { func navigationService(_ service: NavigationService, didSpokenInstruction instruction: SpokenInstruction, routeProgress: RouteProgress) { // 指令播放完成后延迟恢复(根据指令时长调整) DispatchQueue.main.asyncAfter(deadline: .now() + instruction.duration) { self.restoreWebRTCAudio() } } }
验证重点
- 导航音频播放时,WebRTC语音是否仅被压低音量而非完全中断
- 导航音频结束后,WebRTC语音是否自动恢复正常音量
- 切换音频路由(耳机/蓝牙/扬声器)时,两者音频是否均能正常工作
内容的提问来源于stack exchange,提问作者Faraz Ahmed Khan
相关产品推荐
相关产品推荐

