Firebase + WebRTC 程式碼研究室

1. 簡介

在這個程式碼研究室中,您將學習如何在瀏覽器和 Cloud Firestore 中使用 WebRTC API 建構簡單的視訊通訊應用程式來傳送訊號。這款應用程式稱為 FirebaseRTC,可以做為簡易範例,協助您瞭解建構 WebRTC 的應用程式的基本概念。

須知事項

  • 使用 WebRTC 在網路應用程式中發起視訊通話
  • 使用 Cloud Firestore 簽署遠端派對

事前準備

安裝這個程式碼研究室之前,請先確認已安裝下列項目:

  • 隨附於 Node.js 的 npm - 建議使用 Node LTS

2. 建立並設定 Firebase 專案

建立 Firebase 專案

  1. 在 Firebase 主控台中按一下 [新增專案],然後將 Firebase 專案命名為 FirebaseRTC。

記下 Firebase 專案的專案 ID。

  1. 按一下 [建立專案]。

您要建構的應用程式會使用兩種網路上的 Firebase 服務:

  • 使用 Cloud Firestore 將結構化資料儲存在雲端,並在資料更新時收到即時通知
  • 使用 Firebase 代管來託管和提供靜態資產

針對這個特定程式碼研究室,您已在目標專案中設定 Firebase 代管。不過就 Cloud Firestore 而言,我們將逐步引導您進行設定,並使用 Firebase 主控台啟用服務。

啟用 Cloud Firestore

應用程式使用 Cloud Firestore 儲存即時通訊訊息,並接收新的即時通訊訊息。

您需要啟用 Cloud Firestore:

  1. 在 Firebase 主控台選單的「開發」專區中,按一下 [資料庫]。
  2. 按一下 Cloud Firestore 窗格中的 [建立資料庫]
  3. 選取 [Start in test mode] (啟動測試模式) 選項,並在閱讀安全性規則的免責事項後按一下 [啟用]。

測試模式可確保您在開發期間可自由寫入資料庫。我們會在這個程式碼研究室中讓資料庫更加安全。

3. 取得範例程式碼

透過指令列複製 GitHub 存放區:

git clone https://github.com/webrtc/FirebaseRTC

程式碼範例應該已複製到 FirebaseRTC 目錄中。 請確認您的指令列現在從這個目錄執行:

cd FirebaseRTC

匯入啟動應用程式

在編輯器中開啟 FirebaseRTC 中的檔案,然後按照下方操作說明變更檔案。這個目錄含有程式碼研究室的起始程式碼,當中包含並非功能專用的 WebRTC 應用程式。我們也會讓程式碼在程式碼研究室中執行。

4. 安裝 Firebase 指令列介面

Firebase 指令列介面 (CLI) 可讓您在本機提供網頁應用程式,並將網頁應用程式部署至 Firebase 代管。

  1. 請執行以下 npm 指令來安裝 CLI:sh npm -g install firebase-tools
  1. 執行以下指令,確認 CLI 已正確安裝:sh firebase --version

確認 Firebase CLI 版本為 6.7.1 以上版本。

  1. 執行下列指令來授權 Firebase CLI:sh firebase login

您已設定網頁應用程式範本,以便從應用程式的本機目錄和檔案擷取 Firebase 代管應用程式的設定。但是,您必須將應用程式與 Firebase 專案建立關聯。

  1. 執行下列指令,將您的應用程式與 Firebase 專案建立關聯:sh firebase use --add

  2. 當系統提示時,請選取您的專案 ID,然後為您的 Firebase 專案指派別名。

如果您有多個環境 (實際工作環境、暫存等),別名就相當實用。不過,在這個程式碼研究室中,我們僅使用 default 的別名。

  1. 按照指令列中的其他操作說明進行。

5. 執行本機伺服器

你現在可以開始使用我們的應用程式了!在本機環境中執行應用程式!

  1. 請執行下列 Firebase CLI 指令:sh firebase serve --only hosting

  2. 您的指令列應該會顯示下列回應:hosting: Local server: http://localhost:5000

我們使用 Firebase 代管模擬器,在本機執行應用程式。網頁應用程式現在可以透過 http://localhost:5000 使用。

  1. 在 http://localhost:5000 開啟應用程式。

您應該會看到已連結至 Firebase 專案的 FirebaseRTC 副本。

應用程式已自動連結至你的 Firebase 專案。

6. 正在建立新房間

