webrtc原理及相關api使用邏輯

eason,發表於2018-08-16

#簡單剖析webrtc,並結合easyrtc與coturn(stun,turn)服務實現音視訊聊天

  • webRTC全稱為Web Real-Time Communications,即web實時通訊

  • 音視訊聊天實現前提,跟直播不一樣哦~api型別繁多,有的也過時了,見到有不同的就翻翻MDN,換個方案吧,谷歌需要https或者localhost才能開啟媒體許可權,火狐則不需要,但做相容很費工夫。localhost下就自己開兩個網頁測吧,後面會講easyrtc

    • 理解websocket連線/websocket算是node.js最繁華的領域了,socket.io簡單粗暴https://github.com/socketio/socket.io.git
    • 理解webrtc的工作流程 juejin.im/post/5b3f50…
      • stun伺服器作用,獲取雙方ip協助建立連線
      • turn伺服器作用,轉發音視訊
      • 信令伺服器作用,利用socket.io實現,主要就是轉發音視訊聊天雙方的軟硬體資訊ip,裝置資訊,協助直連或者視訊轉發
  • 簡化文章內容介紹,webrtc流程,以下在內網中可以執行

    • 1.獲取使用者音視訊媒體,完成這步,即可看到自己的攝像頭影像
      navigator.mediaDevices.getUserMedia({
        audio: true,
        video: true,
      }).then((stream) => {
        let video = document.querySelector('#video')
        video.srcObject = stream  // mediaDevices.getUserMedia獲取到的音視訊流捆綁在video標籤上
        video.onloadedmetadata = () => video.play() // 讀取資料時進行播放
      })
    複製程式碼
    • 2.進行peertopeer點對點連線,
      • 2-1.房主createOffer回撥中能取到房主的資訊desc,音視訊結構軟硬體資訊,儲存本地,並且傳送到信令伺服器,協助轉發
        let peer = new RTCPeerConnection(servers)
        pc.createOffer(sendOffer, function (error) {
          console.log('傳送 offer 失敗')
        })
        function sendOffer (desc) {
          console.log('sendOffer')
          pc.setLocalDescription(desc);
          socket.emit('offer', JSON.stringify({
          data: {sdp: desc}
            })
          )
        }
      複製程式碼
      • 2-2.房主createOffer時會觸發自身連線的onicecandidate事件,獲取candidate,使用者地址等
        pc.onicecandidate = function(event) {
          if (event.candidate !== null) {
              socket.emit("_ice_candidate",JSON.stringify({
                type: '_candidate',
                data: {
                  candidate: event.candidate
                }
              })
            )
          }
        };
      複製程式碼
      • 2-3.對方在socket中收到offer時,將其設定為遠端描述,offer對應的為answer,建立時會觸發該使用者的onicecandidate事件,能獲得到其使用者地址資訊,此時將描述發給房主
        socket.on('offer', function(e) {
          getUserMedia(function (stream) {
          let vid1 = document.getElementById('vid1')
          vid1.srcObject = stream
          vid1.onloadedmetadata = function(e) {
            vid1.play();
          };
          pc.addStream(stream)
          var json = JSON.parse(e) 
          pc.setRemoteDescription(new RTCSessionDescription(json.data.sdp));
          pc.createAnswer(sendAnswer, function (error) {
            console.log('建立answer失敗')
          })
          }, function (error) {
            console.log('攝像頭獲取失敗', '接聽視訊失敗');
          })
        })
        function sendAnswer(desc) {
          pc.setLocalDescription(desc);
          socket.emit('answer', JSON.stringify({
            type: '_answer',
            data: {
              sdp: desc
            }
          }))
        }
      複製程式碼
      • 2-4.房主在接收answer的socket事件中將其設定為遠端描述
        socket.on('answer', async function(e) {
          let data = e.message
          await peer.setRemoteDescription(data)
        })
      複製程式碼
  • 外網實現點對點音視訊聊天 ICE(結合stun,turn進行穿透獲取音視訊雙方地址)

    • STUN解析
      • 但現實中我們的視訊通話,不可能侷限在內網,可能會在防火牆,NAT之後,點對點連線之前,我們需要檢測是否能進行,該技術稱為NAT穿透,通常基於UDP協議,如RFC3489。在新的RFC5389中支援了TCP穿透
    • TURN解析
      • TURN使用中繼穿透NAT:STUN的擴充套件,跟STUN一樣都是通過修改應用層中的私網地址達到NAT穿透的效果,異同點是TURN是通過兩方通訊的“中間人”方式實現穿透。就有點像伺服器轉發音視訊流的意思,在STUN失敗時會走TURN
    • NAT作用是啥
      • 為了緩解全球ip不足,NAT可以將內網的私有地址轉為外網的共有地址,從而可以進行internet訪問
      • 防止外部主機攻擊內部主機
    • 當然前端開發是不熟悉這些的,閱讀多篇RTC部落格得知谷歌開源了stun,coturn相關的服務,只需要將依賴安裝,賬號密碼加密設定即可使用參考文獻https://www.cnblogs.com/idignew/p/7440048.html
    • 配置完畢coturn後測試地址,返回有relay屬性為伺服器地址證明成功https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/

webrtc原理及相關api使用邏輯

  • easyRTC

    • 經過多次測試,自己的RTCdemo相容性差,目前測試階段就不手寫了。採用了easyRTC,除了safari和古董ie不行,其他方面還是ok的。github.com/priologic/e…

webrtc原理及相關api使用邏輯

  • 注意採用beta分支,為最新的專案

相關文章