问题描述
我们有以下WebRTC双向视频和音频流的设置:
手机
使用Google WebRTC实现Java包装的Android应用程序。已测试这两个库:
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-examplesJava脚本实现。它基于本机浏览器WebRTC支持。
转弯
CoTurn服务器在Docker中工作(coturn/coturn)。
问题
当从RPI调用到浏览器或从移动设备调用到浏览器时,无论是在本地网络还是通过互联网(通过TURN服务器),一切都运行正常。然而,当试图通过互联网连接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
转弯日志完全没有显示任何可疑之处。
如有任何提示或帮助进一步调查此问题,我将不胜感激。
编辑:
在@RSATom的建议下,我们更仔细地查看了正在发送的ICE和SDP消息,没有发现任何丢弃。对于通过互联网和本地的移动-RPI通信,SDP是相同的。唯一的区别是随机生成的ID。冰块也没有太大区别。它对于第一个发送者(要约者)是相同的,而对于回答者则略有不同,因为它包含话轮详细信息:
通过互联网
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
编辑2:
我错过了一些日志不存在。通过互联网连接的完整日志差异(工作与不工作)可用here。有几点不同:
- 无效连接遗漏了许多通知连接创建和保持连接的日志,但仍显示以下内容:
tag: basic_ice_controller.cc
message: (line 541): Sorting 0 available connections
- 对于无效连接,RTP SSRC
transport_cc
已关闭 - GStreamer使用流别名(如
video0
和audio0
),这会导致ICE候选错误,如下所示:
ReadyToUseRemoteCandidate: Invalid candidate. Mid 0 specified but no media section with that mid found.
- 存在要转换的失败的TCP请求:
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
推荐答案
如果是你的话我会怎么做:
- 添加create-offer/create-answer/set-offer/set-answer请求的日志
- 添加每个传入/传出候选冰块的日志和
end-of-candidates
然后查看日志并检查:
- 所有Ice候选人真的是在向对方传递信息。
end-of-candidates
在所有其他候选冰块之后交付。- Set-Offer/Set-Answer之后的冰块候选人
- 双方都可以访问您的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 ...
}
还请检查以下内容:
在Android上
- 您真的是在为每个即将到来的Ice候选对象调用
org.webrtc.PeerConnection.addIceCandidate
- 在
org.webrtc.PeerConnection.setRemoteDescription
调用 之后
在RPI上
- 您真的为每个即将到来的Ice候选对象调用
g_signal_emit_by_name
WITHadd-ice-candidate
更新%2
我注意到您的中继冰候选指向内网IP(172.31.0.169
)。这可能意味着您的配置错误。服务器。
更新%3
请与https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/确认relay
您的两面都有有效的IP。
这篇关于WebRTC连接在本地网络之外无法正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!