27
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

SkyWayを使って多人数ビデオチャットを作ってみた

Last updated at Posted at 2017-07-03

はじめに

弊社の開発部門では、最近リモートワークが活発に行われ始めております。
その中で、ビデオチャットは頻繁に使われるのですが、なかなか良いものに巡り合っておりません。
というのも、ビデオチャットを行う上で懸念として2点が考えるためです。

  • 通信速度
  • 機能的制限

現在、Appear.inをメインに利用しております。
理由としては、Google ハングアウトよりは通信速度が出ており、多人数で行えるためです。
しかしながら、制限として8名までなっており、9名以上の拠点の場合、ブラウザを分けるなどを行わなければなりません。

それなら一層のこと試しに作ってみてはと思ったので、チュートリアルを真似しながらサクっと作ってみました。

SkyWay

参考

環境

# OS/ソフトウェア/ライブラリ バージョン 用途
1 Mac OS X EI Capitan ローカル環境での開発とHerokuへのプッシュなどを行ってます。
2 Heroku - 言わずとしれたかもしれませんが、アプリケーションを動かす無料サーバです。
3 Heroku Git - 今回は、こちらにPushをしております。
4 Node.js v8.1.2 Webサーバとして利用しております。
5 SkyWay - Peerサーバと通信するためのライブラリです。
6 ChromeX 59.0.3071.115 ブラウザ保証としてはこちらのみとなっております。
7 jQuery 1系 実装はこちらを使っております。
8 Git 最新版 Heroku Gitへ色々操作するのに使います。

準備

ローカル環境

anyenvの導入

git clone https://github.com/riywo/anyenv ~/.anyenv

anyenvのPATH設定

if [ -d ${HOME}/.anyenv ] ; then
    export PATH="$HOME/.anyenv/bin:$PATH"
    eval "$(anyenv init -)"
    for D in `ls $HOME/.anyenv/envs`
    do
        export PATH="$HOME/.anyenv/envs/$D/shims:$PATH"
    done
fi

ndenvの導入

anyenv install ndenv
exec $SHELL -l

Node.jsのインストール

ndenv install --list
ndenv install v8.1.2
ndenv global v8.1.2
node -v

Heroku

アカウント登録とログイン

使ったことない方は、Heroku初心者がHello, Herokuをしてみる

アプリケーションの作成

ここでは、video-chatとします。

ドメインの取得

アプリケーション作成後、画面右上の「Open App」をクリックすると、以下のURLにアクセスされます。

ドメインは、「video-chat.herokuapp.com」この部分となります。

SkyWay

アカウント登録

こちらを見れば、すぐわかると思います。
SkyWayを利用するドメインという箇所に先程の「video-chat.herokuapp.com」を入力してください。
また、ローカル環境で利用したい場合は、「localhost」を入力して利用できます。

キーの取得

登録完了後、メールが届きますのでそちらか本登録をすると、キーが取得できます。

準備

Gitのインストール

brew install git

Heroku Gitのインストール

brew install heroku

Heroku Gitのログイン

Herokuに登録したアカウントをパスワードを入力してください。

heroku login

プロジェクトディレクトリの作成

mkdir video-chat

Gitファイルの作成

cd video-chat
git init

公開ディレクトリの作成

cd video-chat
mkdir public

実装

  • multipartyライブラリを用いた多人数ビデオチャットおよびテキストチャット。
  • また、ビデオと音声にはミュート機能を実装しております。
  • スクリーンのシェアも実装はしておりますが、ブラウザのエクステンションが必要なため、そちらの動は行っておりません。ソースコードもコメントアウトしております。
  • index.htmlはpublicディレクトリ以下に配置してください。

ソースコード

