Android WebRTC无法发送DTMF,InsertDtmf调用无效求助
Android WebRTC DTMF发送失败原因及解决办法
核心错误原因
日志InsertDtmf is called on DtmfSender that can't send DTMF本质是调用insertDtmf时,DTMF Sender未处于可工作状态,或未正确定位到音频轨道的Sender,具体分以下几种情况:
- 调用时机过早:你在
peerConnection.addTrack后立刻尝试发送DTMF,但此时WebRTC的ICE连接尚未建立、媒体协商(SDP交换)未完成,音频Sender的DTMF模块还未初始化,无法正常发送。DTMF Sender仅在媒体流成功建立、轨道处于活跃状态后才能工作。 - 未正确定位音频Sender:
peerConnection.senders.firstOrNull()可能拿到的不是音频轨道对应的Sender(比如同时添加视频轨道时,第一个Sender可能是视频),此时调用dtmf()会返回无效实例,导致发送失败。 - MediaConstraints未明确支持DTMF:虽然WebRTC默认支持DTMF,但如果
MediaConstraints未开启相关配置,也可能导致功能不可用。
修正后的代码示例
// 1. 监听ICE连接状态,确保连接建立后再发送DTMF peerConnection.addIceConnectionObserver(object : PeerConnection.IceConnectionObserver { override fun onIceConnectionChange(newState: PeerConnection.IceConnectionState) { if (newState == PeerConnection.IceConnectionState.CONNECTED) { // 连接稳定后执行DTMF发送 sendDtmf(code) } } // 实现其他必要的回调方法 override fun onIceConnectionReceivingChange(p0: Boolean) {} override fun onIceGatheringChange(p0: PeerConnection.IceGatheringState) {} override fun onIceCandidate(p0: IceCandidate?) {} override fun onIceCandidatesRemoved(p0: Array<out IceCandidate>?) {} override fun onIceConnectionFailed() {} override fun onIceConnectionClosed() {} }) // 2. 正确筛选音频Sender并发送DTMF private fun sendDtmf(code: String) { // 过滤出音频轨道对应的Sender val audioSender = peerConnection.senders.firstOrNull { it.track()?.kind == "audio" } audioSender?.dtmf()?.let { dtmfSender -> // 先检查DTMF Sender是否可用 if (dtmfSender.canInsertDtmf()) { dtmfSender.insertDtmf(code, 400, 50) } else { Log.e("DTMF", "DTMF Sender暂时不可用") } } ?: Log.e("DTMF", "未找到有效音频Sender") }
额外注意事项
- 发送DTMF前必须调用
canInsertDtmf()检查状态,避免无效调用。 - 除了ICE连接状态,也可在收到远端媒体流的回调(如
onTrack)后发送DTMF,确保媒体通路完全打通。 - 确认使用的WebRTC版本为稳定版,部分旧版本存在DTMF相关的已知Bug。
内容的提问来源于stack exchange,提问作者Alexey
相关产品推荐
相关产品推荐

