WebRTC 连接在本地网络之外无法工作

2024-01-12

我们对 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。有一些区别:

  1. 无效的连接会错过许多通知连接创建和保持活动的日志,并且仍然显示以下内容:
tag: basic_ice_controller.cc 
message: (line 541): Sorting 0 available connections
  1. 对于无效连接 RTP SSRCtransport_cc已关闭
  2. Gstreamer 使用流别名(例如video0 and audio0),然后会导致 ICE 候选错误,如下所示:
ReadyToUseRemoteCandidate: Invalid candidate. Mid 0 specified but no media section with that mid found.
  1. 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

对于你的情况我会做什么:

  1. 添加 create-offer/create-answer/set-offer/set-answer 请求的日志
  2. 为每个传入/传出的 Ice Candidate 添加日志end-of-candidates

然后查看日志并检查:

  1. 所有冰候选人都真正为对方提供帮助。
  2. end-of-candidates在所有其他 Ice 候选人之后交付。
  3. Ice 候选人在设定要约/设定答案后前来
  4. 您的 STUN/TURN 服务器确实可以被双方访问(通过https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/ https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/)
  5. 您在 STUN/TURN 服务器上配置了 IPv6(某些 GSM 提供商根本无法使用 IPv4)

Upd 1

根据日志,您的 Android 设备具有 IPv4。所以现在不需要担心IPv6。 关于end-of-candidates- 你可以看看我是如何生成它的webrtcbin here https://github.com/WebRTSP/RtStreaming/blob/master/GstRtStreaming/GstWebRTCPeer.cpp#L333。 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 ...
    }

另请检查以下内容:

在安卓上

  1. 你真的是打电话org.webrtc.PeerConnection.addIceCandidate对于每一位即将到来的 Ice 候选人
  2. 你做吧after org.webrtc.PeerConnection.setRemoteDescription call

On RPi

  1. 你真的是打电话g_signal_emit_by_name with add-ice-candidate对于每一位即将到来的 Ice 候选人

Upd 2

我注意到你的中继 Ice Candidate 指向专用网络 IP (172.31.0.169)。这可能意味着您的 TURN 配置错误 服务器。


Upd 3

请检查https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/ https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/你得到relay具有有效 IP 的 Ice 候选者both sides.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

WebRTC 连接在本地网络之外无法工作 的相关文章

  • 模仿 youtube/gmail 应用程序的导航抽屉

    背景 近几个月来 谷歌发布了Youtube 应用程序 http www androidpolice com 2013 08 19 breaking massive youtube for android v5 0 update brings
  • 使用 ActiveAndroid 库存储 HashMap

    我有一堂课 Table name Control public class Control extends Model Column private String name Column private Map
  • Android中如何通过ViewModel类在Activity和Fragment之间共享数据?

    我想知道是否可以传递一个在 Activity 类中声明的字符串数据 并将该字符串数据传递给 ViewModel 类 然后将数据传递给 Fragment 类 视图模型类 class TimeTableViewModel extends Vie
  • 使用 NEON 内在函数除以浮点数

    我当时正在处理四个像素的图像 这是在armv7对于 Android 应用程序 我想分一个float32x4 t向量由另一个向量组成 但其中的数字与大约不同0 7 to 3 85 在我看来 除法的唯一方法是使用右移 但这是针对一个数字2 n
  • 如何解决:无法解析:com.mapbox.mapboxsdk:mapbox-android-sdk:9.5.0

    我在Android studio中尝试使用mapbox时遇到这个问题无法解析 com mapbox mapboxsdk mapbox android sdk 9 5 0 问题是什么 我的 build gradle 依赖项 dependenc
  • 使用 setText 更改文本后如何更新屏幕?

    现在我正在使用以下代码来更新TextView txtMain setText new text 该代码执行后 屏幕不会更新新文本 有没有办法可以强制文本立即更新 该代码执行后 屏幕不会更新新文本 一旦您将控制权归还给 Android 就应该
  • 如何调试“com.android.okhttp”

    在android kitkat中 URLConnection的实现已经被OkHttp取代 如何调试呢 OkHttp 位于此目录中 external okhttp android main java com squareup okhttp 当
  • Android中如何使用JNI获取设备ID?

    我想从 c 获取 IMEIJNI 我使用下面的代码 但是遇到了未能获取的错误cls 它总是返回NULL 我检查了环境和上下文 它们都没有问题 为什么我不能得到Context班级 我在网上搜索了一下 有人说我们应该使用java lang Ob
  • 是否可以将自定义属性添加到 Android 资源的样式中?

    我在我的项目中使用视图流组件 它允许开发人员覆盖一些属性 例如
  • Monodroid 示例/带有源代码的小部件

    我是一名 NET 开发人员 我对用 C 开发 Android 应用程序感兴趣 并且我得到了 monodroid 是否有任何来源可以让我获得 monodroid 示例应用程序 带有源代码 这将帮助我在 monodroid 中开发应用程序 或者
  • 如何将设备屏幕位置转换为发送事件位置?

    我知道关于input tap x yshell 命令 但是 我想了解如何 使用执行单击sendevent命令 我能够通过以下命令实现它 sendevent dev input event5 3 53 X sendevent dev inpu
  • Android Gradle 问题 - Flutter / Dart

    我的 Gradle 同步有问题 我使用 IntelliJ 和 Android Studio 构建 Flutter Dart 应用程序 我添加了 2 个新的依赖项 现在 Gradle 出现了问题 在 Android Studio 中一切正常
  • 通知声音不适用于 api 10 android

    我用这个功能来显示状态notification 一切正常 但没有声音播放notification public void notifiction main String ticker String title String text int
  • 将非 Android 项目添加到 Android 项目

    我在 Eclipse 中有三个项目 Base Server 和 AndroidClient Base和Server是Java 1 7项目 而AndroidClient显然是一个android项目 基础项目具有在服务器和 Android 客户
  • Android NDK 支持区域设置吗?

    我真正想做的就是使用格式化日期strftime x 以正确的顺序 在大多数平台上调用setlocale 足够 在 Android 上 我不断收到 美国日期 那么 Android 不支持语言环境吗 No setlocale and strft
  • PhoneGap 1.4 封装 Sencha Touch 2.X - 性能怎么样?

    我正在构建一个多平台平板电脑应用程序 仅使用其 Webview 使用 Phonegap 1 4 对其进行包装 然后使用 Sencha Touch 2 框架发挥我的魔力 我所说的多平台是指 iOS 5 X 和 Android 3 0 目前 到
  • react-native android fontFamily 不生效

    问题一 我在index android js的欢迎样式中添加了fontFamily 但没有效果 fontFamily 真的可以在 Android 上使用吗 欢迎 字体大小 20 fontFamily roboto thin 文本对齐 居中
  • 在android中从SD卡上传图像到facebook

    我无法从 SD 卡上传 Facebook 上的图像 我使用了下面的代码 但它没有给我错误 但同时它没有上传图像 byte data null try FileInputStream fis new FileInputStream filep
  • Android TextureView 和硬件加速

    我正在尝试实现上所示的示例这一页 http developer android com reference android view TextureView html 我已经在运行 android 4 及以上版本的三种不同设备上进行了尝试
  • Android View Canvas onDraw 未执行

    我目前正在开发一个自定义视图 它在画布上绘制一些图块 这些图块是从多个文件加载的 并将在需要时加载 它们将由 AsyncTask 加载 如果它们已经加载 它们只会被绘制在画布上 这工作正常 如果加载了这些图片 AsyncTask 就会触发v

随机推荐