本文译自

A Closer Look Into WebRTC

我们在最近的一篇

WebKit博客中宣布了对High Sierra平台和iOS中Safari的WebRTC支持。现在,我们希望能够带领大家深入实现其中的一些细节,并且为您网站中的WebRTC应用带来一些建议。

一个应用了WebRTC和媒体摄像头的网站可以获取并传播一些非常私人的信息。用户必须显式地对网站进行授权,并假设他们的图片和声音会被合理使用。WebKit为了利用技术保护用户的隐私权,要求网站满足一些特定的条件。除此之外,当用户的摄像头设备被使用时,Safari会提醒用户,并且用户可以控制网站对摄像头设备的访问权限。对于在App中使用了WebKit的开发者发来说,RTCPeerConnection和RTCDataChannel可以在任意网页视图中使用,但对摄像头和麦克风的访问目前受限于Safari。
开发菜单

Safari技术预览版34向开发者展示了一些选项,可以更容易的测试他们的WebRTC网站或将Safari集成到持续集成系统中,入口在开发>WebRTC子菜单中。

我们将介绍每个选项,并将在下方解释它们是如何帮助你进行开发的。
此外,WebKit将WebRTC的状态作为日志记录在了系统日志中,包括SDP邀请和应答,ICE候选项,WebRCT状态统计,传入及传出视频帧计数器等。
媒体摄像头的安全源策略
希望访问捕获设备的网站需要满足两个约束。
首先,请求需要使用摄像头和麦克风的文档需要来自

HTTPS域。由于在本地开发和测试时可能会很麻烦,因此可以通过在

开发>WebRTC*
菜单中选中

"在不安全的站点上允许使用媒体摄像头"来旁路HTTPS限制。

其次,当子帧请求使用摄像头设备时,通向主帧的帧链需要来自相同的安全源。用户可能无法识别与主帧相关的子帧的第三方来源,因此该约束避免了混淆用户授予其访问权限的用户。
模拟网页摄像头

开发

>WebRTC菜单中,可以选择"使用模拟摄像头设备"来替代真实的摄像头设备。如下所示,模拟循环一个bip-bop AV流。当用作传入流时,模拟的可预测数据可以轻松评估流媒体播放的各个方面,包括同步,延迟和输入设备的选择。

模拟对于在持续集成系统中运行自动化测试也很有用。如果您正在使用并且想要避免来自

getUserMedia的提示,可以通过Safari

首选项

...>网站面板将网站的摄像头和麦克风策略设置为允许。

ICE候选项限制

ICE候选项在WebRTC连接的早期阶段进行信息交换,以识别两个对等连接之间的所有可能的网络路径。为此,WebKit必须将每个对等连接的ICE候选项暴露给网站并共享它们。ICE候选项公开IP地址,特别是那些可以用于跟踪的主机IP地址。

但是,在许多网络拓扑中,主机ICE候选项不必进行连接。无论是否用于交换视频或任意数据,Server Reflexive和TURN ICE候选项通常都足以确保连接。如果不访问摄像头设备,WebKit只会公开Server Reflexive和TURN ICE候选项,这些候选者会公开可能已经被网站收集的IP。授予访问权限后,WebKit将公开主机ICE候选项,从而最大限度地提高连接成功的可能性。我们做出此例外的原因是:我们认为用户通过授予对其摄像流的访问权限来表达对网站的高度信任。
一些测试页面可能会对主机ICE候选项的可用性作出假设。要对此进行测试,请从

开发>WebRTC

菜单中启用"禁用ICE候选限制",然后重新加载页面。

旧版

WebRTC及媒体流API

随着WebRTC标准化过程的推进(免费下载W3C推荐标准WebRTC 1.0: Real-time Communication Between Browsers中文版),

RTCPeerConnection API以各种方式逐步改进。API从最初基于回调,到变为完全基于promise,从最初专注于将MediaStream,移动到专注于MediaStreamTrack。感谢WebRTC in WebKit团队的努力,RTCPeerConnection API的改进与这两个主要变化保持一致。

