作者:Philipp Hancke(原文链接)
翻译:刘通
原标题:YouTube Does WebRTC – Here’s How
我周二登录了一次YouTube,注意到右上角有一个新的摄像头图标,并写着“Go Live(New)”,所以我点了一下它试试看会发生什么。事实证明,你现在可以直接从浏览器进行直播。这听起来真的很像WebRC,所以我加载了chrome://webrtc-internals来查看,并确定它就是WebRTC。我们总是对大规模部署很好奇,所以我立即请WebRTC逆向工程大师Philipp “Fippo” Hancke进行更深入的调查。本文剩下的部分就是他对此的分析。— 编辑:chad hart
自2014年Hangouts分析以来,Chrome的webrtc-internals页面都为我们提供了很好的服务,我们将在此次再次使用它。由于YouTube在注册之后有24小时的冷却时间,所以我们最终分析的数据是由Tsahi Levent-Levi友善提供的,可以从此处下载。你可以使用此导入工具将JSON转储重新导入Chrome。
请注意,该功能好像只适用于Chrome,并且仅适用于使用WebRTC发布摄像头流,接收端不使用WebRTC。这意味着它不是超低延迟,但是我们的老朋友Chris Kranky的报告指出延迟至少不到5秒钟。
让我们输入了解一下技术细节。
getUserMedia调用
在导入数据的顶部,我们看到YouTube进行的getUserMedia调用:
我们可以看到getUserMedia被调用要求从网络摄像头获得1080p分辨率:
并且有一个单独的getUserMedia调用来获取麦克风
请注意,虽然此转储中未显示相关信息,但第一个getUserMedia调用仍会要求音频和视频,以便Chrome中只有一个权限提示。
RTCPeerConnection调用
在getUserMedia之后,我们可以深入到RTCPeerConnection API调用中。如果你想了解更多信息,请参阅上一篇关于Hangouts如何使用WebRTC的文章。
ICE服务器
我们可以看出RTCPeerConnection对象是由一组空的ICE服务器创建的:
1{ iceServers: [], iceTransportPolicy: all,
2bundlePolicy: balanced, rtcpMuxPolicy: require,
3iceCandidatePoolSize: 0 }
我们稍后会看到为什么在此用例中不需要TURN服务器。
客户端然后使用addStream API添加MediaStream。请注意,此API已被弃用,因此缺乏Dog64ing Chrome 64中提供的spec addTrack API,这有点让人失望。
setLocalDescription信令
然后客户端使用Chrome支持的全套音频和视频编解码器来创建一个offer。接下来调用setLocalDescription而不修改该offer。特别是这意味着它不使用同播。
作为setLocalDescription调用的结果,客户端生成一些主机候选项。有可能这些会被丢弃,把它们发送到服务器什么没有什么意义。
更新:信令服务器和协议相对容易找到。过滤realtimemediaservice Chrome的网络检查器显示单个HTTP请求和响应。没有响应的信令要求。
setRemoteDescription
接下来轮到了服务器的setRemoteDescription调用。这是它真正有趣的地方。SDP看起来完全像Chrome或webrtc.org库通常生成的内容,回答支持的编解码器的完整列表。特别值得一提的是,它并未使用Ice-利特,因为Hangouts的做法表明YouTube正在使用不同的基础设施。
服务器在m = 行中首选H264:
1m=video 9 UDP/TLS/RTP/SAVPF 102 96 97 98 99 123 108 109 124
(就是那个102,这里查看SDP内容回顾),尽管Opus编解码器被用于音频。
从原始转储中检查统计信息(其中一些实在导入转储时可视)还确认使用了H264。如果您有兴趣,请搜索send-googCodecName。
对于连接性,我们看到SDP中包含一些ICE候选项:
1a=candidate:3757856892 1 udp 2113939711 2a00:1450:400c:c06::7f 19305
2 typ host generation 0 network-cost 50
3a=candidate:1687053168 1 tcp 2113939711 2a00:1450:400c:c06::7f 19305
4 typ host tcptype passive generation 0 network-cost 50
5a=candidate:1545990220 1 ssltcp 2113939711 2a00:1450:400c:c06::7f 443
6 typ host generation 0 network-cost 50
7a=candidate:4158478555 1 udp 2113937151 66.102.1.127 19305
8 typ host generation 0 network-cost 50
9a=candidate:1286562775 1 tcp 2113937151 66.102.1.127 19305
10 typ host tcptype passive generation 0 network-cost 50
11a=candidate:3430656991 1 ssltcp 2113937151 66.102.1.127 443
12 typ host generation 0 network-cost 50
既有对IPv6和IPv4的UDP候选项,也有ICE-TCP的候选,以及Hangouts也使用的Chrome专用SSL-TCP变种。这导致与TURN UDP / TCP / TLS建立与服务器的连接的机会几乎相同,因此不需要额外的TURN服务器。
编码
不使用同播。鉴于在Chrome中以及底层WebRTC库中没有H264同播,这点也并不让人惊讶。H264对于可以使用硬件加速的编码器来说是有意义的,并且在没有从VP8到H264的转码情况下可以支持更多的观众。
注意,尽管为服务器避免了将VP8转码为H264,但仍可能重新编码,以便为没有足够带宽从客户端接收完整分辨率的数据流的情况下产生一个较低分辨率的流。这个功能可能和很久以前就是YouTube在使用的东西了。
WebRTC统计数据
统计数据本身并不能提供很多信息。唯一有趣的图表是服务器发送的图像丢失指示(PLI):
pliCount每十秒增加一次,因此客户端将在该时间间隔内发送一个关键帧。这可能使YouTube更容易生成服务器端记录,或将流转换为任何使用的输出格式。
总结
Youtube使用WebRTC作为一种用户友好的方式来抓取用户的网络摄像机和流。 虽然这可能不会取代进行广播的人的高级设置,但会显着降低进入门槛,移除初学者的障碍。
不幸的是,该功能在Firefox中无法使用。 这是Google推出仅适用于Chrome的产品的另一个不好的例子。 Mozilla的Nils Ohlmeier尝试让它在欺骗用户代理的同时工作,并遇到了问题,因为Javascript使用了弃用的registerElement API。 从WebRTC的角度来看,该功能应该可以正常工作,所以我们期待在前端错误得到修复时能够回到这个问题。
更新:不幸的是,事实证明,JavaScript代码也使用旧版webkitRTCPeerConnection而不是spec RTCPeerConection。 我期待Chrome删除有前缀的API。