2 回答

TA贡献1765条经验 获得超5个赞
在两个浏览器窗口中打开它,然后点击其中一个窗口中的按钮。这是代码:Connect
const pc = new RTCPeerConnection();
call.onclick = async () => {
const stream = await navigator.mediaDevices.getUserMedia({video:true,audio:true})
video.srcObject = stream;
for (const track of stream.getTracks()) {
pc.addTrack(track, stream);
}
};
pc.ontrack = ({streams}) => video.srcObject = streams[0];
pc.oniceconnectionstatechange = () => console.log(pc.iceConnectionState);
pc.onicecandidate = ({candidate}) => sc.send({candidate});
pc.onnegotiationneeded = async () => {
await pc.setLocalDescription(await pc.createOffer());
sc.send({sdp: pc.localDescription});
}
const sc = new localSocket(); // localStorage signaling hack
sc.onmessage = async ({data: {sdp, candidate}}) => {
if (sdp) {
await pc.setRemoteDescription(sdp);
if (sdp.type == "offer") {
await pc.setLocalDescription(await pc.createAnswer());
sc.send({sdp: pc.localDescription});
}
} else if (candidate) await pc.addIceCandidate(candidate);
}
这是A和B的相同来源,用您喜欢的信令通道(例如websocket)替换黑客攻击。localSocket
不要缓存ICE候选者,因为这违背了涓流ICE的目的。它可能在本地看起来很快,但在实际网络中ICE可能需要时间。
事实上,如果您延迟发送报价/答案,直到收集了所有本地候选人,则发送候选人是没有意义的,因为候选人已经嵌入到提议/答案()中。pc.localDescription

TA贡献1876条经验 获得超7个赞
最后!几周后,我已经弄清楚了这个问题,这个问题在我的问题中包含的代码中并不明显,但对于遇到类似问题的人来说,它可能仍然有用。
我以为在活动结束后,冰上收集正在完成,并且提供了报价/答案。onnegotiationneeded
由于这个不正确的假设,我在这个阶段与冰候选人一起发出报价/答案的信号,但是非常频繁地(根据我的经验,总是在iOS Safari中)此时尚未创建报价/答案。
我通过创建两个承诺来解决这个问题:a)完成冰候选收集,以及b)创建报价/答案。我使用了两个承诺,当它们都完成时,我通过信令服务器同时发送了冰候选者和提供/答案。Promise.all
这是可行的,但是当然在未来,我应该通过发送零碎的东西来“涓涓细流”这些信息,而不是等待一切完全完成。但是我将来会担心这一点,因为目前我正在使用HTTP请求,而且这太麻烦了。
编辑:我的连接仍然总是卡住,所以我创建了一个新问题。但是,如果没有本地连接,则现在100%完全可靠:)iceServers
iceServers
添加回答
举报