我们已经在Safari技术预览版34上默认关闭了旧版WebRTC API,并计划在没有这些API的情况下在macOS High Sierra和iOS 11上发布Safari 11。保留遗留API限制了我们在WebRTC上更快推进的能力。任何希望为Safari提供支持的网站都可能需要进行其他调整,因此这是摆脱这些遗留API的好时机。现有网站仍然可以依赖这些遗留API,您可以通过在

开发

>WebRTC菜单中启用"启用旧版WebRTC API"来达到目的。ui更准确地说,以下API仅在打开旧版API开关时可用,并提供了有关如何更新的建议:

partial interface Navigator {

// Switch to navigator.mediaDevices.getUserMedia

void getUserMedia(MediaStreamConstraints constraints, NavigatorUserMediaSuccessCallback successCallback, NavigatorUserMediaErrorCallback errorCallback);

};

partial interface RTCPeerConnection {

// Switch to getSenders, and look at RTCRtpSender.track

sequence<MediaStream> getLocalStreams();

// Switch to getReceivers, and look at RTCRtpReceiver.track

sequence<MediaStream> getRemoteStreams();

// Switch to getSenders/getReceivers

MediaStream getStreamById(DOMString streamId);

// Switch to addTrack

void addStream(MediaStream stream);

// Switch to removeTrack

void removeStream(MediaStream stream);

// Listen to ontrack event

attribute EventHandler onaddstream;

// Update to promise-only version of createOffer

Promise<void> createOffer(RTCSessionDescriptionCallback successCallback, RTCPeerConnectionErrorCallback failureCallback, optional RTCOfferOptions options);

// Update to promise-only version of setLocalDescription

Promise<void> setLocalDescription(RTCSessionDescriptionInit description, VoidFunction successCallback, RTCPeerConnectionErrorCallback failureCallback);

// Update to promise-only version of createAnswer

Promise<void> createAnswer(RTCSessionDescriptionCallback successCallback, RTCPeerConnectionErrorCallback failureCallback);

// Update to promise-only version of setRemoteDescription

Promise<void> setRemoteDescription(RTCSessionDescriptionInit description, VoidFunction successCallback, RTCPeerConnectionErrorCallback failureCallback);

// Update to promise-only version of addIceCandidate

Promise<void> addIceCandidate((RTCIceCandidateInit or RTCIceCandidate) candidate, VoidFunction successCallback, RTCPeerConnectionErrorCallback failureCallback);

};

许多站点通过开源的adapter.js项目支持polyfill API。更新到最新版本是弥补API差异的一种方法,但我们建议切换到规范中列出的API。
以下是如何使用最新API的几个示例。典型的仅接收/在线研讨的WebRTC调用可以像这样完成:

var pc = new RTCPeerConnection();

pc.addTransceiver('audio');

pc.addTransceiver('video');

var offer = await pc.createOffer();

await pc.setLocalDescription(offer);

// send offer to the other party

...

典型的音频-视频WebRTC调用也可以像以下方式完成:

var stream = await navigator.mediaDevices.getUserMedia({audio: true, video: true});

var pc = new RTCPeerConnection();

var audioSender = pc.addTrack(stream.getAudioTracks()[0], stream);

var videoSender = pc.addTrack(stream.getVideoTracks()[0], stream);

var offer = await pc.createOffer();

await pc.setLocalDescription(offer);

// send offer to the other party

...

基于MediaStreamTrack的API很有意义,因为大多数处理都是在这一层完成的。假设捕获视频轨的640×480默认分辨率不够好,继续前面的示例,动态更改它可以按如下方式完成:

videoSender.track.applyConstraints({width: 1280, height: 720});

或者我们可能想要视频静音但保持音频流动:

videoSender.track.enabled = false;

等等,我们实际上想要对当前的视频轨应用一些很酷的滤镜效果,就像在这个例子中一样,所需要的只是一些不需要任何SDP重新协商的函数调用:

videoSender.track.enabled = true;

renderWithEffects(video, canvas);

videoSender.replaceTrack(canvas.captureStream().getVideoTracks()[0]);

访问摄像流

Safari允许用户完全控制网站对其摄像设备的访问权限。

