我们对 webrtc 双向视频和音频流进行了以下设置:
Mobile
Android应用程序使用谷歌网络RTC https://webrtc.org/实现java包装器。测试了这两个库:
implementation 'org.webrtc:google-webrtc:1.0.+'
implementation 'com.github.webrtc-sdk:android:92.4515.03' // https://github.com/webrtc-sdk/android
RPi
Gstreamer 与WebRTC 插件 https://gstreamer.freedesktop.org/documentation/webrtc/index.html?gi-language=c基于GST 示例 https://gitlab.freedesktop.org/gstreamer/gst-examples/-/tree/master/webrtc/sendrecv经过一些修改。
Browser
也稍作修改GST 示例 https://gitlab.freedesktop.org/gstreamer/gst-examples/-/tree/master/webrtc/sendrecv/jsJavaScript 实现。它基于本机浏览器 WebRTC 支持。
TURN
在 Docker 中工作的 Coturn 服务器(科图恩 https://hub.docker.com/r/coturn/coturn).
问题
当从 RPi 调用浏览器或从移动设备调用浏览器时,无论是在本地网络还是通过互联网(通过 TURN 服务器),一切都工作正常。然而,当尝试通过互联网连接 RPi 和 Android 设备时,它会卡住(本地网络也可以)。设备相互通信,协商 SDP 和 ICE 候选者,TURN 服务器正确打开连接,但没有音频/视频。
查看 Android 日志时,第一个区别是没有触发 ICE 连接更改:
PeerConnectionObserver: onStandardizedIceConnectionChange: CHECKING
nor
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 日志根本没有显示任何可疑的内容。
对于进一步调查此问题的任何提示或帮助,我们将不胜感激。
EDIT:
根据 @RSATom 的建议,我们更仔细地查看了发送的 ICE 和 SDP 消息,没有发现任何差异。对于通过互联网和本地进行的移动 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 https://www.diffchecker.com/elEA6rkJ
ICE 消息差异:https://www.diffchecker.com/C1TzPcMm https://www.diffchecker.com/C1TzPcMm
EDIT 2:
我错过了一些日志不存在。提供通过互联网连接的完整日志差异(工作与不工作)here https://www.diffchecker.com/KBZAJp0c。有一些区别:
- 无效的连接会错过许多通知连接创建和保持活动的日志,并且仍然显示以下内容:
tag: basic_ice_controller.cc
message: (line 541): Sorting 0 available connections
- 对于无效连接 RTP SSRC
transport_cc
已关闭
- Gstreamer 使用流别名(例如
video0
and audio0
),然后会导致 ICE 候选错误,如下所示:
ReadyToUseRemoteCandidate: Invalid candidate. Mid 0 specified but no media section with that mid found.
- TCP TURN 请求失败:
LS_INFO
tag: turn_port.cc
message: (line 375): Port[31f33800:video0:1:0:relay:Net[lo:127.0.0.x/8:Loopback:id=1]]: Trying to connect to TURN server via tcp @ sicdev-turn.ddns.net:3478
LS_INFO
tag: android_network_monitor.cc
message: (line 422): Find network handle.
LS_WARNING
tag: android_network_monitor.cc
message: (line 307): BindSocketToNetwork unable to find network handle for addr: 127.0.0.x ifname: lo
LS_VERBOSE
tag: physical_socket_server.cc
message: (line 207): Binding socket to loopback address failed; result: -3
LS_ERROR
tag: basic_packet_socket_factory.cc
message: (line 186): TCP connect failed with error 22
LS_ERROR
tag: turn_port.cc
message: (line 379): Failed to create TURN client socket