天天看點

實作1V1音視訊實時互動直播系統 十二、第八節 WebRTC用戶端的實作

當收到otherjoin的時候,狀态變成joined_conn,變成這種狀态之後我們就可以做媒體協商了,

socket.on('otherjoin', (roomid) => {
    console.log('receive joined message:', roomid, state);
    state = 'joined_conn';
  });      

這時候還有一個問題,就是說我們有兩個使用者,這時候已經通訊完了,其中主叫方已經離開了,那這個時候留在這個房間裡的使用者,它變成了joined_unbind,就是未綁定狀态,那對于未綁定狀态,這時候又有一個使用者進入進來的時候那它會變成什麼呢?他也會變成這個joined_conn狀态,但是也要重新做一下createConnnection,因為在上一個使用者離開的時候已經把相應的PeerConnection給銷毀掉了,是以現在要重建立一個,那這時候我們要做一個判斷,也就是如果這個時候的狀态是joined_unbind,它要做的就是createPeerConnection也就是創立一個連接配接并進行綁定,這樣我們添加消息和另外一個使用者 加入的消息我們就處理完了。這時候我們把這個狀态列印一下:

socket.on('joined', (roomid, id) => {
    console.log('receive joined message!', roomid, id);
    state = 'joined'

    //如果是多人的話,第一個人不該在這裡建立peerConnection
    //都等到收到一個otherjoin時再建立
    //是以,在這個消息裡應該帶目前房間的使用者數
    //
    //create conn and bind media track
    createPeerConnection();
    bindTracks();

    btnConn.disabled = true;
    btnLeave.disabled = false;
    console.log('receive joined message, state=', state);
  });
  socket.on('otherjoin', (roomid) => {
    console.log('receive joined message:', roomid, state);

    if(state === 'joined_unbind'){
      createPeerConnection();
    }
        state = 'joined_conn';
        // 媒體協商
    console.log('receive other_join message, state=', state);
  });      

在下來就是房間滿了,我之間設定一下狀态就行了,我們不能讓他在這,也就是收到full的狀态的時候 ,實際狀态已經變成leaved了,這個時候我們要将這個連接配接斷掉,否則的話它雖然沒加入到房間,但是與服務端連接配接還在。這時候我們把它這個連接配接給關了。

socket.on('full', (roomid, id) => {
    console.log('receive full message', roomid, id);
    state = 'leaved';
    console.log('receive full message, state=', state);
        socket.disconnect(); // 這個時候我們要将這個連接配接斷掉
    alert('the room is full!');
  });      

在下一個就是leaved,對于leaved來說其實就是在我們主動調leave的時候已經做了一些邏輯,收到leave之後就關閉這個連接配接 就好了其實不用做太多的事情, 和上面的full其實是一樣的,

socket.on('leaved', (roomid, id) => {
    console.log('receive leaved message', roomid, id);
    state='leaved'
    socket.disconnect(); // 關閉連接配接
    console.log('receive leaved message, state=', state);

    btnConn.disabled = false;
    btnLeave.disabled = true;
  });      

最後一個是當我們收到對端走開的時候,那這個時候要把狀态變成joined_unbind,無論你以前是join_conn還是joined狀态,這時候當有一個使用者走的時候,我們這時候都變成了未綁定的狀态,

socket.on('bye', (room, id) => {
    console.log('receive bye message', roomid, id);
    state = 'joined_unbind';
    createPeerConnection();
    console.log('receive bye message, state=', state);
  });      

這個就是收到了伺服器發來的消息,我們做了相應的處理,一共是5個。

那接下來就是端對端的消息;那當我們收到端對端的消息會怎麼樣,那實際收到端對端的消息實際主要就是媒體協商這塊的,,但是對于這個消息我們還是可以寫一個發送媒體協商的消息,媒體協商這塊我們下次再介紹。

socket.on('message', (roomid, data) => {
        console.log('receive client message:', roomid, data);
  });      

那這樣我們基本上就将整個邏輯基本上寫完了 ,這裡還有一個leave,當leave的時候我們發送了一個leave消息,然後将這個對應的值給設好了,但實際當我們真正離開的時候,我們還是要關閉我們相應的資源的,這個資源就包括了我們現在使用的PeerConnection以及我們開啟的這個音視訊裝置,是以這塊我們要準備一個釋放資源的。

我們要将連接配接和自己的媒體的裝置關閉 ,關閉媒體裝置實際就是關閉它的track.

function leave() {

  if(socket){
    socket.emit('leave', roomid); //notify server
  }

  closePeerConnection(); // 将連接配接關閉
        closeLocalMedia(); // 關閉媒體的裝置

  btnConn.disabled = false;
  btnLeave.disabled = true;
}      
function closeLocalMedia(){
  if(localStream && localStream.getTracks()){
    localStream.getTracks().forEach((track)=>{
      track.stop();
    });
  }
  localStream = null;
}      

那麼我們整個連接配接PeerConnection這塊就完成了;

也就是說這節我們首先實作了如何去建立一個 PeerConnection,PeerConnection有一個參數pcConfig,pcConfig實際有好幾個參數,最主要的是這個iceServers,在這個 iceServer裡我們配了一個TURN 服務 ,有使用者名密碼,當我們建立了這個連接配接之後就将這個連接配接設定進去了,在PeerConnection裡我們要監聽兩個事件,第一個是onicecandidate,當我們後面做協商的時候,這個onicecandidate就會被收集到,當我們收集到的時候,這裡需要發送給對端做端對端的消息傳輸,這裡我們沒有做 ,我們先打個日志,這樣就發現了對應的candidate,但是這時候肯定 不會觸發了,因為我們沒有做媒體協商,也沒有做setLocalDesciption,是以這塊肯定不會觸發;

另外一個就是當我們建立這個資料連接配接之後,它會有遠端的資料過來觸發這個ontrack事件,當收到ontrack這個事件之後我們會擷取其中的一個流,然後我們将它設定到遠端的remoteVideo上去,這樣就可以顯示遠端的資料了,那在這裡我們也可以看到,在PeerConnection裡面我們可以同時傳多路流過來,建立完這個peerconnection之後我們又将本地擷取的localStream,然後從它這裡擷取了對應的音頻和視訊這些Track,與這個PeerConnection進行了一次綁定,也就是把它添加到這個PeerConnection裡面,對這個就是getMediaStream擷取到的,這是建立連接配接。

實作1V1音視訊實時互動直播系統 十二、第八節 WebRTC用戶端的實作
實作1V1音視訊實時互動直播系統 十二、第八節 WebRTC用戶端的實作
實作1V1音視訊實時互動直播系統 十二、第八節 WebRTC用戶端的實作