首先,用户首次调用getUserMedia时,系统会提示用户授予网站访问摄像设备的权限。但与其他浏览器不同的是,Safari不要求用户选择特定设备; 相反,它提示请求访问某一特定类型的设备,如所有相机或麦克风。这减少了多次提示带来的困扰,并且可避免用户始终点击"允许"。可能发生这种情况的一种常见情形是在iOS设备的摄像头在前后之间切换。getUserMedia
中已解析的promise将返回满足约束条件的设备,并且后续对getUserMedia的调用将避免向用户显示提示。如果要允许用户切换到其他设备,请务必提供UI以执行此操作。
其次,用户可以决定通过Safari首选项始终允许或拒绝访问摄像头和麦克风。用户可以基于每个来源执行此操作,甚至可以为所有网站设置通用策略。
第三,一旦网站为设备创建MediaStream,Safari UI和系统菜单栏中就会显示图标,表明正在使用摄像设备。用户可以点击或点击该图标以暂停使用中的摄像机和麦克风。在这里,WebKit将发送静音音频和黑色视频帧,您的网站可以通过监听MediaStreamTrack上的静音和取消静音事件来展示合适的UI。

最后,为了避免未经允许的摄像,WebKit只允许一个选项捕获一次视频或音频。已使用的捕获设备将看到他们的MediaStreamTracks静音并在新选项卡获得访问权限时接收静音事件。
指纹

navigator.mediaDevices.enumerateDevices

公开了可用的摄像设备列表,即使未授予对这些设备的访问权限,也可以通过网站查询。对于具有自定义相机和麦克风设置的用户,可以添加到用户的指纹表面。当访问尚未被请求或访问没有被明确拒绝时,

WebKit通过返回与实际可用设备集不一定对应的默认设备列表,来避免暴露这些附加信息。此外,根据规范,设备缺少标签。一旦访问权限被授予,即可获得完整的设备列表及其标签。

媒体摄像头和自动播放视频在之前的帖子中,我们讨论了macOS和iOS上视频自动播放策略的变化。我们调整了两个平台上的策略以适应WebRTC应用程序,在这些应用程序中,通常需要自动播放包含音频的传入媒体流。为了解决这些问题,同时保留当前自动播放规则的好处,我们进行了以下更改:

·如果网页已在捕获,则MediaStream支持的媒体将自动播放。

·如果网页已播放音频,则MediaStream支持的媒体将自动播放。但仍然需要用户手势来激活音频回放。

性能

WebRTC是一个非常强大的特性,可以衍生许多应用程序。我们都知道,强大的力量带来了巨大的责任。设计WebRTC应用程序需要从一开始就考虑到效率。 CPU,内存和网络都可能严重影响用户体验。Web引擎和Web应用程序都应该解决此问题。在Web应用程序方面,已经有各种机制可供选择:选择正确的视频分辨率和帧速率,选择正确的视频编解码器配置文件,使用CVO,在源处将媒体轨静音,以及在客户端执行WebRTC统计数据的监视。

反馈
这就是我们深入研究WebRTC和媒体摄像的结果。我们随时欢迎您的反馈。提交错误,发送电子邮件至web-evangelist@apple.com,或发推并@webkit。
顺便说一句,鼓励大家阅读STUNTURN的RFC规范,以及WebRTC本身的规范。这些文件可能有点难以理解,但是您可以从理解甚至一小部分内容中学到很多东西,这将有助于您的生活更简单。