在這個應用程式中,每個視訊會議工作階段稱為聊天室。使用者只要按一下應用程式中的按鈕,即可建立新聊天室。這項操作會產生一組 ID,方便遠端伺服器加入相同的會議室。在 Cloud Firestore 中,每組聊天室的 ID 都會做為金鑰使用。

每間聊天室都含有優惠和答案的 RTCSessionDescriptions,以及兩項雙方分別擁有的 ICE 候選人。

第一項工作是導入缺少的程式碼,使用呼叫端的初始優惠建立新聊天室。開啟 public/app.js 並找到註解 // Add code for creating a room here,然後新增下列程式碼:

const offer = await peerConnection.createOffer();
await peerConnection.setLocalDescription(offer);

const roomWithOffer = {
    offer: {
        type: offer.type,
        sdp: offer.sdp
    }
}
const roomRef = await db.collection('rooms').add(roomWithOffer);
const roomId = roomRef.id;
document.querySelector('#currentRoom').innerText = `Current room is ${roomId} - You are the caller!`

第一行會建立一個 RTCSessionDescription,代表呼叫端的優惠。然後設為本機說明,最後寫入 Cloud Firestore 中的新物件物件。

接著,我們會監聽資料庫變更,並偵測呼叫者在何時加入答案。

roomRef.onSnapshot(async snapshot -> {
    console.log('Got updated room:', snapshot.data());
    const data = snapshot.data();
    if (!peerConnection.currentRemoteDescription && data.answer) {
        console.log('Set remote description: ', data.answer);
        const answer = new RTCSessionDescription(data.answer)
        await peerConnection.setRemoteDescription(answer);
    }
});

必須等到呼叫者寫入答案的 RTCSessionDescription,並將其設為呼叫 RTCPeerConnection 的遠端說明時。

7. 正在加入聊天室

下一步是執行加入現有聊天室的邏輯。使用者可以按一下 [加入聊天室] 按鈕,並輸入聊天室 ID 即可加入。您的工作是實作答案的 RTCSessionDescription 建立作業,並視情況在資料庫中更新聊天室。

const offer = roomSnapshot.data().offer;
await peerConnection.setRemoteDescription(offer);
const answer = await peerConnection.createAnswer();
await peerConnection.setLocalDescription(answer);

const roomWithAnswer = {
    answer: {
        type: answer.type,
        sdp: answer.sdp
    }
}
await roomRef.update(roomWithAnswer);

在上述程式碼中,我們首先會從呼叫者擷取優惠,並建立 RTCSessionDescription 做為遠端說明。接著,我們建立答案,並將其設為本機說明,並更新資料庫。資料庫更新會觸發呼叫端的 onSnapshot 回呼,進而根據呼叫者的答案設定遠端說明。如此會完成呼叫者與呼叫者之間的 RTCSessionDescription 物件交換作業。

8.收集 ICE 求職者

來電者和來電者必須能夠彼此交換資訊,通知 WebRTC 如何連線至遠端對等點,呼叫者與來電者才能彼此連線。下一步是實作會監聽 ICE 候選程式碼的程式碼,並新增至資料庫中的集合。找出函式 collectIceCandidates 並新增下列程式碼:

async function collectIceCandidates(roomRef, peerConnection,
                                    localName, remoteName) {
    const candidatesCollection = roomRef.collection(localName);

    peerConnection.addEventListener('icecandidate', event -> {
        if (event.candidate) {
            const json = event.candidate.toJSON();
            candidatesCollection.add(json);
        }
    });

    roomRef.collection(remoteName).onSnapshot(snapshot -> {
        snapshot.docChanges().forEach(change -> {
            if (change.type === "added") {
                const candidate = new RTCIceCandidate(change.doc.data());
                peerConneciton.addIceCandidate(candidate);
            }
        });
    })
}

這個函式會有兩個動作, 他們會從 WebRTC API 收集 ICE 候選項目並新增至資料庫,並監聽遠端對等點新增的 ICE 候選項目,並新增至其 RTCPeerConnection 執行個體。監聽資料庫變更時,請務必篩選掉所有不屬於新的額外項目,因為我們日後可能會不斷新增同一組 ICE 候選項目。

9. 結論

在這個程式碼研究室中,您已瞭解如何使用 Cloud Firestore 實作 WebRTC 信號,以及如何利用這個 API 建立簡易視訊通訊應用程式。

詳情請參閱以下資源:

  1. FirebaseRTC 原始碼
  2. WebRTC 範例
  3. Cloud Firestore