WebRTC代码疑难解答

时间:2012-12-19 20:49:06

标签: webrtc

我用这个把头发拉了出来。大约一个月前,我能够使用来自SignalR的优秀人员的一些示例代码,将概念验证WebRTC演示放在一起。该演示位于here,其来源为here,它可以完成它应该做的事情。

但是当我把这些代码移到我们的实际应用程序中时,我还没有能够让它运行起来。当然代码必须得到显着改变 - 不同的后端,不同的框架和支持代码,支持多个同时连接,这类事情 - 但核心逻辑非常相似。但我无法让它发挥作用。

我在这里整理了一个示例应用程序来说明问题:

https://bitbucket.org/smithkl42/signalr.webrtc

核心WebRTC逻辑就在这个TypeScript文件中:

https://bitbucket.org/smithkl42/signalr.webrtc/src/tip/SignalR.WebRTC/Scripts/Media/WebRTC.ts?at=default

它有几百行,所以我不打算在这里发帖,但你可以点击上面的链接看到它。

运行时会产生如下输出:

  

12:17:58.531 WebRTCController.call():准备完成后调用7d9e0d39-5047-4afe-86e5-e6e01b9f5955

     

12:17:58.533 WebRTCController.prepareForCall():准备呼叫:localSessionId =' 39d2df53-6854-415a-8748-b5230eda2eb1&#39 ;; remoteSessionId =' 7d9e0d39-5047-4afe-86e5-e6e01b9f5955'

     

12:18:0.139对象。():用户已授予媒体设备访问权限,因此继续准备呼叫

     

12:18:0.141 Connection.createPeerConnection():创建对等连接;使用stunServer stun:stun1.l.google.com:19302

     

12:18:0.144():准备完成。创建和发送JSEP产品。 util.js中:21

     

12:18:0.272 Connection.handleIceCandidate():STUN服务器找到了一个ICE候选者(event.type =' icecandidate')。

     

12:18:0.282 Connection.handleIceCandidate():STUN服务器找到了一个ICE候选者(event.type =' icecandidate')。

     

(更像那样)

     

12:18:0.655 WebRTCController.handleJsepAnswer():从7d9e0d39-5047-4afe-86e5-e6e01b9f5955处理JsepAnswer

     

12:18:0.694对象。():将ICE候选者发送到远程机器:{" sdpMLineIndex":0," sdpMid":" audio" ,"候选人":" a =候选人:2999745851 1 udp 2113937151 192.168.56.1 62978 typ host generation 0 \ r \ n"}

     

12:18:0.706对象。():将ICE候选者发送到远程机器:{" sdpMLineIndex":0," sdpMid":" audio" ,"候选人":" a =候选人:2999745851 2 udp 2113937151 192.168.56.1 62978 typ host generation 0 \ r \ n"}

     

(更像那样)

但是它永远不会连接,即来自另一方的视频永远不会开始播放。在信令层,我可以通过日志和逐步通过代码看出第一个浏览器正在发送JSEP报价;第二个浏览器正在接收它,存储它并发送回适当的JSEP答案;并且第一台机器正在存储该答案。然后每个peerConnection找到ICE候选者并将它们发送到远程机器;并且每个peerConnection正在接收并且显然正在尝试那些ICE候选者;并且peerConnections甚至引发了onaddstream事件。但视频从未开始播放。

peerConnection对象的状态如下所示:

(iceGatheringState=new; iceState=starting; readyState=active)

令人沮丧的是,每隔一段时间,也许是20次中的一次, 工作,即两个视频都显示出来。所以我没有所有错误。这听起来像是某种时间问题 - 但我无法弄清楚它是什么。据我所知,WebRTC对象(特别是RTCPeerConnection)中没有太多可以告诉你出了什么问题。

我不想让别人为我做故障排除,但是......好吧,我的选项已经用完了。有没有人看到我做错了什么?

更新2012-12-19 :我取得了一些进展。我意识到我正在同步调用peerConnection.setLocalDescription(),即没有指定回调。所以现在我有一些看起来像这样的代码:

// Answer the call by sending a JsepAnswer message.
connection.peerConnection.createAnswer(
    answer => {
        connection.peerConnection.setLocalDescription(answer, () => {
            var signalState: mData.SignalState = {
                FromSessionId: connection.localSessionId,
                ToSessionId: connection.remoteSessionId,
                Message: JSON.stringify(answer)
            };
            me.roomHub.server.jsepAnswer(signalState);
            mUtil.log("Sent JSEP answer: " + signalState.Message);
            connection.readyForIceCandidates.resolve();
        },
        error => {
            mUtil.error("Error setting local description from created answer: " + error + "; answer=" + JSON.stringify(answer));
        });
    },
error => {
    mUtil.error("Error creating answer: " + error);
}, me.mediaConstraints);

setLocalDescription()错误回调显示此错误:

  

