WebRTC 连接在本地网络之外不起作用
Posted
技术标签:
【中文标题】WebRTC 连接在本地网络之外不起作用【英文标题】:WebRTC connection not working outside of local network 【发布时间】:2022-01-10 13:57:21 【问题描述】:我们为 webrtc 双向视频和音频流设置了以下设置:
移动
android 应用程序使用Google WebRTC 实现 java 包装器。测试了这两个库:
implementation 'org.webrtc:google-webrtc:1.0.+'
implementation 'com.github.webrtc-sdk:android:92.4515.03' // https://github.com/webrtc-sdk/android
RPi
带有WebRTC plugin 的Gstreamer 基于gst-examples 并进行了一些修改。
浏览器
还稍微修改了gst-examples javascript 实现。它基于原生浏览器 WebRTC 支持。
转
在 Docker 中工作的 Coturn 服务器 (coturn/coturn)。
问题
当从 RPi 调用浏览器或手机调用浏览器时,无论是在本地网络还是通过 Internet(通过 TURN 服务器),一切正常。但是,当尝试通过 Internet 连接 RPi 和 Android 设备时,它会卡住(本地网络也可以)。设备相互通信,协商 SDP 和 ICE 候选,TURN 服务器正确打开连接,但没有音频/视频。
查看Android日志时,第一个区别是没有触发ICE连接变化:
PeerConnectionObserver: onStandardizedIceConnectionChange: CHECKING
也没有
PeerConnectionObserver: onConnectionChange: CONNECTING
这发生在 ICE 候选人交换之前。发送 ICE 候选后,不会与其他设备进行进一步通信,也不会触发任何状态更改。例如在工作案例中的这些:
PeerConnectionObserver: onSelectedCandidatePairChanged: org.webrtc.CandidatePairChangeEvent@a856333
PeerConnectionObserver: onStandardizedIceConnectionChange: CONNECTED
PeerConnectionObserver: onConnectionChange: CONNECTED
PeerConnectionObserver: onIceConnectionChange CONNECTED
[Internal data channel]: onStateChange
PeerConnectionObserver: onDataChannel org.webrtc.DataChannel@b76f6f0
[External data channel]: onStateChange
coturn 日志根本没有显示任何可疑之处。
在进一步调查此问题时提供任何提示或帮助。
编辑 在@RSATom 的建议下,我们更仔细地查看了正在发送的 ICE 和 SDP 消息,并没有发现任何差异。对于通过 Internet 和本地的移动 RPi 通信,SDP 是相同的。唯一的区别是随机生成的 id。 ICE 也没有太大区别。第一个发送者(提议者)是相同的,而回答者则略有不同,因为它包含 TURN 详细信息:
通过互联网
video0:0:candidate:228040959 1 udp 2122260223 10.111.215.156 53556 typ host generation 0 ufrag 3SNh network-id 3 network-cost 900::UNKNOWN
video0:0:candidate:559267639 1 udp 2122202367 ::1 48566 typ host generation 0 ufrag 3SNh network-id 2::UNKNOWN
video0:0:candidate:1510613869 1 udp 2122129151 127.0.0.1 41279 typ host generation 0 ufrag 3SNh network-id 1::UNKNOWN
video0:0:candidate:1876313031 1 tcp 1518222591 ::1 46051 typ host tcptype passive generation 0 ufrag 3SNh network-id 2::UNKNOWN
video0:0:candidate:344579997 1 tcp 1518149375 127.0.0.1 60259 typ host tcptype passive generation 0 ufrag 3SNh network-id 1::UNKNOWN
video0:0:candidate:842163049 1 udp 1686052607 31.0.91.196 6742 typ srflx raddr 10.111.215.156 rport 53556 generation 0 ufrag 3SNh network-id 3 network-cost 900:stun:3.70.23.20:3478:UNKNOWN
video0:0:candidate:593469510 1 udp 41885439 172.31.0.169 14307 typ relay raddr 31.0.91.196 rport 6742 generation 0 ufrag 3SNh network-id 3 network-cost 900:turn:3.70.23.20:3478?transport=udp:UNKNOWN
通过本地 WiFi
video0:0:candidate:2858526953 1 udp 2122260223 192.168.0.21 38123 typ host generation 0 ufrag rwx/ network-id 3 network-cost 10::UNKNOWN
video0:0:candidate:559267639 1 udp 2122202367 ::1 52058 typ host generation 0 ufrag rwx/ network-id 2::UNKNOWN
video0:0:candidate:1510613869 1 udp 2122129151 127.0.0.1 39469 typ host generation 0 ufrag rwx/ network-id 1::UNKNOWN
video0:0:candidate:842163049 1 udp 1686052607 178.235.191.135 13607 typ srflx raddr 192.168.0.21 rport 38123 generation 0 ufrag rwx/ network-id 3 network-cost 10:stun:3.70.23.20:3478:UNKNOWN
video0:0:candidate:1876313031 1 tcp 1518222591 ::1 51551 typ host tcptype passive generation 0 ufrag rwx/ network-id 2::UNKNOWN
video0:0:candidate:344579997 1 tcp 1518149375 127.0.0.1 41007 typ host tcptype passive generation 0 ufrag rwx/ network-id 1::UNKNOWN
video0:0:candidate:593469510 1 udp 41885439 172.31.0.169 13744 typ relay raddr 178.235.191.135 rport 13607 generation 0 ufrag rwx/ network-id 3 network-cost 10:turn:3.70.23.20:3478?transport=udp:UNKNOWN
ICE 消息的顺序似乎没有保留。
完整日志的差异(互联网左侧,本地右侧):https://www.diffchecker.com/elEA6rkJ
ICE 消息差异:https://www.diffchecker.com/C1TzPcMm
【问题讨论】:
您使用的是什么 GStreamer 版本?某些版本中存在一些错误... 1.18.5 这似乎是最新版本。但是版本控制是一团糟 你使用“notify::ice-gathering-state”通知吗?如果是,它甚至在 1.18.5 中都已损坏。 我错了notify::ice-gathering-state
已在 1.17.1...
【参考方案1】:
在你的情况下我会怎么做:
-
为 create-offer/create-answer/set-offer/set-answer 请求添加日志
为每个传入/传出的 Ice Candidate 和
end-of-candidates
添加日志
然后查看日志并检查:
-
所有 Ice 候选者都在真正交付给对方。
end-of-candidates
在所有其他 Ice 候选人之后交付。
在 set-offer/set-answer 之后出现的 Ice 候选人
双方都可以真正访问您的 STUN/TURN 服务器(使用 https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/)
您在 STUN/TURN 服务器上配置了 IPv6(一些 GSM 提供商根本无法使用 IPv4)
更新 1
根据日志,您的 Android 设备具有 IPv4。因此,现在无需担心 IPv6。
关于end-of-candidates
- 你可以看看我是如何用webrtcbin
here 生成它的。
Android的类似代码:
private val connectionObserver = object: PeerConnection.Observer
// ... some overrides skipped ...
override fun onIceCandidate(candidate: IceCandidate)
Log.d(TAG, "onIceCandidate \"$candidate\"")
override fun onIceGatheringChange(state: PeerConnection.IceGatheringState)
Log.d(TAG, "IceGathering state: $state")
if(state == PeerConnection.IceGatheringState.COMPLETE)
Log.d(TAG, "onIceCandidate \"a=end-of-candidates\"")
// ... some overrides skipped ...
还请检查以下内容:
在安卓上
-
对于每一位即将到来的 Ice 候选人,您都可以直接致电
org.webrtc.PeerConnection.addIceCandidate
你在之后 org.webrtc.PeerConnection.setRemoteDescription
打电话
在树莓派上
-
你真的是打电话给
g_signal_emit_by_name
和 add-ice-candidate
为每一位即将到来的 Ice 候选人
更新 2
我注意到您的中继 Ice Candidate 指向专用网络 IP (172.31.0.169
)。这可能意味着您的 TURN 服务器配置错误。
【讨论】:
嗨@RSATom,感谢您的回答!我们改进了我们的日志记录(见编辑)并遵循您的清单。一切看起来都还不错,但是……这两种情况都没有end-of-candidates
通信。此外,我们在转向服务器上为 IPv4 和 IPv6 开放了端口,并且 coturn 应该开箱即用地处理 IPv6 流量,但我们不知道如何测试它是否真的被允许。如果您能看看 ICE 候选人并分享您的见解,那就太好了!再次感谢以上是关于WebRTC 连接在本地网络之外不起作用的主要内容,如果未能解决你的问题,请参考以下文章