ビデオチャットアプリを作る ( WebRTC + Node.js + Socket.IO )

WebRTC と Node.js と Socket.IO を用いて、ビデオチャットアプリを作成する方法を解説します。

WebRTCは、JavaScript APIの一つで、リアルタイムP2P通信を提供します。WebRTCを利用すると、ウェブブラウザをクライアントとして、2つのクライアント間で、映像や音声や独自データをリアルタイムに送受信するウェブアプリケーションを作成することができます。
RTCは、 Real-Time Communicationの略です。

使用開発環境は、以下です。
Node.js : version 10.16.3
Express : version 4.17.1
Socket.IO : version 2.3.0

01. 開発環境を準備する
開発環境を準備します。Node.js、Express、Socket.IO をインストールし、簡単なウェブアプリを作成し、動作を確認します。

デモ(Google App Engine) : https://my-video-chat.appspot.com/app01/index.html
デモ(Heroku) : https://myvideochat1234.herokuapp.com/app01/index.html

02. カメラとマイクの開始と停止
カメラとマイクをOn/Offするウェブページを作成します。カメラとマイクを開始/停止する処理を作成します。

デモ(Google App Engine) : https://my-video-chat.appspot.com/app02/index.html
デモ(Heroku) : https://myvideochat1234.herokuapp.com/app02/index.html

03. マニュアルシグナリング(「OfferSDPの作成」まで構築)
WebRTCでは、P2P通信を始める前に、お互いの情報を交換するシグナリングと呼ばれる処理を行います。
シグナリングの手続きを理解するために、「03. 」~「06. 」にかけて、お互いの情報の交換を手動で行う「マニュアルによるシグナリング」の処理を構築します。
「マニュアルによるシグナリング」では、交換する情報をブラウザ画面に表示し、手動のコピー&ペーストによって情報をWebRTCに設定します。
本項では、「マニュアルによるシグナリング」の「OfferSDPの作成」までを構築します。

デモ(Google App Engine) : https://my-video-chat.appspot.com/app03/index.html
デモ(Heroku) : https://myvideochat1234.herokuapp.com/app03/index.html

04. マニュアルシグナリング(「AnswerSDPの作成」まで構築)
WebRTCでは、P2P通信を始める前に、お互いの情報を交換するシグナリングと呼ばれる処理を行います。
本項では、「マニュアルによるシグナリング」の「AnswerSDPの作成」までを構築します。

デモ(Google App Engine) : https://my-video-chat.appspot.com/app04/index.html
デモ(Heroku) : https://myvideochat1234.herokuapp.com/app04/index.html

05. マニュアルシグナリング(「接続完了」まで構築)
WebRTCでは、P2P通信を始める前に、お互いの情報を交換するシグナリングと呼ばれる処理を行います。
本項では、「マニュアルによるシグナリング」の「接続完了」までを構築します。

デモ(Google App Engine) : https://my-video-chat.appspot.com/app05/index.html
デモ(Heroku) : https://myvideochat1234.herokuapp.com/app05/index.html

06. マニュアルシグナリング(「リモートの映像の表示、音声の再生」まで構築)
WebRTCでは、P2P通信を始める前に、お互いの情報を交換するシグナリングと呼ばれる処理を行います。
本項では、「マニュアルによるシグナリング」の「リモートの映像の表示、音声の再生」まで構築をします。

デモ(Google App Engine) : https://my-video-chat.appspot.com/app06/index.html
デモ(Heroku) : https://myvideochat1234.herokuapp.com/app06/index.html

07. シグナリングサーバーによる自動シグナリング
WebRTCでは、P2P通信を始める前に、お互いの情報を交換するシグナリングと呼ばれる処理を行います。
前項までで、「マニュアルによるシグナリング」の処理を構築しました。
本項では、「マニュアルによるシグナリング」の処理を、「シグナリングサーバーによる自動シグナリングの処理」に変更します。

デモ(Google App Engine) : https://my-video-chat.appspot.com/app07/index.html
デモ(Heroku) : https://myvideochat1234.herokuapp.com/app07/index.html

08. チャットからの離脱
前項までで、P2P通信を開始し、リモート映像の表示、音声の再生ができるようになりました。
本項では、「チャットからの離脱」の機能を追加します。

デモ(Google App Engine) : https://my-video-chat.appspot.com/app08/index.html
デモ(Heroku) : https://myvideochat1234.herokuapp.com/app08/index.html

