WebRTC中的完美协商(一)

写在前面:如果你不必担心连接状态、闪退问题(信号冲突)、角色(你处于哪一方),就可以在实时WebRTC连接中添加和删除媒体,你会怎么做呢?不受时间和地点限制,你可以很容易地调用pc.addTrack(track,stream),并且你的连接路径只会显示在另一侧,不会有终端连接失败的风险。这是个白日梦?还有很多问题亟待解决?实际上,现在Chrome已经基本完成了协商,上述操作几乎可以运行!但是这样的操作并没有广泛应用,可能是因为“几乎”这两个字。这代表该操作有5%的时间无法工作,并且若Chrome闪退,风险太高了(无法从该操作回滚,只能运用pc.close())。但API最初的承诺仍然有效。我们只需要一个除Firefox以外的浏览器来实现回滚,并用规范允许的方法修复一些明显的竞赛问题。

WebRTC API中的一些东西可能会导致像SDP和ICE的非对称交换一样多的操作失误。如果编程不正确,其SignalState和对时间敏感的ICE流可能会导致一些问题。如果这还不够有挑战性,那么保持两端同步并且不同方向的话,会使很多用户陷入死循环。

如果我告诉你我们可以解决这个棘手的问题呢?如果我说,如今大多数人在协商时用到的WebRTC人工是低效的,我们可以使其变得高效呢?

这里我们谈到的是negotiationneeded的(操作)和“rollback”。我们可以协同使用两种系统,完全不用协商。然而,没有人使用它们,因为它们分别都没有在Chrome中得到应用。下面我们会逐一介绍这两种系统。

negotiationneeded  处理当地变化

negotiationneeded是提供/回答交换ice candidate事件对ICE候选交换的内容。您可能已经知道如何使用后者。那么这样做就可以发送信息:

pc.onicecandidate = ({candidate}) => io.send({candidate});

这样做可以接收信息:

io.onmessage = async ({data: {description, candidate}}) => {
  if (candidate) await pc.addIceCandidate(candidate);
}

然后浏览器会负责接下来的事情。 这简直太简单了! 我们不关心如何、何时或为何需要交换候选,我们只是连接网络,并用浏览器与其对接即可。 我们已经有效地抽离了ICE交易; 浏览器会处理它的。

有这么方便的操作,我们为什么还要多此一举用人工呢? 只需以同样的方式设置它。 这样做就可以发送信息:

pc.onnegotiationneeded = async () => {
  await pc.setLocalDescription(await pc.createOffer());
  io.send({description: pc.localDescription});
}

这样做就可以接收信息:

io.onmessage = async ({data: {description, candidate}}) => {
  if (description) {
    await pc.setRemoteDescription(description);
    if (description.type == "offer") {
      await pc.setLocalDescription(await pc.createAnswer());
      io.send({description: pc.localDescription});
    }
  } else if (candidate) await pc.addIceCandidate(candidate);
}

这样就完成了!

现在,每当我们在RTCPeerConnection上传输媒体流时,它就会自动发送以下内容:

const stream = await navigator.mediaDevices.getUserMedia({video: true,
                                                          audio: true});
for (const track of stream.getTracks()) {
  pc.addTrack(track, stream);
}

到了另一端:

pc.ontrack = ({streams}) => video.srcObject = streams[0];

协商会按需自动进行。我们已经简化了协商操作,接下来就看浏览器的了。

原文地址:https://blog.mozilla.org/webrtc/perfect-negotiation-in-webrtc/

文章作者:Jan-Ivar Bruaroey

 

填写常用邮箱,接收社区更新

WebRTC 中文社区由

运营