16:14:42.439 WebRTCController.handleJsepOffer():从创建的答案设置本地描述时出错:SetLocalDescription失败。 answer = {" sdp":" v = 0 \ r \ no = - 439659381 2 IN IP4 127.0.0.1 \ r \ ns = - \ r \ nt = 0 0 \ r \ na = group:BUNDLE audio video \ r \ nn = msid-semantic:WMS u9fhVrWeLLweqb5ubLkw61Ijsh6BM6vZLhjf \ r \ nm = audio 1 RTP / SAVPF 103 104 111 0 8 107 106 105 13 126 \ r \ nc = IN IP4 0.0.0.0 \ r \ nn = rtcp:1 IN IP4 0.0.0.0 \ r \ nn = na = ice-ufrag:vOKflTJ56gV0R9i0 \ r \ nn = na = ice-pwd:9nuXPMDvQ2mZATFCQyEzPRQz \ r \ nn = sendrecv \ r \ n \ na = mid:audio \ r \ n = na = rtcp- mux \ r \ nNa = crypto:1 AES_CM_128_HMAC_SHA1_80 inline:m9q9pmLgLuFnfFC09KXKW5p8TjsKk + VdqX0OWv77 \ r \ na = rtpmap:103 ISAC / 16000 \ r \ na = rtpmap:104 ISAC / 32000 \ r \ nn = rtpmap:111 opus / 48000/2 \ r \ n = na = rtpmap:0 PCMU / 8000 \ r \ n = na = rtpmap:8 PCMA / 8000 \ r \ n = na = rtpmap:107 CN / 48000 \ r \ na = rtpmap:106 CN / 32000 \ r \ nn = rtpmap :105 CN / 16000 \ r \ n = na = rtpmap:13 CN / 8000 \ r \ nn = rtpmap:126电话事件/ 8000 \ r \ n = na = ssrc:548068416 cname:IXg8QRisWrd7 + 7f8 \ r \ na = ssrc:548068416 msid:u9fhVrWeLLweqb5ubLkw61Ijsh6BM6vZLhjf a0 \ r \ na = ssrc:548068416 mslabel:u9fhVrWeLLweqb5ubLkw61Ijsh6BM6vZLhjf \ r \ na = ssrc:548068416 label:u9fhVrWeLLweqb5ubLkw61Ijsh6BM6vZLhjfa0 \ r \ nm = video 1 RTP / S AVPF 100 116 117 \ r \ nc = IN IP4 0.0.0.0 \ r \ nn = rtcp:1 IN IP4 0.0.0.0 \ r \ n = na = ice-ufrag:vOKflTJ56gV0R9i0 \ r \ na = ice-pwd:9nuXPMDvQ2mZATFCQyEzPRQz \ r \ na = sendrecv \ r \ nn = mid:video \ r \ n = na = rtcp-mux \ r \ n \ nn = crypto:1 AES_CM_128_HMAC_SHA1_80 inline:m9q9pmLgLuFnfFC09KXKW5p8TjsKk + VdqX0OWv77 \ r \ na = rtpmap:100 VP8 / 90000 \ r \ na = rtpmap :116 red / 90000 \ r \ n = na = rtpmap:117 ulpfec / 90000 \ r \ n = na = ssrc:1460425980 cname:IXg8QRisWrd7 + 7f8 \ r \ na = ssrc:1460425980 msid:u9fhVrWeLLweqb5ubLkw61Ijsh6BM6vZLhjf v0 \ r \ na = ssrc:1460425980 mslabel :u9fhVrWeLLweqb5ubLkw61Ijsh6BM6vZLhjf \ r \ n = na = ssrc:1460425980标签:u9fhVrWeLLweqb5ubLkw61Ijsh6BM6vZLhjfv0 \ r \ n","输入":"回答"}

现在我只需要弄清楚为什么直接来自createAnswer()方法的特定SDP失败了。

更新2012-12-20 :我已在此处创建了问题的在线演示:http://srdemo.alanta.com/。我还打开了Chrome调试日志记录,结果我发现了一堆看起来像这样的错误:

[6584:7308:1220/091356:ERROR:rtc_peer_connection_handler.cc(84)] Native session description is null. [6584:7308:1220/091356:ERROR:rtc_peer_connection_handler.cc(84)] Native session description is null. [6584:7308:1220/091356:ERROR:rtc_peer_connection_handler.cc(84)] Native session description is null. [6584:7308:1220/091356:ERROR:rtc_peer_connection_handler.cc(84)] Native session description is null. [6584:7308:1220/091356:ERROR:rtc_peer_connection_handler.cc(84)] Native session description is null.

不确定他们与我的问题有什么关系,但我还在继续调查。

*编辑2012-12-20:我已经管理(我认为)以缩小问题范围。有关更多详细信息,请参阅this question

1 个答案:

答案 0 :(得分:4)

想出来。事实证明,SignalR 1.0 RC1中有一个错误,它将字符串中的任何“+”更改为空格。因此,SDP中的行看起来像这样:

a=ice-pwd:qZFVvgfnSso1b8UV1SUDd2+z

变成了这个:

a=ice-pwd:qZFVvgfnSso1b8UV1SUDd2 z

但是因为不是每个SDP在关键线上都有“+”,所以有时它会起作用。一切都解释了。

已向使用SignalR的好人报告了该错误(请参阅https://github.com/SignalR/SignalR/issues/1194),与此同时,围绕相关字符串的简单encodeURIComponent()decodeURIComponent()修复了该错误。