index.html
<!doctype html>
<html>
    <head>
        <script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
        <script src="https://skyway.io/dist/0.3/peer.min.js"></script>
        <script src="https://skyway.io/dist/multiparty.min.js"></script>
        <script src="https://skyway.io/dist/screenshare.min.js"></script>
        <style>
            body {
                margin: 0;
            }
            #message {
                width: 190px;
                margin: 10px;
            }
            #streams {
                position: absolute;
                top: 10px;
                margin-left: 200px;
            }
            .video{
                margin: 0px 0px 0px 5px;
                width: 300px;
                border: 1px solid #000000;
                border-radius: 10px;
            }
            #streams .my-video {
                -webkit-transform: scaleX(-1);
                -o-transform: scaleX(-1);
                -moz-transform: scaleX(-1);
                transform: scaleX(-1);
            }
        </style>
    </head>
    <body>
        <div id="message">
            <form>
                <input type="text"><button type="submit">send</button>
            </form>
            <p class="receive">
            </p>
        </div>
        <div id="streams">
            <div>
                <!-- <button id="start-screen" data-muted="false">start screen</button> -->
                <button id="video-mute" data-muted="false">video mute</button>
                <button id="audio-mute" data-muted="false">audio mute</button>
            </div>
        </div>
        <script>
            multiparty = new MultiParty( {
                "key": "{キー}",
                "reliable": true,
                "debug": 3
            });

            screen = new SkyWay.ScreenShare({debug: true});

            multiparty.on('my_ms', function(video) {
                var vNode = MultiParty.util.createVideoNode(video);
                vNode.setAttribute("class", "video my-video");
                vNode.volume = 0;
                $(vNode).appendTo("#streams");
            }).on('peer_ms', function(video) {
                console.log("video received!!")
                console.log(video);
                var vNode = MultiParty.util.createVideoNode(video);
                vNode.setAttribute("class", "video peer-video");
                $(vNode).appendTo("#streams");
                console.log($("#streams"))
            }).on('ms_close', function(peer_id) {
                $("#"+peer_id).remove();
            })

            multiparty.on('message', function(msg) {
                $("p.receive").append(msg.data + "<br>");
            });

            multiparty.on('error', function(err) {
                alert(err);
            });

            multiparty.start();

            $("#message form").on("submit", function(e) {
                e.preventDefault();

                var $text = $(this).find("input[type=text]");
                var data = $text.val();

                if (data.length > 0) {
                    data = data.replace(/</g, "&lt;").replace(/>/g, "&gt;");
                    $("p.receive").append(data + "<br>");
                    multiparty.send(data);
                    $text.val("");
                }
            });

            $('#start-screen').click(function () {
                if (screen.isEnabledExtension()) {
                    screen.startScreenShare({
                        Width: $('#Width').val(),
                        Height: $('#Height').val(),
                        FrameRate: $('#FrameRate').val()
                    },
                    function (stream) {
                        $('#my-video').prop('src', URL.createObjectURL(stream));

                        if(existingCall != null){
                            var _peerid = existingCall.peer;
                            existingCall.close();
                            var call = peer.call(_peerid, stream);
                            step3(call);
                        }

                        localStream = stream;

                    },function(error){
                        console.log(error);
                    },function() {
                        alert('ScreenShareを終了しました');
                    });
                } else {
                    alert('ExtensionまたはAddonをインストールして下さい');
                }
            });

            $('#stop-screen').click(function() {
                localStream.stop();
            });

            $("#video-mute").on("click", function(ev) {
                var mute = !$(this).data("muted");
                multiparty.mute({video: mute});
                $(this).text("video " + (mute ? "unmute" : "mute")).data("muted", mute);
            });

            $("#audio-mute").on("click", function(ev) {
                var mute = !$(this).data("muted");
                multiparty.mute({audio: mute});
                $(this).text("audio " + (mute ? "unmute" : "mute")).data("muted", mute);
            });
        </script>
    </body>
</html>

Webサーバ設定

expressのインストール

対話はすべてEnter押してます。もしかすると初回だけエラーが出力されますが、動作上は問題ないとおもいます。

cd video-chat
npm init
npm install express

package.json

{
  "name": "video-chat",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "node app.js"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.15.3"
  }
}

app.js

デフォルトは3000番なのですが、よくSlackや他のチャットを動かしてるとぶつかるので、他のポートを使うのがオススメです。こちらでは13000番を使ってます。

var express = require('express');
var app = express();

app.use(express.static('public', { hidden: true }));

app.listen(process.env.PORT || 13000);

公開

Heroku Gitへのファイルの追加

cd video-chat
git add .

Heroku Gitへのコミット

git commit -am "new make"

Heroku GitへのプッシュとHerokuサーバへデプロイ

git push heroku master

実行

  • 顔はモザイクいれてます。
  • 多人数でできるかなどはお近くの人と試してみてください。
スクリーンショット 2017-07-03 15.06.38.png

まとめ

  • WebRTCを使ったチャットアプリを作っている方は、3,4年前くらいから多々おりますが、シグナリングサーバを作成したりするのに手間が掛かってました。しかし、最近ではSkyWayのようなお手軽簡単にできちゃうAPIやライブラリが揃っていたので苦労することなく構築できました。
  • 速度としては、Herokuがどれほどのネットワークを備えているかは不明ですが、Appear.inより体感でも速く感じました。個人のツールとしては良いかもしれません。
  • 社内ネットワーク制限がかかっている場合などはあるため、その辺は注意深く確認の必要がありそうです。

全ページリンク

27
23
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
27
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?