【Webkit Blog翻译】深入研究WebRTC | 内有福利的更多相关文章

  1. [翻译]60,000毫秒内对Linux进行性能诊断

    原文链接:http://techblog.netflix.com/2015/11/linux-performance-analysis-in-60s.html 原文作者:Brendan Gregg,L ...

  2. WebRTC内置debug工具,详细参数解读 chrome://webrtc-internals/

    为了确保这篇文章所写内容尽可能的准确,我决定请来Philipp Hancke来作为此篇文章的共同作者. 当你想要找到你WebRTC产品中的问题时,webrtc-internals是一个非常棒的工具,因 ...

  3. Python协程爬取妹子图(内有福利,你懂得~)

    项目说明: 1.项目介绍   本项目使用Python提供的协程+scrapy中的选择器的使用(相当好用)实现爬取妹子图的(福利图)图片,这个学会了,某榴什么的.pow(2, 10)是吧! 2.用到的知 ...

  4. 单独编译使用WebRTC的音频处理模块

    块,每块个点,(12*64=768采样)即AEC-PC仅能处理48ms的单声道16kHz延迟的数据,而 - 加载编译好的NS模块动态库 接下来只需要按照 此文 的描述在 android 的JAVA代码 ...

  5. WebRTC 音视频开发

    WebRTC 音视频开发 webrtc   Android IOS WebRTC 音视频开发总结(七八)-- 为什么WebRTC端到端监控很关键? 摘要: 本文主要介绍WebRTC端到端监控(我们翻译 ...

  6. 转:Android IOS WebRTC 音视频开发总结 (系列文章集合)

    随笔分类 - webrtc   Android IOS WebRTC 音视频开发总结(七八)-- 为什么WebRTC端到端监控很关键? 摘要: 本文主要介绍WebRTC端到端监控(我们翻译和整理的,译 ...

  7. WebRTC音频预处理单元APM的整体编译及使用

    正文 行的gnu静态库链接路径是针对NDK版本 r8d 的,如读者版本不匹配,请自行找到 libgnustl_static.a 静态库的路径进行替换. 3)本示例并不打算编译 WebRTC 的测试工程 ...

  8. Android IOS WebRTC 音视频开发总结(八十七)-- WebRTC中丢包重传NACK实现分析

    本文主要介绍WebRTC中丢包重传NACK的实现,作者:weizhenwei ,文章最早发表在编风网,微信ID:befoio 支持原创,转载必须注明出处,欢迎关注我的微信公众号blacker(微信ID ...

  9. webrtc 的回声抵消(aec、aecm)算法简介(转)

    webrtc 的回声抵消(aec.aecm)算法简介        webrtc 的回声抵消(aec.aecm)算法主要包括以下几个重要模块:1.回声时延估计 2.NLMS(归一化最小均方自适应算法) ...

随机推荐

  1. centos 7 构造iptables开放80port

    centos7默认是使用firewalld托管防火墙. 安装后centos7后,已安装nginxserver,但同样没有在一个局域网访问,我哥哥告诉我,我应该是一个防火墙以打开.防火墙关闭就可以了. ...

  2. Network Function Virtualization for a Network Device

    An apparatus for performing network function virtualization (NFV), comprising: a memory, a processor ...

  3. Blend_ControlTemplate(Z)

    原文:Blend_ControlTemplate(Z) 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u010265681/article/deta ...

  4. cocos2dx-3.1加入cocosStudio参考库 libCocosStudio

    一个,创建好项目 两,在"解(项目名称)".选择现有项目 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2dzbHVja3k=/fon ...

  5. MinGW —— Minimalist GNU for Windows、Cygwin —— Windows 下的类 unix 系统

    0. 楔子 Windows 下显然是没有 gcc 编译器的.对于一些软件或者工具如果想要在 Windows 平台下运行,而又需要依赖 gcc 编译其中的一些基于 C/C++ 实现的代码. 此时就借助 ...

  6. Android学习-- 基于位置的服务 LBS(基于百度地图Android SDK)--定位SDK

    原文:Android学习-- 基于位置的服务 LBS(基于百度地图Android SDK)--定位SDK 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.ne ...

  7. VLC-FM PLAYLIST

    VLC-FM-PLAYLIST.xspf <?xml version="1.0" encoding="UTF-8"?> <playlist x ...

  8. 关闭Mac OS 的Rootless

    今天在使用mac的时候,需要删除 /usr/bin/下的 自带的php文件.然后提示Operation not permitted 使用sudo 依然不可以,通过google 得到解决方案. 需要关闭 ...

  9. WPF 4 DataGrid 控件(进阶篇二)

    原文:WPF 4 DataGrid 控件(进阶篇二)      上一篇<WPF 4 DataGrid 控件(进阶篇一)>中我们通过DataGridTemplateColumn 类自定义编辑 ...

  10. WPF DatePicker默认显示当前日期,格式化为年月日

    原文:WPF DatePicker默认显示当前日期 WPF的日历选择控件默认为当前日期,共有两种方法,一种静态,一种动态. 静态的当然写在DatePicker控件的属性里了,动态的写在对应的cs文件里 ...