09. STUN Serverへの対応
STUN Serverについて対応し、NAT※を超えたビデオチャットを可能にします。
作成したビデオチャットプログラムをインターネットに公開されたサーバー上に配置し、起動したとき、前項までのビデオチャットプログラムは、ローカルエリアネットワーク内の相手とビデオチャットができますが、同じローカルネットワークにいないインターネット越しの相手とはビデオチャットができませんでした。STUN Serverへの対応を行うことで、インターネット越しの相手ともビデオチャットができるようになります。
※NAT : Network Address Translation : IPアドレスを変換する技術。ローカルエリアネットワーク内でのIPアドレスであるプライベートIPアドレスをインターネットにおけるIPアドレスであるグローバルIPアドレスに変換する技術。

デモ(Google App Engine) : https://my-video-chat.appspot.com/app09/index.html
デモ(Heroku) : https://myvideochat1234.herokuapp.com/app09/index.html

10. Trickle ICE 方式によるシグナリング
前項までのビデオチャットプログラムは、P2P通信しようとする相手にSDPを送信する方法として、Vanilla ICE 方式と呼ばれる「ICE candidate の収集の完了後に、収集したICE candidateを保持するSDPを相手に送信する」という方法を採用していました。
本項では、Trickle ICE 方式と呼ばれる「SDPを作成直後にすぐに相手に送信し、ICE candidateを見つけるごとに相手に送信する」という方法の処理を構築します。

デモ(Google App Engine) : https://my-video-chat.appspot.com/app10/index.html
デモ(Heroku) : https://myvideochat1234.herokuapp.com/app10/index.html

11. 独自データの送受信
前項までに、リモート映像の表示、リモート音声の再生ができるようになりました。
Web RTCを利用すると、映像ストリームデータ、音声ストリームデータの送受信にとどまらず、独自データの送受信を行うことができます。
Web RTCを利用して独自データを送受信を行うには、DataChannelを作成します。
本項では、カスタムデータの送受信として、テキストデータの送受信を行います。

デモ(Google App Engine) : https://my-video-chat.appspot.com/app11/index.html
デモ(Heroku) : https://myvideochat1234.herokuapp.com/app11/index.html

12. カメラ(マイク)の停止と再開
前項までのビデオチャットプログラムは、チャットの途中でカメラの停止をするとチャット相手のリモート映像は静止画像となり、停止したカメラを再開してもチャット相手のリモート映像は再開しません。
本項では、チャットの途中でカメラ(マイク)の停止や再開ができるようにします。

デモ(Google App Engine) : https://my-video-chat.appspot.com/app12/index.html
デモ(Heroku) : https://myvideochat1234.herokuapp.com/app12/index.html

13. チャット離脱の相手への通知
前項までのビデオチャットプログラムは、ビデオチャットを離脱したとき、離脱される側はすぐにはコネクション終了処理が行われませんでした。
本項では、ビデオチャットを離脱したとき、離脱される側ですぐにはコネクション終了処理が行われるようにします。

デモ(Google App Engine) : https://my-video-chat.appspot.com/app13/index.html
デモ(Heroku) : https://myvideochat1234.herokuapp.com/app13/index.html

14. オファーされる側のみビデオ(マイク)をOnにした場合の問題への対応
前項までのビデオチャットプログラムは、オファーした側でカメラ(orマイク)をOnにしなかった場合、オファーされた側でカメラ(orマイク)をOnにしても、カメラ映像(orマイク音声)の通信ストリームは作成されず、カメラ映像(orマイク音声)が相手に送信されません。
本項では、オファーされた側のみカメラ(orマイク)をOnにした場合でも、カメラ映像(orマイク音声)が相手に送信されるようにします。

デモ(Google App Engine) : https://my-video-chat.appspot.com/app14/index.html
デモ(Heroku) : https://myvideochat1234.herokuapp.com/app14/index.html

15. ユーザー名の入力と表示
ユーザー名を入力する参加画面を追加します。チャット画面に「自身のユーザー名」と「チャット相手のユーザー名」を表示するようにします。

デモ(Google App Engine) : https://my-video-chat.appspot.com/app15/index.html
デモ(Heroku) : https://myvideochat1234.herokuapp.com/app15/index.html

16. 複数人でのビデオチャット
前項までのビデオチャットプログラムは、1対1のビデオチャットでした。本項では複数人でビデオチャットができるようにします。

デモ(Google App Engine) : https://my-video-chat.appspot.com/app16/index.html
デモ(Heroku) : https://myvideochat1234.herokuapp.com/app16/index.html

17. チャットルームに分かれてチャット
前項までのビデオチャットプログラムは、サイトにアクセスした人全員が同じチャットに参加しました。本項では、チャットルームに分かれてチャットができるようにします。

デモ(Google App Engine) : https://my-video-chat.appspot.com/app17/index.html
デモ(Heroku) : https://myvideochat1234.herokuapp.com/app17/index.html

参考