Node.js
websocket
WebRTC
OriginalFusic Day 21

WebRTCでビデオチャットアプリを作ってみた!

こんにちは!
Fusic Advent Calendar 2017 21日目の記事です。
WebRTCを触ってみた話をさせていただきます。

WebRTCとは

WebRTC(Web Real-Time Communication)は、ウェブブラウザーの間で特定のプラグインがなくても通信できるAPIです。
W3Cで提示された草案であり、映像、音声、P2Pファイル共有などで活用できます。

WebRTCで提供するAPIは以下の三つです!

①MediaStream

ユーザー端末機のビデオ、マイクにアクセスできます。
getUserMediaを使ってアクセスし、MedisStreamオブジェクトをPeerConnectionに渡して転送することになります。

②PeerConnection

一番重要なAPIであり、ブラウザ間でビデオ、音声などのやりとりするAPIです!

③DataChannel

ブラウザ間でのテキストやファイルなどをやりとりします。

事前準備

  • Webサーバー
  • Node.js
  • WebSocket

カメラを触ってみよう

Webサーバーに以下のサンプルコードを作成し、試してみましょう!

sample.html
<!doctype html>
<html>
 <head>
  <title>Self Camera</title>
 </head>
 <body>
   <video id="myVideo" width="400" height="300" autoplay="1" ></video>

   <script type="text/javascript">
    navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || window.navigator.mozGetUserMedia;
    window.URL = window.URL || window.webkitURL;

    var video = document.getElementById('myVideo');
    var localStream = null;
    navigator.getUserMedia({video: true, audio: false}, 
     function(stream) { // for success case
      console.log(stream);
      video.src = window.URL.createObjectURL(stream);
     },
     function(err) { // for error case
      console.log(err);
     }
    );
   </script>
 </body>
</html>

最初ブラウザーからアクセスすると、カメラにアクセスしてもいいかどうかの確認ダイアログが表示されるので、
OKボタンを押して許可してください。

シグナリングサーバーを動かす

WebRTCの通信について

WebRTCでは、映像や音声などリアルタイムに取得されたデータを、ブラウザ間で送受信することができます。
それを司るのが RTCPeerConnection です。 RTCPeerConnectionには2つの特徴があります。

  • Peer-to-Peer(P2P)の通信 → ブラウザとブラウザの間で直接通信する
  • UDP/IPを使用 → TCP/IPのようにパケットの到着は保障しないが、オーバーヘッドが少ない(らしい)

P2P通信を行うために

ブラウザ間でP2P通信を行うには、
- 相手のIPアドレス
- 動的に割り振られるUDPのポート番号

を知る必要があります。

そのために、WebRTCでは以下の情報をやり取りしています。

  • SDP (Session Description Protocol)

    • セッションが含むメディアの種類(音声、映像)、
    • メディアの形式(コーデック)
    • IPアドレス、ポート番号 などなど
  • ICE (Interactive Connectivity Establishment)

    • P2Pによる直接通信
    • NATを通過するためのSTUNサーバーから取得したポートマッピング → 最終的にはP2Pになる
    • Firefallを越えるための、TURNによるリレーサーバーを介した中継通信

ということでシグナリングサーバーを動かしてみよう!

P2Pを始めるまでの情報のやり取りを「シグナリング」と言います。
シグナリングサーバーは、クライアントからメッセージを受け取ったら他のクライアントに送信する役割をします。

WebSocketをのインストール

npm install ws

シングルサーバーサンプルコード

signaling.js
"use strict";

let WebSocketServer = require('ws').Server;
let port = 9000; //ポート番号は必要に応じて変更してください。
let wsServer = new WebSocketServer({ port: port });
console.log('websocket server start. port=' + port);

wsServer.on('connection', function(ws) {
    console.log('-- websocket connected --');
    ws.on('message', function(message) {
        wsServer.clients.forEach(function each(client) {
            if (isSame(ws, client)) {
                console.log('- skip sender -');
            }
            else {
                client.send(message);
            }
        });
    });
});

function isSame(ws1, ws2) {
    // -- compare object --
    return (ws1 === ws2);     
}

シングルサーバーを起動

node signaling.js

実際に動かしてみよう!(結果)

ブラウザーからアクセスし、スクリプトを読み込むと

こんな感じです!

最後に

何よりもFusic開発合宿で普段から自分が作りたかったものや
新しい技術を勉強できて、とても楽しめたと思います!

まだまだいけてないところや課題もたくさんあるんですが、引き続き勉強しつつ発展させていきたいと思います!!

参考リンク

  • WebRTC入門2016 大変参考になりました!!
  • あと、SkyWayというサービスもありますので、参考までに・・