部署到Heroku的WebRTC音视频通话应用跨网连接失败该如何解决?
问题根因及修复方案
1. RTCPeerConnection 初始化参数错误
你当前代码创建Peer连接时直接传入了iceServers数组,不符合API规范:
// 错误写法 let peerConnection = new RTCPeerConnection(iceConfiguration.iceServers)
RTCPeerConnection 要求传入完整的配置对象,正确写法应为:
// 正确写法 let peerConnection = new RTCPeerConnection(iceConfiguration)
该错误会导致你的STUN/TURN配置完全没有生效,是跨网连接失败的核心原因之一。
2. TURN服务器配置字段不兼容
你当前TURN服务配置用了已废弃的url字段,部分浏览器无法识别,需要统一替换为标准字段urls:
// 修复后的TURN配置 iceConfiguration.iceServers.push({ urls: 'turn:numb.viagenie.ca', credential: 'muazkh', username: 'webrtc@live.com' })
3. 缺失ICE候选交换逻辑
你目前的onicecandidate回调仅做了日志打印,没有将生成的ICE候选同步给远端对等端,也没有实现接收远端ICE候选后调用addIceCandidate的逻辑,这会导致两端无法完成NAT穿透协商。
修复步骤:
- 两端
onicecandidate触发时,将候选信息通过接口存储到MongoDB对应会话记录中 - 两端通过轮询(或改用WebSocket实时推送)拿到对方的ICE候选后,调用
peerConnection.addIceCandidate(new RTCIceCandidate(candidateData))添加候选
4. 信令同步时序问题
你当前用2.5秒间隔轮询拉取会话信息,时序容错性极低,建议调整:
- 房主设置完远端SDP(访客应答)后,继续轮询拉取访客的ICE候选
- 访客设置完本地SDP后,继续轮询拉取房主的ICE候选
- 所有信令存储时要区分类型(offer/answer/房主候选/访客候选),避免互相覆盖
补充说明
本地环境能正常互通是因为同网络下不需要STUN/TURN,也不需要额外的ICE候选交换,仅靠SDP里的主机候选就能完成连接,跨网时才会暴露上述问题。
如果修复后依然有问题,可以替换公共TURN服务器为自建服务,公开的numb.viagenie.ca访问限制多、稳定性差,经常无法正常提供中继服务。
内容的提问来源于stack exchange,提问作者Marin Dedic
相关产品推荐
相关产品推荐

