- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
背景资料
您好,我正在尝试在 Android 中构建一个 WebRTC 客户端,该客户端订阅正在使用 NodeJS 和 JavaScript 广播的视频源。
广播公司代码可以完整查看in this lovely article by Gabriel Tanner .
在 localhost 下的 http://localhost:4000/broadcaster.html
下运行时效果很好在 Chrome 中,然后从网络上的另一台设备访问我的 IP 地址。我可以看到视频,它几乎是实时的。
我已经尝试过使用两种不同的网络摄像头设备,内置和 USB 网络摄像头,但即使 JavaScript Broadcaster 和客户端工作正常,Android 客户端也无法工作。
手头的任务
在遵循教程并让示例运行之后,我决定尝试实现我自己的 Android 应用程序,可以查看整个源代码 right here on my GitHub .
我已经按照这个地方的各种教程进行操作,问题总是源于尝试设置远程描述,该描述使用以下代码完成:
private void setRemoteDescription(Object[] arguments) {
JSONObject message = (JSONObject) arguments[1];
try {
String sdp = message.getString("sdp");
SessionDescription sessionDescription = new SessionDescription(OFFER, sdp);
peerConnection.setRemoteDescription(new SimpleSdpObserver(), sessionDescription);
} catch (JSONException e) {
Log.e(TAG, "setRemoteDescription: failed to parse JSON", e);
}
}
就像我说的那样,可以在 GitHub 中查看完整的代码,我不想把这篇文章弄得太乱,但基本上按照 Gabriel 的教程,当套接字在连接时发出“观察者”(Android 应用程序正确地做到了)它会然后发回一个“offer”,然后在客户端监听,如下所示:
private void bindSocketEvents() {
socket.on(EVENT_CONNECT, args -> {
socket.emit("watcher");
}).on("broadcaster", args -> {
socket.emit("watcher");
}).on("offer", args -> {
setRemoteDescription(args);
performAnswer();
}).on("candidate", this::addIceCandidate);
}
然后我们看到,在“提供”时,我们使用 JavaScript 中的 args 调用代码并尝试设置远程描述,但它没有这样做。
v=0
o=- 7040957491050894781 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE 0
a=extmap-allow-mixed
a=msid-semantic: WMS l91G3Ekmme9tlvEso1ApTqS6djaxtsamgfLu
m=video 9 UDP/TLS/RTP/SAVPF 96 97 98 99 100 101 102 121 127 120 125 107 108 109 35 36 124 119 123
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:XEnc
a=ice-pwd:2PyQmLOm9YPPf1Pozvonticd
a=ice-options:trickle
a=fingerprint:sha-256 64:22:D7:93:FD:6C:A9:94:E3:65:76:B0:DB:4E:E9:8E:91:46:56:87:B1:E3:E9:B3:24:D0:CF:A5:3F:91:0A:FD
a=setup:actpass
a=mid:0
a=extmap:1 urn:ietf:params:rtp-hdrext:toffset
a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:3 urn:3gpp:video-orientation
a=extmap:4 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=extmap:5 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay
a=extmap:6 http://www.webrtc.org/experiments/rtp-hdrext/video-content-type
a=extmap:7 http://www.webrtc.org/experiments/rtp-hdrext/video-timing
a=extmap:8 http://www.webrtc.org/experiments/rtp-hdrext/color-space
a=extmap:9 urn:ietf:params:rtp-hdrext:sdes:mid
a=extmap:10 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
a=extmap:11 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id
a=sendrecv
a=msid:l91G3Ekmme9tlvEso1ApTqS6djaxtsamgfLu 7eb4296c-f3e4-4e95-9f6f-05aa386a3176
a=rtcp-mux
a=rtcp-rsize
a=rtpmap:96 VP8/90000
a=rtcp-fb:96 goog-remb
a=rtcp-fb:96 transport-cc
a=rtcp-fb:96 ccm fir
a=rtcp-fb:96 nack
a=rtcp-fb:96 nack pli
a=rtpmap:97 rtx/90000
a=fmtp:97 apt=96
a=rtpmap:98 VP9/90000
a=rtcp-fb:98 goog-remb
a=rtcp-fb:98 transport-cc
a=rtcp-fb:98 ccm fir
a=rtcp-fb:98 nack
a=rtcp-fb:98 nack pli
a=fmtp:98 profile-id=0
a=rtpmap:99 rtx/90000
a=fmtp:99 apt=98
a=rtpmap:100 VP9/90000
a=rtcp-fb:100 goog-remb
a=rtcp-fb:100 transport-cc
a=rtcp-fb:100 ccm fir
a=rtcp-fb:100 nack
a=rtcp-fb:100 nack pli
a=fmtp:100 profile-id=2
a=rtpmap:101 rtx/90000
a=fmtp:101 apt=100
a=rtpmap:102 H264/90000
a=rtcp-fb:102 goog-remb
a=rtcp-fb:102 transport-cc
a=rtcp-fb:102 ccm fir
a=rtcp-fb:102 nack
a=rtcp-fb:102 nack pli
a=fmtp:102 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f
a=rtpmap:121 rtx/90000
a=fmtp:121 apt=102
a=rtpmap:127 H264/90000
a=rtcp-fb:127 goog-remb
a=rtcp-fb:127 transport-cc
a=rtcp-fb:127 ccm fir
a=rtcp-fb:127 nack
a=rtcp-fb:127 nack pli
a=fmtp:127 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42001f
a=rtpmap:120 rtx/90000
a=fmtp:120 apt=127
a=rtpmap:125 H264/90000
a=rtcp-fb:125 goog-remb
a=rtcp-fb:125 transport-cc
a=rtcp-fb:125 ccm fir
a=rtcp-fb:125 nack
a=rtcp-fb:125 nack pli
a=fmtp:125 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f
a=rtpmap:107 rtx/90000
a=fmtp:107 apt=125
a=rtpmap:108 H264/90000
a=rtcp-fb:108 goog-remb
a=rtcp-fb:108 transport-cc
a=rtcp-fb:108 ccm fir
a=rtcp-fb:108 nack
a=rtcp-fb:108 nack pli
a=fmtp:108 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42e01f
a=rtpmap:109 rtx/90000
a=fmtp:109 apt=108
a=rtpmap:35 AV1X/90000
a=rtcp-fb:35 goog-remb
a=rtcp-fb:35 transport-cc
a=rtcp-fb:35 ccm fir
a=rtcp-fb:35 nack
a=rtcp-fb:35 nack pli
a=rtpmap:36 rtx/90000
a=fmtp:36 apt=35
a=rtpmap:124 red/90000
a=rtpmap:119 rtx/90000
a=fmtp:119 apt=124
a=rtpmap:123 ulpfec/90000
a=ssrc-group:FID 4173041010 2470630943
a=ssrc:4173041010 cname:VrEB0NYLt23UUzRD
a=ssrc:4173041010 msid:l91G3Ekmme9tlvEso1ApTqS6djaxtsamgfLu 7eb4296c-f3e4-4e95-9f6f-05aa386a3176
a=ssrc:4173041010 mslabel:l91G3Ekmme9tlvEso1ApTqS6djaxtsamgfLu
a=ssrc:4173041010 label:7eb4296c-f3e4-4e95-9f6f-05aa386a3176
a=ssrc:2470630943 cname:VrEB0NYLt23UUzRD
a=ssrc:2470630943 msid:l91G3Ekmme9tlvEso1ApTqS6djaxtsamgfLu 7eb4296c-f3e4-4e95-9f6f-05aa386a3176
a=ssrc:2470630943 mslabel:l91G3Ekmme9tlvEso1ApTqS6djaxtsamgfLu
a=ssrc:2470630943 label:7eb4296c-f3e4-4e95-9f6f-05aa386a3176
错误
peerConnection.createAnswer
:
2021-11-12 13:45:52.819 26795-27780/au.com.australiandroid.androidclient D/CustomPeerConnectionObs: onSignalingChange: new signaling state is HAVE_REMOTE_OFFER
2021-11-12 13:45:52.820 26795-27780/au.com.australiandroid.androidclient E/SimpleSdpObserver: onSetFailure: failed to set the remote description: Failed to set remote offer sdp: Failed to set remote video description send parameters for m-section with mid='0'.
2021-11-12 13:45:52.820 26795-27780/au.com.australiandroid.androidclient E/MainActivity: onCreateFailure: failed to create answer: Session error code: ERROR_CONTENT. Session error description: Failed to set remote video description send parameters for m-section with mid='0'..
如果您有任何关于为什么它无法 setRemoteDescription 的任何信息,或者即使您对如何实现 Android WebRTC 客户端有任何建议,那么此时任何事情都会有所帮助。我已经挣扎了几个星期,我不知道从哪里开始,因为谷歌搜索这个错误没有帮助。要么是因为我根本不理解答案,要么是因为答案不相关。我不知道,但请不要只粘贴指向 Google 热门歌曲的链接,因为我已经阅读了很多。
最佳答案
由于包含 H264 编解码器的报价而触发了错误消息,而 Android 客户端未预期 H264 并且未设置为编码和/或解码此特定硬件编码流。
修复是确保连接工厂设置如下:
private void createPeerConnectionFactory() {
PeerConnectionFactory.InitializationOptions initializationOptions =
PeerConnectionFactory.InitializationOptions.builder(this)
.createInitializationOptions();
PeerConnectionFactory.initialize(initializationOptions);
PeerConnectionFactory.Options options = new PeerConnectionFactory.Options();
VideoEncoderFactory encoderFactory = new DefaultVideoEncoderFactory(rootEglBase.getEglBaseContext(), true, true);
VideoDecoderFactory decoderFactory = new DefaultVideoDecoderFactory(rootEglBase.getEglBaseContext());
peerConnectionFactory = PeerConnectionFactory.builder()
.setOptions(options)
.setVideoDecoderFactory(decoderFactory)
.setVideoEncoderFactory(encoderFactory)
.createPeerConnectionFactory();
List<PeerConnection.IceServer> iceServers = new ArrayList<>();
PeerConnection.RTCConfiguration rtcConfig = new PeerConnection.RTCConfiguration(iceServers);
createPeerConnection(rtcConfig);
}
rootEglBase
之前是通过在 Activity 中定义一个变量来设置的,例如
private EglBase rootEglBase;
然后使用
EglBase.create()
创建它的新实例在 Activity 中
onCreate
方法。
peerConnectionFactory
中的实际获胜线正在定义
encoderFactory
和
decoderFactory
并指定正确的标志来告诉 WebRTC 我们要使用 h264HighProfile。
VideoEncoderFactory encoderFactory = new DefaultVideoEncoderFactory(rootEglBase.getEglBaseContext(), true, true);
哪里第
true
boolean 是启用 VP8 编码,第二个是 H264。
setRemoteDescription
时接受报价。它引导我走上正确的道路,以解决我的代码中仍然存在的许多其他问题。
关于javascript - 为什么我在 Chrome 中运行时在 Android 中收到 "Failed to set remote video description send parameters for m-section with mid=' 0'"错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69937781/
目前我正在尝试创建一个 Web 部署包。所以我在我的项目的根目录中添加了一个 parameters.xml 并指定了一些自定义参数。 我发现我的很多参数都部分相同。所以我想做某种参数引用。寻找这个,我
如何设置我的 Symfony 2 项目以使用 parameters.yml 而不是 parameters.ini? 在 Controller 中,我可以像这样从 parameters.ini 中获取变
有什么建议说明为什么此 AWS CloudFormation 不断回滚吗? { "Description" : "Single Instance", "Resources" : {
PARAMETERS: p_1 TYPE i, p_2 TYPE i. 因此在初始屏幕中,我看到了 2 个文本框,每个参数一个。 如果我填写其中一个,但不按回车键,然后我在第二个上调用 F4 帮助,我
我需要存储 Parameter由 Build() 返回作为 Parameter (因为我将参数存储在一个数组中,另一种方法就是为每个参数数量复制粘贴相同的类太多,因为 c# 没有可变参数泛型)。 问题
我正在为我的 CS 类(class)做作业,它使用了 const,我对何时使用它们感到有点困惑。 这3个函数有什么区别? int const function(parameters) int fu
在 xgboost 的文档中,我读到: base_score [default=0.5] : the initial prediction score of all instances, global
我正在创建一个新的 REST 服务。 向 REST 服务传递参数的标准是什么。在 Java 的不同 REST 实现中,您可以将参数配置为路径的一部分或请求参数。例如, 路径参数 http://www.
在我的程序中,我需要验证传递给程序的参数是一个整数,所以我创建了这个小函数来处理用户键入“1st”而不是“1”的情况。 问题是它根本不起作用。我尝试调试,我只能告诉你参数是 12,long 是 2。(
谁能告诉我如何使用存储在 &rest 指定值中的参数。 我已经阅读了很多,似乎作者只知道如何列出所有参数。 (defun test (a &rest b) b) 这很高兴看到,但并不是很有用。 到目前
我使用 git 有一段时间了,但大多数时候我更喜欢与 Intelij IDEA 的集成。现在,为了扩展我对系统的知识和理解,我决定更多地使用命令行。我观察到的是有两种类型的参数: --paramete
我正在用 RAML 编写一些 REST 文档,但我被卡住了。 我的问题: - 我有一个用于搜索的 GET 请求,它可以采用参数“id”或( 独占或 )“引用”。拥有 只有其中之一 是必须的。 我知道怎
我定义了一个这样的 Action : /secure/listaAnnunci.action /login.jsp 我可以从 Action 内部访问参数吗?谢谢 最佳答案 您需要实现 S
我有一个 TeamCity 8.0.3 项目,其中包含多个配置,其中有一个通用参数(定义为项目参数):targetServerIP .这些配置之一是“一键部署”,它通过使用快照依赖项启动其他配置。我已
try{ Class.forName("com.mysql.jdbc.Driver"); mycon = DriverManager.getConnec
我在实际的 javascript 项目中遇到了一个非常奇怪的情况。我创建了一个自定义事件并将数组放入该事件 $.publish("merilon/TablesLoaded", getTables())
在使用参数数组进行插入/更新期间,可以忽略一个/一些特定行的一个/一些参数。 我提供了一个简单的例子。想象一下,我们有一个包含 3 列的表:X、Y 和 Z。我们想在 block 中执行更新(如果缺少某
如何编写接受未定义参数的函数?我想它可以像那样工作: void foo(void undefined_param) { if(typeof(undefined_param) == int) {
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界. 这篇CFSDN的博客文章PDO版本问题 Invalid parameter number: no
Jenkins 管道作业如下所示: 部分 Jenkinsfile(我们使用脚本化管道)是: properties([parameters([string(defaultValue: "", descr
我是一名优秀的程序员,十分优秀!