你该什么时候显示传入的WebRTC视频

作者:Philipp Hancke(原文链接

翻译:刘通

原标题:When should you display incoming WebRTC video

 

自2011年的第一个版本以来,WebRTC规范已经发生了很大的变化。Jan-Ivar对多年来WebRTC的演变情况进行了精彩的总结,详见这篇文章

Web开发人员的核心问题之一是何时显示传入的视频流。

在第一版本中,规范有一个addstream事件,这是在设置远程描述时出发的。Addstream事件有一个流对象,你可以将视频元素的srcObject属性设置为该流对象,如下所示(使用更现代但相似的轨道事件):

 1const pc1 = new RTCPeerConnection(), pc2 = new RTCPeerConnection();
 2
 3pc2.ontrack = e => {
 4  console.log('got track', e.track, e.streams);
 5  remoteVideo.srcObject = e.streams[0];
 6};
 7
 8pc2.oniceconnectionstatechange = () =>
 9  console.log('PC2 ice state ' + pc2.iceConnectionState);
10
11(async () => {
12  const stream = await navigator.mediaDevices.getUserMedia({video: true});
13  pc1.addTrack(stream.getVideoTracks()[0], stream);
14  const offer = await pc1.createOffer();
15  await pc1.setLocalDescription(offer);
16  await pc2.setRemoteDescription(offer);
17  const answer = await pc2.createAnswer();
18  await pc2.setLocalDescription(answer);
19  await pc1.setRemoteDescription(answer);
20})();
21
22const console = {log: msg => div.innerHTML += msg + "<br>"};

处于演示的目的,这个小代码没有完成两个本地对象之间的WebRTC连接。它永远不会连接ICE候选。“Result”标签显示我们得到了轨道事件,即使连接从未成功。在WebRTC的早期,有很多像“远程视频是个黑箱”这样的情况。特别是当点对点连接失败时发生这种情况。比如当防火墙阻拦了什么的时候:

display1

为了检测到这点,必须监听iceconnectionstatechange事件并对其进行评估。状态演示显示如何监听这种状态变化。当对等连接的iceConnectionState属性更改为“connected”或者“completed”时会显示视频。在仅有单个流的简单情况下,这种方式非常有效。

对于多个流,以及将流添加到正在进行的连接时,这将不再起作用。新流的开始处用户可能会遇到非常短暂的黑屏时间。此外,我们的视频元素现在必须能够访问对等连接状态,并说明它甚至不代表正确的事情。

轨道静音属性来解决

在规范的最新版本中—在Firefox 59版本中实现的收发器模型—MediaStreamTrack具有静音属性。此属性最初设置为true,一旦媒体到达,它将变为false。有关详细信息,请参阅规范中的RTCRTPReceiver

这可以更好地决定何时显示视频元素以及何时通过监听MediaStreamTrack上的非静音和静音事件来隐藏它,如下所示:

 

 1const pc1 = new RTCPeerConnection(), pc2 = new RTCPeerConnection();
 2
 3pc2.ontrack = e => {
 4  console.log('track event muted = ' + e.track.muted);
 5  e.track.onunmute = () => {
 6    console.log('track unmuted');
 7    remoteVideo.srcObject = e.streams[0];
 8  }
 9};
10
11pc1.onicecandidate = e => pc2.addIceCandidate(e.candidate);
12pc2.onicecandidate = e => pc1.addIceCandidate(e.candidate);
13pc2.oniceconnectionstatechange = () =>
14  console.log('PC2 ice state ' + pc2.iceConnectionState);
15
16(async () => {
17  const stream = await navigator.mediaDevices.getUserMedia({video: true});
18  pc1.addTrack(stream.getVideoTracks()[0], stream);
19  await pc1.setLocalDescription(await pc1.createOffer());
20  await pc2.setRemoteDescription(pc1.localDescription);
21  await pc2.setLocalDescription(await pc2.createAnswer());
22  await pc1.setRemoteDescription(pc2.localDescription);
23})();
24const console = {log: msg => div.innerHTML += msg + "<br>"};

 

我们在上面的“Result”标签中的日志输出中看到的是,在对等连接变为已连接之后,轨道最初被静音并且只有在视频数据包到达时才被解除静音。

不幸的是,这只适用于Firefox 59及更高版本。有一个Chrome / WebRTC bug以及Microsoft Edge的ORTC实现中存在类似的问题。希望围绕此问题的错误很快就会解决,但它是向WebRTC 1.0过渡的一个小而关键的细节。

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

WebRTC 中文社区由

运营