【Webkit Blog翻译】深入研究WebRTC | 内有福利
“本文譯自A Closer Look Into WebRTC”
我們在最近的一篇WebKit博客中宣布了對High Sierra平臺和iOS中Safari的WebRTC支持。現在,我們希望能夠帶領大家深入實現其中的一些細節(jié),并且為您網站中的WebRTC應用帶來一些建議。
一個應用了WebRTC和媒體攝像頭的網站可以獲取并傳播一些非常私人的信息。用戶必須顯式地對網站進行授權,并假設他們的圖片和聲音會被合理使用。WebKit為了利用技術保護用戶的隱私權,要求網站滿足一些特定的條件。除此之外,當用戶的攝像頭設備被使用時,Safari會提醒用戶,并且用戶可以控制網站對攝像頭設備的訪問權限。對于在App中使用了WebKit的開發(fā)者發(fā)來說,RTCPeerConnection和RTCDataChannel可以在任意網頁視圖中使用,但對攝像頭和麥克風的訪問目前受限于Safari。
開發(fā)菜單
Safari技術預覽版34向開發(fā)者展示了一些選項,可以更容易的測試他們的WebRTC網站或將Safari集成到持續(xù)集成系統中,入口在開發(fā)>WebRTC子菜單中。
我們將介紹每個選項,并將在下方解釋它們是如何幫助你進行開發(fā)的。
此外,WebKit將WebRTC的狀態(tài)作為日志記錄在了系統日志中,包括SDP邀請和應答,ICE候選項,WebRCT狀態(tài)統計,傳入及傳出視頻幀計數器等。
媒體攝像頭的安全源策略
希望訪問捕獲設備的網站需要滿足兩個約束。
首先,請求需要使用攝像頭和麥克風的文檔需要來自HTTPS域。由于在本地開發(fā)和測試時可能會很麻煩,因此可以通過在開發(fā)>WebRTC*菜單中選中"在不安全的站點上允許使用媒體攝像頭"來旁路HTTPS限制。
其次,當子幀請求使用攝像頭設備時,通向主幀的幀鏈需要來自相同的安全源。用戶可能無法識別與主幀相關的子幀的第三方來源,因此該約束避免了混淆用戶授予其訪問權限的用戶。
模擬網頁攝像頭
在開發(fā)>WebRTC菜單中,可以選擇"使用模擬攝像頭設備"來替代真實的攝像頭設備。如下所示,模擬循環(huán)一個bip-bop AV流。當用作傳入流時,模擬的可預測數據可以輕松評估流媒體播放的各個方面,包括同步,延遲和輸入設備的選擇。
模擬對于在持續(xù)集成系統中運行自動化測試也很有用。如果您正在使用并且想要避免來自getUserMedia的提示,可以通過Safari首選項...>網站面板將網站的攝像頭和麥克風策略設置為允許。
ICE候選項限制
ICE候選項在WebRTC連接的早期階段進行信息交換,以識別兩個對等連接之間的所有可能的網絡路徑。為此,WebKit必須將每個對等連接的ICE候選項暴露給網站并共享它們。ICE候選項公開IP地址,特別是那些可以用于跟蹤的主機IP地址。
但是,在許多網絡拓撲中,主機ICE候選項不必進行連接。無論是否用于交換視頻或任意數據,Server Reflexive和TURN ICE候選項通常都足以確保連接。如果不訪問攝像頭設備,WebKit只會公開Server Reflexive和TURN ICE候選項,這些候選者會公開可能已經被網站收集的IP。授予訪問權限后,WebKit將公開主機ICE候選項,從而最大限度地提高連接成功的可能性。我們做出此例外的原因是:我們認為用戶通過授予對其攝像流的訪問權限來表達對網站的高度信任。
一些測試頁面可能會對主機ICE候選項的可用性作出假設。要對此進行測試,請從開發(fā)>WebRTC菜單中啟用"禁用ICE候選限制",然后重新加載頁面。
舊版WebRTC及媒體流API
隨著WebRTC標準化過程的推進(免費下載W3C推薦標準WebRTC 1.0: Real-time Communication Between Browsers中文版),RTCPeerConnection API以各種方式逐步改進。API從最初基于回調,到變?yōu)橥耆趐romise,從最初專注于將MediaStream,移動到專注于MediaStreamTrack。感謝WebRTC in WebKit團隊的努力,RTCPeerConnection API的改進與這兩個主要變化保持一致。
我們已經在Safari技術預覽版34上默認關閉了舊版WebRTC API,并計劃在沒有這些API的情況下在macOS High Sierra和iOS 11上發(fā)布Safari 11。保留遺留API限制了我們在WebRTC上更快推進的能力。任何希望為Safari提供支持的網站都可能需要進行其他調整,因此這是擺脫這些遺留API的好時機。現有網站仍然可以依賴這些遺留API,您可以通過在開發(fā)>WebRTC菜單中啟用"啟用舊版WebRTC API"來達到目的。
更準確地說,以下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差異的一種方法,但我們建議切換到規(guī)范中列出的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默認分辨率不夠好,繼續(xù)前面的示例,動態(tài)更改它可以按如下方式完成:
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不要求用戶選擇特定設備; 相反,它提示請求訪問某一特定類型的設備,如所有相機或麥克風。這減少了多次提示帶來的困擾,并且可避免用戶始終點擊"允許"。可能發(fā)生這種情況的一種常見情形是在iOS設備的攝像頭在前后之間切換。getUserMedia中已解析的promise將返回滿足約束條件的設備,并且后續(xù)對getUserMedia的調用將避免向用戶顯示提示。如果要允許用戶切換到其他設備,請務必提供UI以執(zhí)行此操作。
其次,用戶可以決定通過Safari首選項始終允許或拒絕訪問攝像頭和麥克風。用戶可以基于每個來源執(zhí)行此操作,甚至可以為所有網站設置通用策略。
第三,一旦網站為設備創(chuàng)建MediaStream,Safari UI和系統菜單欄中就會顯示圖標,表明正在使用攝像設備。用戶可以點擊或點擊該圖標以暫停使用中的攝像機和麥克風。在這里,WebKit將發(fā)送靜音音頻和黑色視頻幀,您的網站可以通過監(jiān)聽MediaStreamTrack上的靜音和取消靜音事件來展示合適的UI。
最后,為了避免未經允許的攝像,WebKit只允許一個選項捕獲一次視頻或音頻。已使用的捕獲設備將看到他們的MediaStreamTracks靜音并在新選項卡獲得訪問權限時接收靜音事件。
指紋
navigator.mediaDevices.enumerateDevices公開了可用的攝像設備列表,即使未授予對這些設備的訪問權限,也可以通過網站查詢。對于具有自定義相機和麥克風設置的用戶,可以添加到用戶的指紋表面。當訪問尚未被請求或訪問沒有被明確拒絕時,WebKit通過返回與實際可用設備集不一定對應的默認設備列表,來避免暴露這些附加信息。此外,根據規(guī)范,設備缺少標簽。一旦訪問權限被授予,即可獲得完整的設備列表及其標簽。
媒體攝像頭和自動播放視頻
在之前的帖子一和二中,我們討論了macOS和iOS上視頻自動播放策略的變化。我們調整了兩個平臺上的策略以適應WebRTC應用程序,在這些應用程序中,通常需要自動播放包含音頻的傳入媒體流。為了解決這些問題,同時保留當前自動播放規(guī)則的好處,我們進行了以下更改:
- 如果網頁已在捕獲,則MediaStream支持的媒體將自動播放。
- 如果網頁已播放音頻,則MediaStream支持的媒體將自動播放。但仍然需要用戶手勢來激活音頻回放。
性能
WebRTC是一個非常強大的特性,可以衍生許多應用程序。我們都知道,強大的力量帶來了巨大的責任。設計WebRTC應用程序需要從一開始就考慮到效率。 CPU,內存和網絡都可能嚴重影響用戶體驗。Web引擎和Web應用程序都應該解決此問題。在Web應用程序方面,已經有各種機制可供選擇:選擇正確的視頻分辨率和幀速率,選擇正確的視頻編解碼器配置文件,使用CVO,在源處將媒體軌靜音,以及在客戶端執(zhí)行WebRTC統計數據的監(jiān)視。
反饋
這就是我們深入研究WebRTC和媒體攝像的結果。我們隨時歡迎您的反饋。提交錯誤,發(fā)送電子郵件至web-evangelist@apple.com,或發(fā)推并@webkit。
?
順便說一句,鼓勵大家閱讀STUN和TURN的RFC規(guī)范,以及WebRTC本身的規(guī)范。這些文件可能有點難以理解,但是您可以從理解甚至一小部分內容中學到很多東西,這將有助于您的生活更簡單。免費下載W3C推薦標準WebRTC 1.0: Real-time Communication Between Browsers中文版。
?
總結
以上是生活随笔為你收集整理的【Webkit Blog翻译】深入研究WebRTC | 内有福利的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 网易超分黑科技来了!全新移动端视频体验时
- 下一篇: 0314互联网新闻 | 陌陌秘密发布6款