const pc1 = new RTCPeerConnection(null);
const pc2 = new RTCPeerConnection(null);
async function call(){
const offer = await pc1.createOffer();
pc1.setLocalDescription(offer);
pc2.setRemoteDescription(offer);
const answer = await pc2.createAnswer();
pc2.setLocalDescription(answer);
pc1.setRemoteDescription(pc2.localDescription);
}
async function showVideo(){
const config={audio:true,video:true};
stream = await navigator.mediaDevices.getUserMedia(config);
pc1.addStream(stream);
}
Run Code Online (Sandbox Code Playgroud)
这是我的代码的简化版本。
现在,在此代码中,我没有将icecandidate添加到对等方,也没有收听onicecandidate。但是,如果我两次调用call(),则建立连接。
我使用事件处理程序更改iceconnectionstate的状态,发现当我第一次调用call时,iceconnection状态处于检查状态,而当我第二次调用它时,iceconnection状态被调用并且状态完成。
因此,我想知道即使不将icecandidate添加到另一个对等方又如何启动检查并第二次连接?
四个原因:代码中的错误、Chrome 的行为、没有防火墙以及有关涓流 ICE 工作原理的信息。
首先,以下几组pc1.setRemoteDescription(null):
pc2.setLocalDescription(answer);
pc1.setRemoteDescription(pc2.localDescription); // pc2.localDescription == null here
Run Code Online (Sandbox Code Playgroud)
...因为setLocalDescription是一个异步方法,不会立即完成。
现在最终pc2.localDescription会被设置,所以当你第二次调用它时,它就在那里,并且谈判可以进行。call()
要解决此问题,您必须使用或等待承诺:awaitthen
await pc2.setLocalDescription(answer);
pc1.setRemoteDescription(pc2.localDescription); // pc2.localDescription is set!
Run Code Online (Sandbox Code Playgroud)
浏览器可以使用“主机”候选者(您计算机的 IP)与同一 LAN 上的其他计算机或自身进行通信。不需要 ICE 服务器来发现这些。
个别冰候选人使用的信号(滴流)onicecandidate是一种旨在加快谈判速度的优化。一旦setLocalDescription成功,浏览器的内部ICE 代理就会启动,将发现的 ICE 候选者插入到浏览器自身中localDescription。等待几秒钟进行协商,根本不需要滴流:所有 ICE 候选人都将包含在要约和答案中传输。
我怀疑在第二次调用call()Chrome 的 ICE 代理时会记住它上次收集的候选主机,并将它们插入到 Offer 中,并localDescription立即在setLocalDescription成功回调运行完成之前进行竞赛。这可能是一个错误,也可能是规范规定的工作方式。无论如何,行为似乎根据浏览器 atm 的不同而有所不同,所以我今天不会依赖它。
Call!按钮一次,然后再单击一次。0 candidates(输出两次);两次;无连接。3 candidates第二 次 联系。// await wait(2000);4浏览器都会在 2 秒或8 candidates之后进行连接。候选人的实际数量可能会因您的系统而异,但行为应该不会。
当我在 Firefox 中运行它时,它两次都不会连接,除非我将其修改为等待或滴流候选者)。
浏览器更新: 两种浏览器都有缺陷:Firefox在从 ICE 故障中恢复方面限制过于严格,Chrome过于宽松。
| 归档时间: |
|
| 查看次数: |
448 次 |
| 最近记录: |