15. ユーザー名の入力と表示
ユーザー名を入力する参加画面を追加します。チャット画面に「自身のユーザー名」と「チャット相手のユーザー名」を表示するようにします。
解説
前項までは、チャットプログラムのウェブページに2人がアクセスしているときに、片方がオファーを送ると、チャットが始まりました。
チャットプログラムのウェブページに1人しかアクセスしていないときに、その1人がオファーを送ると、返って来ないアンサーを待ち続けてしまうという問題がありました。
この問題の解決として、「チャットに参加します。誰かいませんか、いたらオファーを私に送ってください。いなければいいです」という仕組みを取り入れます。
チャットプログラムのウェブページに最初にアクセスした人は、「参加します」という通知をシグナリングサーバーを経由して自分以外に送ります。しかし、自分以外誰もいないため、何も起こりません。
チャットプログラムのウェブページに2番目にアクセスした人も、「参加します」という通知をシグナリングサーバーを経由して自分以外に送ります。最初にアクセスした人は、「参加します」の通知を受けて、「オファー」を作成し、2番目にアクセスした人にオファーを送り、シグナリングが開始し、シグナリングの結果チャットが始まります。
準備
「14. オファーされる側のみビデオ(マイク)をOnにした場合の問題への対応」を実施していない場合は、実施します。
サーバー側の処理
「server.js」ファイルを編集します。
- 「signalingデータ受信時の処理」を変更します。「送信元以外の全員に送信」していた処理を「指定の相手に送信」に変更します。
- 「ビデオチャット参加時の処理」を追加します。"join"を送信元以外の全員に送信します。
「server.js」 の内容を以下のようにします。
ウェブページ
「public/index.html」ファイルを編集します。
- 「div_join_screen」というid名の<div>要素として、ユーザー名入力テキストボックスのある「参加画面」を追加します。
- 既存の「チャット画面」を「div_chat_screen」というid名の<div>要素に格納し、初期表示設定を非表示にします。
- 「ローカル映像表示用の要素」と「リモート映像表示用の要素」の上に「ユーザー名」の表示のためのテキストボックスを追加します。「div_userinfo」というid名の<div>要素に格納します。
- 「Send OfferSDP.」ボタンをコメントアウトします。「Send OfferSDP.」ボタンHTML要素部を「<!--」と「-->」で囲みます。
- 「参加画面」がブラウザの表示領域の端まで覆うように、いくつかのHTML要素のstyleを設定します。
「public/index.html」 の内容を以下のようにします。
クライアント側の処理
「public/client.js」ファイルを編集します。
グローバル変数
「グローバル変数」コード部に、以下のグローバル変数の定義を追加します。
- 「参加画面」に関するDIV要素
- 「チャット画面」に関するDIV要素
- 「ユーザー名を入力」するためのテキストボックス
- 「ローカルのユーザー名を表示」するためのテキストボックス
- 「リモートのユーザー名を表示」するためのテキストボックス
「Join」ボタンを押すと呼ばれる関数の追加
「UIから呼ばれる関数」コード部に、「Join」ボタンを押すと呼ばれる関数を追加します。また、「「Send OfferSDP.」ボタンを押すと呼ばれる関数」をコメントアウトします。
「Join」ボタンを押すと呼ばれる関数は、以下を行います。
- 参加画面で入力した「自身のユーザー名」を、「ローカルのユーザー名を表示」するためのテキストボックスへ設定します。
- サーバーに「join」を送信します。
- 画面をチャット画面に切り替えます。
サーバーからのメッセージ受信に対する処理
サーバーに"join"を送信しすると、サーバーは"join"を送信元以外の全員に送信します。"join"
を受信したクライアントは、OfferSDPの作成と送信の処理を行います。
送信元のSocketIDを取得する処理を追加します。
自身がまだ参加していないときは、"signaling"イベントを無視するようにします。
「Socket.IO関連の関数」コード部の「サーバーからのメッセージ受信に対する処理」に、"join" を受信したときの処理を追加します。
"join" を受信したときには、以下を行います。
- 「「Send OfferSDP.」ボタンを押すと呼ばれる関数」と同様の処理によりOfferSDPを作成します。
- 「RTCPeerConnectionオブジェクトの作成」関数の引数にSocketIDの追加します。
"offer" を受信したとき処理を変更します。
- 「RTCPeerConnectionオブジェクトの作成」関数の引数にSocketIDを追加します。
- リモートユーザー名を「リモートのユーザー名を表示」するためのテキストボックスへ設定します。
"anser" を受信したとき処理を変更します。
- リモートユーザー名を「リモートのユーザー名を表示」するためのテキストボックスへ設定します。
RTCPeerConnectionオブジェクトの作成関数
「RTCPeerConnection関連の関数」コード部の「RTCPeerConnectionオブジェクトの作成」の関数の処理を変更します。
- 関数の引数に、チャット相手のSocketIDを追加します。
- チャット相手のSocketIDを、作成したRTCPeerConnectionのメンバーに追加します。
g_socket.emit()
「RTCPeerConnection関連の関数」コード部の3か所のg_socket.emit() の送信データに「チャット相手のSocketID」を追加します。
- 「RTCPeerConnectionオブジェクトのイベントハンドラの構築関数」の「ICE candidate イベントが発生したときのイベントハンドラ」のg_socket.emit() の送信データに「チャット相手のSocketID」を追加します。
- 「OfferSDPの作成」関数のg_socket.emit() の送信データに「チャット相手のSocketID」を追加します。
- 「OfferSDPの設定とAnswerSDPの作成」関数のg_socket.emit() の送信データに「チャット相手のSocketID」を追加します。
加えて、「OfferSDPの作成」関数と「OfferSDPの設定とAnswerSDPの作成」関数のg_socket.emit() の送信データに「自身のユーザー名」を追加します。
「Leave Chat.」ボタンを押すと呼ばれる関数
「UIから呼ばれる関数」コード部の「「Leave Chat.」ボタンを押すと呼ばれる関数」の処理を変更します。
- 「ローカルのユーザー名を表示」するためのテキストボックスをクリアします。
- 参加画面に切り替えます。
動作確認
node でサーバーを起動します。
ブラウザを2つ立ち上げ、それぞれのブラウザで「localhost:1337」にアクセスします。
ユーザー名を入力する参加画面が表示されます。
ユーザー名を入力し「Join」ボタンをクリックすると、チャット画面が表示されます。
チャット相手がいる場合はチャットが開始します(チャット相手の名前が表示されます)。
ダウンロード
デモ
デモ(Google App Engine) : https://my-video-chat.appspot.com/app15/index.html
デモ(Heroku) : https://myvideochat1234.herokuapp.com/app15/index.html
関連ページ
前項目 : 14. オファーされる側のみビデオ(マイク)をOnにした場合の問題への対応
次項目 : 16. 複数人でのビデオチャット