はじめに
弊社の開発部門では、最近リモートワークが活発に行われ始めております。
その中で、ビデオチャットは頻繁に使われるのですが、なかなか良いものに巡り合っておりません。
というのも、ビデオチャットを行う上で懸念として2点が考えるためです。
- 通信速度
- 機能的制限
現在、Appear.inをメインに利用しております。
理由としては、Google ハングアウトよりは通信速度が出ており、多人数で行えるためです。
しかしながら、制限として8名までなっており、9名以上の拠点の場合、ブラウザを分けるなどを行わなければなりません。
それなら一層のこと試しに作ってみてはと思ったので、チュートリアルを真似しながらサクっと作ってみました。
参考
環境
# | 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ディレクトリ以下に配置してください。
ソースコード
<!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, "<").replace(/>/g, ">");
$("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
実行
- 顔はモザイクいれてます。
- 多人数でできるかなどはお近くの人と試してみてください。
まとめ
- WebRTCを使ったチャットアプリを作っている方は、3,4年前くらいから多々おりますが、シグナリングサーバを作成したりするのに手間が掛かってました。しかし、最近ではSkyWayのようなお手軽簡単にできちゃうAPIやライブラリが揃っていたので苦労することなく構築できました。
- 速度としては、Herokuがどれほどのネットワークを備えているかは不明ですが、Appear.inより体感でも速く感じました。個人のツールとしては良いかもしれません。
- 社内ネットワーク制限がかかっている場合などはあるため、その辺は注意深く確認の必要がありそうです。