1. 程式人生 > >從零到一,使用實時音視訊 SDK 一起開發一款 Zoom 吧

從零到一,使用實時音視訊 SDK 一起開發一款 Zoom 吧

從零到一,使用實時音視訊 SDK 一起開發一款 Zoom 吧

zoom(zoom.us) 是一款受到廣泛使用的線上會議軟體。相信各位一定在辦公、會議、聊天等各種場景下體驗或者使用過,作為一款成熟的商業軟體,zoom 提供了穩定的實時音視訊通話質量,以及白板、聊天、螢幕共享、PPT放映等常用功能。但是在當今瀏覽器成為端上主流的時代,實時音視訊又怎甘於落後呢?相比於需要安裝包的 Zoom,直接在網頁上開發一款類似的會議軟體肯定會受到更多的關注。當需要開會的時候,直接通過一個連結,大家就可以接入並開始會議了。現在,使用七牛實時音視訊的 Web SDK,我們可以將您的想法輕鬆變為現實。

首先,讓我們梳理一下一款Web的線上會議產品需要哪些關鍵點需要攻破

  • 瀏覽器相容性要好,需要支援大部分主流桌面瀏覽器。

七牛實時音視訊基於 Google 在 Chrome 上推行的 WebRTC 協議,目前該協議已經正式寫入 Web 標準之中,所有的現代瀏覽器對其都有很好的相容性。

  • 通話質量要好,延遲低,清晰度高

不同於傳統 WebRTC 採用使用者和使用者 P2P 的形式進行通訊,我們使用了在全球範圍內部署的節點作為低延遲的實時互動網路來和各個端上進行 P2P 通訊,在保證延遲的同時也保證了通話的質量。

  • 會議功能要豐富,ppt演示、白板、螢幕共享等等我都要

我們的 SDK 提供了豐富的功能列表,滿足絕大多數會議場景的需求,理論上使用 SDK 可以完全復刻一個 Web 版本的 zoom。

  • 說了這麼多,接入難不難?有沒有示例和文件?

當然!目前就可以去體驗我們 Web 的 Demo(在桌面瀏覽器下開啟)。https://demo-rtc.qnsdk.com。Demo 的原始碼也開源在 Github 上供各位參考 https://github.com/pili-engineering/QNRTC-Web

這個 Demo 實現了絕大多數 SDK 直接提供的功能,整合白板/PPT共享/聊天等場景的 Demo 目前還在準備上線中,敬請期待哦。關於接入的具體過程我們下面將會簡單地介紹一遍,詳細的說明和參考可以移步我們的文件站 https://developer.qiniu.com/rtn/sdk/4412/description-of-web-sdk

開發流程

一個簡單的會議產品,一般是通過如下流程:

  • 使用者註冊/登陸 (開發者自己整合,SDK 只需要用於區分使用者的 userID)
  • 建立一個會議房間/加入一個會議房間
  • 採集自己的攝像頭/麥克風資料
  • 將採集到的媒體資料釋出到房間中
  • 訂閱房間裡其他人的媒體資料並實時播放
  • 處理使用者加入/離開,釋出/取消釋出

這裡簡化到 SDK 的各個功能,其實就是 加入房間-採集本地媒體流-釋出媒體流-訂閱媒體流-事件處理,SDK 對每個步驟都做了簡單的封裝,使用幾行程式碼即可搞定。

引入 SDK

推薦使用 npm 引入我們的 SDK,直接 npm i pili-rtc-web 即可,或者可以選擇直接引入打包好的 js 檔案 https://github.com/pili-engineering/QNRTC-Web/blob/master/Release/pili-rtc-web.js

非同步處理

實時音視訊是一個強非同步的場景,各種各樣的操作因為涉及到網路都是非同步相關的,為了讓開發者能夠更好地控制程式碼編寫過程中的非同步邏輯。SDK 沒有使用繁瑣的 callback 模式,而是使用了現代 Javascript 的 async/await 或者是 Promise 特性來編寫非同步程式碼,儘量避免了開發過程中回撥地獄的情況(以下所有 await 程式碼都假定在一個 async 函式包裹之下)。

加入房間

準備完畢後,第一步,加入房間。說是加入房間,抽象後的說法其實是“什麼使用者以什麼身份加入什麼房間”。這裡有 3 個未知量:使用者標識、身份標識(許可權)、房間標識。其實整個加入房間的過程需要的未知量還有很多,比如房間隸屬於哪個 APP(應用,不同應用中房間獨立),APP 隸屬於哪個七牛賬戶等等。在這裡我們將這些值統一進行編碼簽名,變成一個 roomToken 提供給前端,端上就只需要通過這個 token 即可加入房間。(token 的生成可以在七牛控制檯完成,也可以使用服務端 SDK 根據需要動態生成)

const myRTC = new QNRTC.QNRTCSession(); // 初始化
await myRTC.joinRoomWithToken(ROOM_TOKEN); // 加入房間

採集本地媒體流

