Google は、黒人コミュニティのための人種的公平の促進に取り組んでいます。詳細をご覧ください。

Firebase + WebRTC Codelab

1. はじめに

この Codelab では、ブラウザで WebRTC API とシグナリング用に Cloud Firestore を使用して簡単なビデオチャット アプリケーションを作成する方法を学習します。このアプリケーションは FirebaseRTC と呼ばれ、WebRTC 対応のアプリケーションを作成する基本的な方法を示す簡単な例になっています。

学習内容

  • WebRTC を使用したウェブ アプリケーションでのビデオ通話の開始
  • Cloud Firestore を使用したリモート パーティのシグナル

必要なもの

この Codelab を開始する前に、次のことを確認してください。

  • 一般的に Node.js に付属する npm - ノード LTS が推奨されます

2. Firebase プロジェクトを作成して設定する

Firebase プロジェクトを作成する

  1. Firebase コンソールで [プロジェクトを追加] をクリックし、Firebase プロジェクトに FirebaseRTC という名前を付けます。

Firebase プロジェクトのプロジェクト ID を覚えておいてください。

  1. [プロジェクトを作成] をクリックします。

構築するアプリケーションは、ウェブで利用できる以下の 2 つの Firebase サービスを使用します。

  • Cloud Firestore: 構造化データをクラウドに保存し、データが更新されたらすぐに通知を受け取れます。
  • 静的アセットをホストして提供する Firebase Hosting

この Codelab では、クローンを作成するプロジェクトですでに Firebase Hosting を構成しています。Cloud Firestore については、Firebase コンソールを使用してサービスを構成し、有効にする手順について説明します。

Cloud Firestore を有効にする

アプリは、Cloud Firestore を使用してチャット メッセージを保存し、新しいチャット メッセージを受信します。

Cloud Firestore を有効にする必要があります。

  1. Firebase コンソールのメニューの [開発] セクションで、[データベース] をクリックします。
  2. [Cloud Firestore] ペインで [データベースを作成] をクリックします。
  3. [テストモードで開始] を選択し、セキュリティ ルールに関する免責条項を確認してから [有効] をクリックします。

テストモードでは、開発中に自由にデータベースに書き込むことができます。この Codelab では、データベースのセキュリティを強化します。

3. サンプルコードを取得する

コマンドラインから GitHub リポジトリのクローンを作成します。

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

サンプルコードのクローンは、FirebaseRTC ディレクトリに存在しているはずです。今後はこのディレクトリからコマンドラインが実行されるようにします。

cd FirebaseRTC

スターター アプリをインポートする

エディタで FirebaseRTC のファイルを開き、以下の手順に沿って変更します。このディレクトリには、まだ機能しない WebRTC アプリで構成される Codelab の開始コードが含まれています。この Codelab 全体でこの機能を使えるようにします。

4.Firebase コマンドライン インターフェースをインストールする

Firebase コマンドライン インターフェース(CLI)を使用すると、ウェブアプリをローカルで提供し Firebase Hosting にデプロイできます。

  1. 次の npm コマンドを実行して、CLI をインストールします。sh npm -g install firebase-tools
  1. 次のコマンドを実行して、CLI が正しくインストールされたことを確認します。sh firebase --version

Firebase CLI のバージョンが v6.7.1 以降であることを確認します。

  1. sh firebase login コマンドを実行して Firebase CLI を承認します。

これで、ウェブアプリのテンプレートを作成し、アプリのローカル ディレクトリとファイルから Firebase Hosting のアプリ構成を pull しました。そのためには、アプリを Firebase プロジェクトに関連付ける必要があります。

  1. 次のコマンドを実行して、アプリを Firebase プロジェクトに関連付けます。 sh firebase use --add

  2. プロンプトが表示されたら、プロジェクト ID を選択して、Firebase プロジェクトにエイリアスを指定します。

エイリアスは、複数の環境(本番環境、ステージング環境など)がある場合に便利です。 ただし、この Codelab では、default というエイリアスのみを使用します。

  1. コマンドラインの残りの手順を行います。

5. ローカル サーバーの実行

アプリで実際に作業を開始する準備が整いました。 アプリをローカルで実行しましょう。

  1. 次の Firebase CLI コマンドを実行します。sh firebase serve --only hosting

  2. コマンドラインに次のレスポンスが表示されます。hosting: Local server: http://localhost:5000

Firebase Hosting エミュレータを使用してアプリをローカルに配信しています。これで、ウェブアプリが http://localhost:5000 から利用できるようになります。

  1. http://localhost:5000 でアプリを開きます。

Firebase プロジェクトに接続されている FirebaseRTC のコピーが表示されます。

アプリは自動的に Firebase プロジェクトに接続されました。

6. 新しいチャットルームを作成する

このアプリケーションでは、ビデオチャット セッションをチャットルームと呼びます。ユーザーは、アプリケーションでボタンをクリックすると新しいチャットルームを作成できます。これにより、リモート パーティが同じチャットルームに参加する際に使用できる ID が生成されます。この ID は、各チャットルームの Cloud Firestore のキーとして使用されます。

各客室には、特典と回答の両方の RTCSessionDescriptions と、各当事者の ICE 候補を含む 2 つのコレクションが含まれます。

最初のタスクは、呼び出し元からの初回特典を使用して新しい客室を作成するための欠落しているコードを実装することです。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 候補も交換する必要があります。次のタスクでは、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);
            }
        });
    })
}

この関数は 2 つのことを行います。WebRTC API から ICE 候補を収集してデータベースに追加し、リモートピアから追加された ICE 候補をリッスンして RTCPeerConnection インスタンスに追加します。データベースの変更をリッスンして、新たに追加されていないものを除外することが重要です。そうしないと、同じ ICE 候補のセットが何度も追加されるためです。

9. まとめ

この Codelab では、Cloud Firestore を使用して WebRTC のシグナリングを実装する方法と、それを使用してシンプルなビデオチャット アプリケーションを作成する方法を学習しました。

詳しくは以下のページをご覧ください。

  1. FirebaseRTC ソースコード
  2. WebRTC サンプル
  3. Cloud Firestore