WebP2P 讓你的直播免流
你在下載的時候,有沒有體驗過 P2P 下載,能夠讓你的網速從 10KB 直接提升到 10MB?你在企業內傳輸文件的時候,有沒有體驗過文件秒傳?你在看直播的時候,想不想用別人的流量看直播呢?...
能做到上面這些場景的技術,叫做 P2P。P2P 技術中,最出名的叫做 WebRTC。WebRTC 是一個含金量非常高的技術。做好的話你可以養活一家公司,做不好,那就只能是一個 demo。
WebRTC 雖然能做很多事,但是並不是所有場景都適合。最大的使用場景是 兩個終端在同一個 NAT 內,簡單來說,都在一個 wifi 內。這個場景中,最顯著的效果就是帶寬無限並且高速,你走的就是內部的線路,根本不消耗運營商的流量。
P2P 技術在基於 WebRTC 標準下,可以做很多事情:
作為 Web 開發,WebRTC 又能夠給前端賦能些什麼呢?
在了解這些基本內容後,接下來,我們會從底層一步一步介紹一下 P2P 在 Web 直播的應用。
P2P 穿透
P2P 穿透也可以叫做 NAT 穿透,這是 P2P 最大的一個難點。為了解決 ipv4 不夠用,推出了 NAT 技術。NAT (Network Address Translation)是用來將內網私有 ip,轉化為公有 ip。簡單點,就是讓很多台電腦公用同一個 IP。但是 NAT 有個非常重要的點:
NAT 不允許外網主機主動訪問內網主機。
這個不允許訪問的機制也有很多種,根據這些特性,我們可以將 NAT 分為多種:
一般情況下,前面三種 NAT 是可以穿透的,但是,對稱型NAT 無法穿透。具體內容,大家網上搜一搜 NAT 穿透,資源應該很多。在穿透時,我們不僅需要考慮 NAT 還需要考慮到集群機器的防火牆設定,如果防火牆限制了 UDP 打洞,那麼我們還需要切換為 TCP 打洞(TCP 打洞一般會慢一點)。
總的來說,我們穿透時需要考慮的問題就有:
這些問題一旦組合起來,這個複雜度就是 N*N 的關係了。如果搭建 p2p 每次都需要從頭解決這個內容,P2P 也不會像現在發展的這麼好了。WebRTC 就是用來解決這一問題的標準模板,通過 STUN/TURN Server 來實現打洞穿透。
WebRTC 打洞流程
這裡,我們按照一個比較常見的情況作為模板講解一下。兩端都位於 NAT 層背後,並且,NAT 是可以穿透的 Full Cone NAT 類型。具體穿透流程如下:
在 WebRTC 完成這裡流程的 API 是: 。通過自建的一個中間 Server,來交換指定的 SDP 和 candidate。
SDP 是當前 Point 的一些基本描述信息,當前 WebRTC 版本 ICE 的描述信息,以及,對已經連接的 ICE 內容的描述,比如 video/audio 信息。SDP 這一環節,其實就是告訴了哪兩個 Point 會進行連接。本身和打洞並沒有太大的關聯。具體內容可以參考:SDP antonomy
candidate 則是打洞的關鍵信息,裡面會包含當前 Point 的內外網 ip:port,以及防火牆設定規則 tcp/upd。這裡有一點需要注意的是,一個 point 為了能夠提高 NAT 打洞的成功率,會產生多個 candidate。這裡主要取決於幾個 candidate 裡面幾個基本參數:
不過, 類型的 candidate 只會在你初始化 時,傳入 的 STUN 伺服器 URL 時,才會獲得。
在 webRTC 代碼層面,我們並不需要額外針對 candidate 做邏輯處理。我們只需要將 candidate 傳給另外一端,通過 註冊到 RTC 內部即可。
通過雲伺服器完成 candidate 和 sdp 信息的交換後,我們就已經做完了 RTC 連接的必要準備。剩下的就是在連接建立完成之後做的狀態監聽和其他擴展事情。
連接狀態判斷
這裡面最大的一個問題在於,我們完成數據添加之後,怎麼判斷 P2P 是否連接上。WebRTC 提供了我們 7 個基本的事件監聽:
通過 就可以得到連接狀態的變化。直接綁定該方法,即可獲得相關內容:
其能夠提供的事件回調信息,可以直接參考:connection states。裡面,我們只需要判斷狀態是否是 ,來決定該次連接是否成功。
如果不成功,我們可以直接從 裡面獲得相關的錯誤信息,具體可以參考:ICE gather error。當然,在連接過程中,也可以直接從 Promise 中,獲得連接失敗的信息,這部分內容可以直接參考:RTC Error。
上面整個代碼流程可以直接參考:webRTC trickle candidate
DataChannel 數據穿洞
打洞過程是 WebRTC 最基礎的一步,如果連這一步都沒成功,那麼後面就需要做一些其它適配的兼容。比如,直接通過 CDN 拉去資源。WebRTC 打洞成功後,我們就可以利用這個打洞包,根據用戶的種子資源數、上行帶寬、下載進度來判斷 P2P 傳輸的資源。
WebRTC 原生提供了 RTC Media API、RTCDataChannel、DTMF 這三個傳輸通道。Media 能夠直接結合 API 傳輸當前攝像頭和麥克獲取的音視頻。並且 Chrome 瀏覽器在底層內嵌了很多功能強大的編碼器,這裡可以直接參考:webRTC FRQ.
不過,經過測試 WebRTC 回聲消除和雙端同時對話的效果並不是特別好。這塊,大家可以考慮一下,能不能直接在底層替換編碼器或者購買其他服務。
Media 和 DTMF 通常都需要建立在 的前提下,但是,IOS11 並不支持,它只支持 DataChannel 傳輸數據的 API。所以,這裡,我們只會針對 DataChannel 來做一些講解。如何通過 DataChannel 來傳輸你的自定義文件內容。
DataChannel 是 PeerConnection 的一個拓展 API,可以直接通過 來創建一個 SCTP 通道。SCTP 是一種高效的幀傳輸協議,它和 TCP/UDP 是在同一層的,集中了兩者之間的優勢。我們只需要在發送端創建 Channel,接收端直接監聽 事件即可。
RTCDataChannel 一共可以發送兩種數據:String 和 Binary(也可以叫做 ArrayBuffer,ArrayBufferView or Blob) 具體直接參考:dataView。
Channel 具體的用法其實就和 WebSocket 一樣,通過 send 來傳遞相關的信息,再監聽 事件獲得數據的回調。
上面的流程大致的覆蓋了打洞的雲端流程,比如穿透 NAT 層,P2P 數據 Channel 建立。不過,中間還有很多細節並沒有解決清楚:
而這些問題就需要落地到具體的業務當中了。因為現在直播行業非常的火熱,本人也在該行業裡面摸爬滾打,了解到該行業一些基本的痛點。最大的就是非常吃帶寬,為了解決這一問題,我們完全可以利用 P2P 來做直播帶寬的節省。
但是,說起來很容易,怎麼做這才是關鍵?
不過,對於 Web 開發來說,這裡只介紹一下 的基本思路。在 Web 直播中比較流行的是通過 http-chunked 模式來實現直播。而 http-chunked 協議很難得到具體播放的進度,那我們就需要一個能夠很容易獲得播放進度的協議--切片協議。
對於切片協議而言,最為突出的就是 HLS,但是它的延時性過高,沒辦法滿足直播低延時的問題。針對這個點,MPEG 提出了一個 DASH 協議,來作為直播內容協議的補充。直播 DASH 是基於 HTTP-URL 的動態直播協議,通過 URL 上面的時間戳就很容易做到對流的時間記錄,整個端的 P2P 流程圖為:
雲端這一步,就主要在 做的事情,右邊的則是本地播放的 IS/MS 處理。而如果你能夠在雲上做好這一整套流程,比如:
那麼,你的 P2P 功能和編碼能力應該比一般程序員高太多了。
入門 Tip
事情需要一點一點做,飯需要一口一口的吃,DASH 由於協議比較複雜,推薦大家先從 HTTP-Chunked 協議入手,自己先搭建一個直播的 DEMO 試試水,這裡推薦一下 HTTPLIVE 庫。
TAG:前端小吉米 |