大约六个月前,我能够用PHP成功编写自己的WebSocket服务器脚本。这样,我就可以在本地主机上设置WebRTC视频聊天服务。在意识到要进行部署之前,我很高兴,我需要一个可以访问套接字的Web服务器。
不幸的是,没有共享的Web托管允许套接字,并且所有提供套接字的Web服务器都很昂贵。虽然这不是一个大规模的有效解决方案,但是为了建立一个演示来展示给人们看,我想将信令方法从WebSocket更改为Ajax,以便可以展示我制作的WebRTC视频聊天服务。
为此,过去几天来我一直在尝试编写一些代码,但未能成功地使WebRTC同行捕获彼此的视频。
目前,当一个客户端连接到脚本时,我正在使用Ajax将请求发送到PHP脚本,该脚本检查数据库中是否还有其他活动用户。如果不是,则脚本然后创建一个报价,并将该报价放置在数据库中。之后,客户端每秒轮询一个单独的PHP脚本,以检查来自另一个连接到该脚本的客户端的答案。
然后,我从另一个客户端连接到脚本,该客户端查询相同的PHP脚本和数据库,然后意识到活动用户(第一个连接)已经发布了要约,第二个客户端获取并设置了要约。描述。然后,第二个客户端创建一个答案,并将其放置在数据库中。
此时,第一个客户端(正在每秒轮询数据库一次)检测到存在答案,并将该答案设置为第一个客户端的远程描述。不幸的是,即使在成功完成所有这些操作后,其他客户端的视频也没有弹出。
所以这是我很困惑的地方,有三个(多部分)问题:
1)我以为在两个客户端都设置了本地描述之后,将该本地描述发送给另一个客户端,并且另一个接收到该描述的客户端将其作为远程描述发送给onaddstream事件,因此我可以显示远程视频。但是,这没有发生。在我使用WebSocket之前,此方法运行良好,但对于纯Ajax则根本不起作用。我特别想念什么吗?在过去的六个月中,WebRTC规范是否发生了根本变化?我曾尝试查看WebRTC规范,但没有看到任何重大变化。
2)在对无法使用Ajax感到沮丧之后,我回到了WebSocket版本并将其加载到本地主机上。自上次使用它以来,我根本没有更改过代码(六个月前运行良好),但是现在,当我尝试使用它时,有时它可以工作,有时却不起作用。有时,我会收到与无法设置本地和/或远程描述有关的错误。这是怎么回事?规格上是否有更改会导致这种情况发生?与此相关的是,即使我无法使用Ajax版本弹出远程视频,但我一直在向控制台回显很多内容,似乎也使用了Ajax版本,有时是本地的和两个客户的远程描述均已成功建立,有时无论出于什么原因尝试设置本地/远程描述时都会发生错误,即使我每次都运行完全相同的脚本而没有任何更改。我使用的是最新版的Chrome,并且开始怀疑它是否存在错误或其他问题。
3)是否需要onicecandidate事件处理程序才能建立连接?我的假设是,同龄人可以仅凭有效的要约和答案建立联系,而onicecandidate事件用于提供替代路线等,这可以导致更好的联系(但不是必需的)。我错了吗?如果需要onicecandidate信息,您如何建议我将Ajax作为信号传递方法来处理呢?
我知道很多信息和很多问题,但是任何人都可以提供的任何信息/见解将不胜感激。在过去的几天里,我一直把头撞在桌子上,试图解决这个问题,但没有任何意义。
关于您的应用的第一条建议。偶尔工作/不工作是要查看当前的在线工作实现。互联网上有很多WebRTC演示。
关于AJAX:为什么不起作用?我目前正在从事与您相同的工作,并且 每次 都可以正常工作(我暂时无法透露消息来源)。客户端不断以固定的时间间隔轮询服务器,他们可以通过这种方式将SDP描述/ ICE候选对象发送到特定的其他客户端。服务器充当一个简单的桥梁(这是信令的基础)。
无论是WebSocket,AJAX还是IPoAC,只要您将他需要的一切转移到另一个客户端(在适当的时候,稍后再介绍),它就可以正常工作。我什至进行了演示,您在其中使用文本区域手动复制/粘贴了SDP描述和ICE候选者,然后单击按钮以在信令过程中前进,当然也可以正常工作。
现在:是的,您需要ICE候选人。看一下我刚刚在Chromium 27上使用的示例 SDP报价 块createOffer:
createOffer
v=0 o=- 3866099361 2 IN IP4 127.0.0.1 s=- t=0 0 a=group:BUNDLE audio video a=msid-semantic: WMS 9kTlKaNe1exIs6JgEFYfXlu6E5f4B5R3I2D8 m=audio 1 RTP/SAVPF 111 103 104 0 8 107 106 105 13 126 c=IN IP4 0.0.0.0 a=rtcp:1 IN IP4 0.0.0.0 a=ice-ufrag:l8Qu31Vu4VG5YApS a=ice-pwd:TpyQ5iESUH4HvYGE4ay8JUhe a=ice-options:google-ice a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level a=sendrecv a=mid:audio a=rtcp-mux a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:bC5YSe2xCmui0wSxUHWKIi9INbZ2y0VrO1swoZbl a=rtpmap:111 opus/48000/2 a=fmtp:111 minptime=10 a=rtpmap:103 ISAC/16000 a=rtpmap:104 ISAC/32000 a=rtpmap:0 PCMU/8000 a=rtpmap:8 PCMA/8000 a=rtpmap:107 CN/48000 a=rtpmap:106 CN/32000 a=rtpmap:105 CN/16000 a=rtpmap:13 CN/8000 a=rtpmap:126 telephone-event/8000 a=maxptime:60 a=ssrc:1976175890 cname:/+lKYsttecoiyiu5 a=ssrc:1976175890 msid:9kTlKaNe1exIs6JgEFYfXlu6E5f4B5R3I2D8 9kTlKaNe1exIs6JgEFYfXlu6E5f4B5R3I2D8a0 a=ssrc:1976175890 mslabel:9kTlKaNe1exIs6JgEFYfXlu6E5f4B5R3I2D8 a=ssrc:1976175890 label:9kTlKaNe1exIs6JgEFYfXlu6E5f4B5R3I2D8a0 m=video 1 RTP/SAVPF 100 116 117 c=IN IP4 0.0.0.0 a=rtcp:1 IN IP4 0.0.0.0 a=ice-ufrag:l8Qu31Vu4VG5YApS a=ice-pwd:TpyQ5iESUH4HvYGE4ay8JUhe a=ice-options:google-ice a=extmap:2 urn:ietf:params:rtp-hdrext:toffset a=sendrecv a=mid:video a=rtcp-mux a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:bC5YSe2xCmui0wSxUHWKIi9INbZ2y0VrO1swoZbl a=rtpmap:100 VP8/90000 a=rtcp-fb:100 ccm fir a=rtcp-fb:100 nack a=rtpmap:116 red/90000 a=rtpmap:117 ulpfec/90000 a=ssrc:3452335690 cname:/+lKYsttecoiyiu5 a=ssrc:3452335690 msid:9kTlKaNe1exIs6JgEFYfXlu6E5f4B5R3I2D8 9kTlKaNe1exIs6JgEFYfXlu6E5f4B5R3I2D8v0 a=ssrc:3452335690 mslabel:9kTlKaNe1exIs6JgEFYfXlu6E5f4B5R3I2D8 a=ssrc:3452335690 label:9kTlKaNe1exIs6JgEFYfXlu6E5f4B5R3I2D8v0
您是否看到任何可以帮助其他客户端连接到我的计算机的东西?我不这么认为。所有这种ICE机制的目的是,192.168.1.15如果您落后于任何非对称的NAT,或者使用TURN的对称NAT,则使用STUN 收集连接候选对象(如本地的,如“公共”(由ISP分配的公共IP)) 。
192.168.1.15
收到这些ICE候选者后,其他对等方将使用一些预定义的度量对它们进行排序以进行优先级排序,然后发出连接测试以找到合适的候选者。因此,请共享它们:另一个对等方也需要它们(您也需要)。
所以这是我的一些ICE候选人:
a=candidate:303249700 1 udp 2113937151 192.168.50.238 43806 typ host generation 0 a=candidate:303249700 2 udp 2113937151 192.168.50.238 43806 typ host generation 0 a=candidate:1552991700 1 tcp 1509957375 192.168.50.238 35630 typ host generation 0
现在,这些方法是具体的(尽管只是本地的,因为我没有使用任何STUN URL配置RTC对等连接),以便其他对等方连接到我的计算机。
此页面底部有一些有趣的提示。我直言不讳地告诉你为什么你应该遵循这些原则或者为什么它们首先存在,但是我确实遵循了它们,没有任何信号问题。他们来了:
您可以通过拥有一些WebRTC有限状态机来在客户端进行所有管理。请参阅参考页以了解他的意思是 远程流开始流动 。
尝试共享ICE候选人并将其添加到相反的一侧,并至少遵循提示#1和#3,您的应用程序应该可以再次运行。
您询问了在ICE候选人对于共享至关重要的情况下如何将ICE候选人从对等方转移到另一方。要使用AJAX共享内容,无论这些内容是什么,都可以使用邮箱。我相信您已经通过在数据库中放置客户端的内容来完成此操作。
每当对等方需要将某项内容发送给另一方时,请尽快发送(使用AJAX)。在服务器端,将此“邮件”放在目标客户端的邮箱中。当对等方(定期)轮询服务器是否有新邮件时,请为其提供所有新邮件。
创建SDP报价后,会快速生成ICE候选者。所有这些ICE候选对象和SDP描述可能会在几毫秒内进入目标邮箱。目标对等方很有可能立即轮询所有需要的东西。即使ICE候选人迟到,它的下一次投票也会得到它。