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

WebRTC通话振铃时拨号音仅播放1秒就静音如何解决?

问题修复方案

根因分析

你遇到的音频播放1秒就中断的问题确实是AVAudioSession被覆写导致的:WebRTC内部默认会自动管理AVAudioSession的配置、激活状态,发起呼叫后WebRTC会触发Session配置修改,直接打断正在运行的AVAudioPlayer播放流程。

修复步骤

  • 第一步:禁用WebRTC的自动音频会话管理,避免它随意覆写你的配置
    在初始化WebRTC之后,立刻添加如下配置:
let rtcAudioSession = RTCAudioSession.sharedInstance()
rtcAudioSession.useManualAudio = true
rtcAudioSession.isAudioEnabled = false
  • 第二步:优化拨号音播放代码,补充必要的Session选项和错误日志
    你原来的代码缺少应对Session冲突的适配,同时要确保dialPlayer是全局强持有(你已经用了self持有,这点没问题),优化后的代码如下:
func startDialSound() {
    do {
        let session = AVAudioSession.sharedInstance()
        // 增加mixWithOthers等选项,避免和后续WebRTC的音频配置冲突
        try session.setCategory(.playAndRecord, options: [.duckOthers, .mixWithOthers, .allowBluetooth])
        try session.setActive(true, options: .notifyOthersOnDeactivation)
        
        guard let path = Bundle.main.path(forResource: "dial.wav", ofType: nil) else {
            print("拨号音文件不存在")
            return
        }
        let url = URL(fileURLWithPath: path)

        self.dialPlayer = try AVAudioPlayer(contentsOf: url)
        self.dialPlayer?.prepareToPlay()
        self.dialPlayer?.numberOfLoops = -1
        self.dialPlayer?.volume = 1
        let playSuccess = dialPlayer?.play() ?? false
        print("拨号音播放结果:\(playSuccess)")
    } catch {
        print("拨号音播放失败:\(error.localizedDescription)")
    }
}
  • 第三步:在对方接通/挂断的回调中处理后续逻辑
    当收到对方接通的回调时,先停止拨号音,再启用WebRTC的音频:
// 通话接通回调里执行
func onCallConnected() {
    // 停止拨号音
    self.dialPlayer?.stop()
    self.dialPlayer = nil
    
    do {
        let session = AVAudioSession.sharedInstance()
        // 切换到通话需要的Session配置
        try session.setCategory(.playAndRecord, options: [.allowBluetooth, .allowBluetoothA2DP])
        try session.setActive(true, options: .notifyOthersOnDeactivation)
        // 启用WebRTC音频
        let rtcAudioSession = RTCAudioSession.sharedInstance()
        rtcAudioSession.isAudioEnabled = true
    } catch {
        print("通话音频配置失败:\(error.localizedDescription)")
    }
}

// 通话被挂断/拒接回调里执行
func onCallEnded() {
    self.dialPlayer?.stop()
    self.dialPlayer = nil
    do {
        try AVAudioSession.sharedInstance().setActive(false, options: .notifyOthersOnDeactivation)
    } catch {
        print("Session停用失败:\(error.localizedDescription)")
    }
}

额外注意点

  • 要确保dialPlayer是当前类的强引用属性,不能是局部变量,否则方法执行完就会被释放,播放自然中断
  • 不要空吞error,添加日志可以快速定位其他可能的问题(比如拨号音文件损坏、路径错误等)

内容的提问来源于stack exchange,提问作者Mahmoud Shurrab

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 20:45:04