一般採集都會同時採集音訊和視訊,即麥克風和攝像頭,但是根據需求 SDK 也支援純音訊採集或者純視訊採集的模式。呼叫方法也很簡單,更改一下 options 即可。

const DOM_ELEMENT = ... // 頁面上準備用來播放流的 dom 元素
// 採集本地流
const localStream = await QNRTC.deviceManager.getLocalStream({
    video: { enabled: true },
    audio: { enabled: true },
});
// 播放採集到的流
localStream.play(DOM_ELEMENT)

釋出媒體流

直接將剛剛拿到的流物件作為參賽,呼叫 publish 方法即可

await myRTC.publish(localStream);

訂閱媒體流

當加入房間成功後,隨時可以通過訪問 users 成員來獲取當前房間內使用者狀態,如果房間記憶體在使用者正在釋出且不是自己,那麼我們就可以發起訂閱了

const users = myRTC.users;
users.forEach(async (user) => {
    if (user.published && user.userId !== myRTC.userId) {
        // 訂閱房間其他使用者返回的流資料
        const remoteStream = await myRTC.subscribe(user.userId);
        // 同樣,直接呼叫 play 就可以播放流了
        remoteStream.play(DOM_ELEMENT);
    } 
});

事件處理

SDK 暴露了豐富的事件列表來滿足絕大多數場景的需求,事件的處理也很簡單,以“有其他使用者釋出”這個事件為例

// 監聽事件
myRTC.on('user-publish', handleUserPublish);
// 只監聽一次
myRTC.once('user-publish', handleUserPublish);
// 取消某個監聽函式
myRTC.off('user-publish', handleUserPublish);
// 取消所有監聽函式
myRTC.removeAllListeners('user-publish');

具體的事件列表可以參考 https://developer.qiniu.com/rtn/sdk/4423/the-event-list-web

特色功能

除了這些基本的功能,SDK 還提供了很多強大的高階功能,進一步滿足各行各業的使用需求。

螢幕共享

除了直接採集攝像頭,SDK 還支援進行螢幕採集(或者視窗採集)來實現共享螢幕進行會議。並且在螢幕共享和攝像頭採集之間支援無縫切換,保證使用者的使用體驗。

// 螢幕共享
await QNRTC.deviceManager.getLocalStream({
    screen: { enabled: true },
    audio: { enabled: true },
});

直播轉推

對於一個線上會議而言,參與會議討論的可能只有十個人左右,而卻有大部分的人需要實時地觀看這場會議(但不參與實時討論)。這就是實時音視訊和直播兩大塊場景的交集,將少數有實時互動需求的使用者分配到超低延遲( 200ms )的實時音視訊雲上,將大部分只有實時觀看需求的使用者分配到低延遲( 2~3s )的直播雲上,可以最大限度的減少成本滿足需求。同時,實時視訊流被轉推到直播雲上後,就可以使用七牛直播雲的 API 將這些流資料儲存到各個儲存空間中進行長期的儲存。完成了一個從 實時互動 到 直播觀看 到最後 轉為檔案儲存(用於點播等等)的完整業務流程。

首先,在實時音視訊雲的控制檯頁面上關聯好相應的直播雲空間,再開啟合流轉推的開關。

如果想推送到自定義的 RTMP 地址(不使用七牛直播雲),也通過實時音視訊雲的後端 API 來配置(詳細見文件)

從零到一,使用實時音視訊 SDK 一起開發一款 Zoom 吧
從零到一,使用實時音視訊 SDK 一起開發一款 Zoom 吧

之後的工作就是 SDK 上了,使用 SDK 開啟直播轉推也非常簡單,加入房間後呼叫一行程式碼即可。

myRTC.setDefaultMergeStream(WIDTH, HEIGHT); // 這裡的 width height 對應上文設定的合流輸出尺寸

使用這個程式碼,SDK 將會預設將房間內的所有流平均佈局,最終推送到目標 RTMP 地址實現合流轉推。如果您想自定義畫面佈局,可以使用如下 API:

myRTC.setMergeStreamLayout("目標使用者ID", { w: 100, h: 100, x: 0, y: 0, muted: false, hidden: false });

另外,我們還提供了網頁實時白板的服務,就像 Zoom 一樣,使用者可以在頁面上和房間裡的其他使用者共享一個白板進行輔助演示,同時白板也支援 PPT 和 PDF 的演示。關於這一塊的演示 Demo,可以訪問我們的牛課堂體驗 https://edu-demo.qnsdk.com

以上只是列舉了一款會議軟體常用的功能場景,將這些基本功能和使用者自身的場景整合,一款簡單的會議軟體就能夠輕鬆完成。如果您已經打算開始嘗試並體驗一下,訪問我們的 Demo(見上)會是一個很好的選擇。如果您打算將自己的產品接入到我們實時音視訊中,這裡有一份更為詳細的實時音視訊應用開發實踐https://developer.qiniu.com/rtn/sdk/5043/rtc-application-development-process,從 html/css 到 js,從每一行程式碼到每一個功能都有詳細的解釋和示例,幫助您快速接入。