16. 複数人でのビデオチャット
前項までのビデオチャットプログラムは、1対1のビデオチャットでした。本項では複数人でビデオチャットができるようにします。
解説
WebRTCを用いて複数人でビデオチャットするには、すべての参加者同士でコネクションオブジェクトを作成します。
前項までは、「コネクションオブジェクトは1つのみ」「リモートのユーザー名、映像、音声のHTML要素は1つのみ」でした。
本項では、「コネクションオブジェクトは参加者の数に応じて動的に追加削除する」「リモートのユーザー名、映像、音声のHTML要素は参加者の数に応じて動的に追加削除する」ようにします。
準備
「15. ユーザー名の入力と表示」を実施していない場合は、実施します。
サーバー側の処理
変更なし。
ウェブページ
「public/index.html」ファイルを編集します。
- リモートのユーザー名、映像、音声のHTML要素は参加者の数に応じて動的に追加削除するので、HTMLからは削除します。
- 前項でコメントアウトした「Send OfferSDP.」ボタンを削除します。
「public/index.html」 の内容を以下のようにします。
クライアント側の処理
「public/client.js」ファイルを編集します。
グローバル変数
「コネクションオブジェクトは参加者の数に応じて動的に追加削除する」および「リモートのユーザー名、映像、音声のHTML要素は参加者の数に応じて動的に追加削除する」のためのグローバル変数を追加します。
「グローバル変数」コード部に、以下のグローバル変数の定義を追加します。
- 「ユーザー情報(ユーザー名、映像、音声)」を入れるDIV要素
- グローバルRTCPeerConnectionオブジェクトMap
「リモートのユーザー名、映像、音声のHTML要素は1つのみ」および「コネクションオブジェクトは1つのみ」のために存在したグローバル変数をコメントアウトします。
「グローバル変数」コード部に、以下のグローバル変数の定義をコメントアウトします。
- 「リモートのユーザー名を表示」するためのテキストボックス
- リモートの映像表示用の要素
- リモートの音声再生用の要素
- 単独のグローバルRTCPeerConnectionオブジェクト
カメラとマイクのOn/Offのチェックボックスを押すと呼ばれる関数
「UIから呼ばれる関数」部の「カメラとマイクのOn/Offのチェックボックスを押すと呼ばれる関数」の処理を変更します。
- 単独のグローバルRTCPeerConnectionオブジェクトに対する処理を、グローバルRTCPeerConnectionオブジェクトMapのループ処理に変更します。
「Send Message」ボタンを押すと呼ばれる関数
「UIから呼ばれる関数」部の「「Send Message」ボタンを押すと呼ばれる関数」の処理を変更します。
- コネクションオブジェクトがないかをチェックする処理を、グローバルRTCPeerConnectionオブジェクトMapのサイズがゼロかチェックする処理に変更します。
- 単独のグローバルRTCPeerConnectionオブジェクトに対する処理を、グローバルRTCPeerConnectionオブジェクトMapのループ処理に変更します。
「Leave Chat.」ボタンを押すと呼ばれる関数
「UIから呼ばれる関数」部の「「Leave Chat.」ボタンを押すと呼ばれる関数」の処理を変更します。
- 単独のグローバルRTCPeerConnectionオブジェクトに対する処理を、グローバルRTCPeerConnectionオブジェクトMapのループ処理に変更します。
サーバーからのメッセージ受信に対する処理
「Socket.IO関連の関数」部の「サーバーからのメッセージ受信に対する処理」を変更します。
- "join"と"offer"を受信したときの、「既にコネクションオブジェクトがあるか」の処理を、「単独のグローバルRTCPeerConnectionオブジェクトが存在するか」から、「グローバルRTCPeerConnectionオブジェクトMap」中に「リモートのSocketID」をキーとするものがあるかの処理に変更します。
- "join"と"offer"を受信したときの、「単独のグローバルRTCPeerConnectionオブジェクトへの設定処理」を、「グローバルRTCPeerConnectionオブジェクトMapへの追加処理」に変更します。
- "offer"と"answer"を受信したときの、「リモートユーザー名の設定」の処理を「リモートユーザー名を引数にして、リモート情報表示用のHTML要素を追加する」処理に変更します。
- "answer"と"candidate"を受信したときの、「単独のグローバルRTCPeerConnectionオブジェクトに対する処理」を、「リモートSocketIDをキーとしてグローバルRTCPeerConnectionオブジェクトMapからオブジェクトを取得し、取得したオブジェクトに対して処理」するように変更します。
コネクションの終了処理
「RTCPeerConnection関連の関数」部の「コネクションの終了処理」を変更します。
- 「リモート映像の停止」と「リモート音声の停止」の処理をコメントアウトし、「リモート映像表示用のHTML要素の削除」の処理を追加します。
- 「単独のグローバルRTCPeerConnectionオブジェクトのクリア」の処理をコメントアウトし、「グローバルRTCPeerConnectionオブジェクトMapからの削除」の処理を追加します。
Track イベントが発生したときのイベントハンドラ
「RTCPeerConnection関連の関数」部の「RTCPeerConnectionオブジェクトのイベントハンドラの構築」関数の「Track イベントが発生したときのイベントハンドラ」と「相手のメディアストリームがRTCPeerConnectionから削除されたときのイベントハンドラ」の処理を変更します。
- 「グローバルのリモートの映像表示用・音声再生用の要素に対する処理」を、「リモートSocketIDをキーとしてリモートの映像表示用・音声再生用の要素を取得し、取得した要素に対して処理」するように変更します。
その他の内部関数
「その他の内部関数」部に、以下のリモート情報表示用のHTMLの要素の追加・取得・削除の関数を追加します。
「Send OfferSDP.」ボタンを押すと呼ばれる関数
前項でコメントアウトした「「Send OfferSDP.」ボタンを押すと呼ばれる関数」を削除します。
動作確認
node でサーバーを起動します。
ブラウザを4つ立ち上げ、それぞれのブラウザで「localhost:1337」にアクセスします。
4つのブラウザ間でビデオチャット
インターネットに公開されたサーバーでプログラムを動作させ、4つの端末間でビデオチャット
ダウンロード
デモ
デモ(Google App Engine) : https://my-video-chat.appspot.com/app16/index.html
デモ(Heroku) : https://myvideochat1234.herokuapp.com/app16/index.html
関連ページ
前項目 : 15. ユーザー名の入力と表示
次項目 : 17. チャットルームに分かれてチャット