webRtc及元件之間通訊

qytzj發表於2018-12-18

應公司專案需求。 需要在原先完整專案的基礎上將音視訊通話部分與專案進行分離, 形成單獨的元件。 實現在專案中傳入url, 後彈出model框進行兩端音視訊通話。

通話功能

通話功能的流程是通過頁面上的某個按鈕執行init()方法。 因為用了騰訊雲的音視訊技術。 所以需要在騰訊雲伺服器建立房間, 還有公司本地伺服器建立房間做通話兩端的中間人角色。

import rtc from `path`;

rtc.init(
    obj,           // 建立房間基本資訊欄位
    `p1`,          // 獲取騰訊雲資訊
    `p2`,          // 本地伺服器建立房間
    `p3`,          // 心跳介面
    `p4`,          // 退出本地伺服器房間
    heart,         // 心跳回撥 根據返回值檢視視訊過程
    eventcb,       // 騰訊雲伺服器 發生事件回撥  可不傳
    1,             // 是否需要混流   可不傳
    `p5`,          // 混流介面   可不傳
);

在頁面中引入rtc元件並執行init()方法, 傳入路徑,監聽通話過程的回撥等。

在rtc元件中:

const rtc = {
  ...  // 儲存資訊變數

  init(obj, u1, u2, u3, u4, heart, eventcb, isMixed = 0, u5 = ``) {
    ... // 全域性儲存傳入欄位

    axios.post(u1, Qs.stringify(params)).then((res) => {

      const opt = {
        ...  // 房間資訊
      };
       
      const RTC = that.create(opt);

      Object.keys(that.events).forEach((key) => {
        if (!eventcb) {
          that.eventcb = function (rs) {
            return rs.tip;
          };
        } else {
          that.eventcb = eventcb;
        }

        RTC.on(key, that.events[key]);
      });
    });
  }
}

init()方法中通過傳入的路徑, 首先呼叫後臺初始化介面, 獲取建立房間必要的引數資訊。 同時將資訊存入全域性變數中。 執行create()。 開始在伺服器及騰訊雲伺服器建立房間。 在create中 return RTC; 說明房間建立成功。 events 定義了騰訊雲事件通知, 遍歷key, value, RTC.on 進行監聽. eventcb為傳入的事件回撥。

create(opt) {
    const self = this;

    const RTC = new WebRTCAPI(opt, function () {
      const params = {   
        ... // 建立本地伺服器房間
      };

      axios.post(self.u2, Qs.stringify(params)).then((res) => {
        const createOpt = {
          ...  // 建立騰訊伺服器房間
        };

        RTC.createRoom(createOpt, function() {
          console.log(`建立房間`);

          self.heartbeat();
        })
      });
    });

    return RTC;
  },

heartbeat( ) 遞迴呼叫心跳函式, 對通話過程進行監聽, 比如一端退出房間通過與後臺商定的code值, 即使在本地伺服器退出房間等。

events: {
    onRemoteStreamUpdate(data) { 
      ...  // 遠端流 新增/更新

      if (!rtc.connect) {
        rtc.connect = 1; // 開始通話
        rtc.instance.$emit(`connection`, rtc.connect);
      }

      rtc.eventcb(....);  回撥返回資訊
    },
    onRemoteStreamRemove(data) {
      ...  // 遠端流斷開

      rtc.eventcb(....);
    },
    onRelayTimeout(data) { 
      ...  //  server 超時斷開
    
      rtc.eventcb(....);
    }
  },

eventcb 如果傳入能確保在執行init( )方法的頁面得到通話過程中的事件執行資訊。

元件通訊

init( )與rtc.js 可以通過回撥傳參的方式進行通訊, 但rtc.js 與 通話皮膚之間無法通過這種方式進行資訊傳遞。 比如需要在rtc.js 通知 model通話開始, 這時需要開始計時等。 vuex, bus無法在這種情況下使用. 所以通過 Vue.extend( ) , 在Vue構造器上建立子類。 註冊到全域性。 使用vm.$emit 及 vm.$om 釋出訂閱事件

import rtcContainer from `./view.rtc`;

init( ... ) {

  ...

  const callPanel = Vue.extend(rtcContainer);

  this.instance = new callPanel({
    propsData: {
      // 傳值
    }
  }).$mount();

  document.body.appendChild(this.instance.$el);
}

如果$mount( )不傳值,沒有掛載節點, 也會生成callpanel例項。這是一個坑,而後將其掛載到body上。 在需要的地方$emit釋出事件.

結語

做完這些初步完成以專案為基礎的元件抽離,程式碼太次,正在優化。

相關文章