はじめに
この記事はSkyWay Advent Calendar 2018の9日目の記事です。
8日目はkolifeさんの「【爆速!】5分でビデオチャットを構築する」でした。
作ったもの
タイトルにある通り、Webカメラの映像を分割し、SkyWayを使ってP2Pで配信するWebアプリケーションを作りました。
イメージとしては「HTML5 JUMBOTRON」の逆のような感じです。
ソースコードはこちらで公開しています。
コミットログを見てわかるように、最初はVue.jsを使ってみようと思いましたが、よくわからずに挫折してしまいました。
SkyWay Advent Calendar 2018の4日目でn0bisukeさんが「Nuxt.jsとSkyWayで1時間でビデオチャットを作ってみる」という記事を書いてくださっているので、こちらを参考に再挑戦してみたいと思います。
仕組み
映像取得
皆さんおなじみ(?)のnavigator.mediaDevices.getUserMedia
です。今回は映像のみを扱うため、audio
はfalse
を指定しています。
解像度の指定は1280x720としています。
映像が取得できたらvideo
のsrcObject
に取得したストリームを指定し、映像を表示させます。
その後、video
からcanvas
に映像の1コマを描画するようにしています。
記述としては、
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
こんな感じです。これで映像の1コマがcanvas
に描画されます。
分割
canvas
に描画した1コマの画像を分割していきます。
今回は2x2の4つのブロックに分割します。
まず、分割した画像を描画するために、4つのcanvas
を用意します。
あとは、それぞれのcanvas
に「元の画像のどの領域を描画するか」を指定して画像を描画します。
例えば、左上の分割画像は、
ctxs[0].drawImage(video, 0, 0, canvas.width / 2, canvas.height / 2, 0, 0, canvas.width / 2, canvas.height / 2);
こんな感じで指定します。
canvas
のcontext
をあらかじめ取得して配列に格納しているので、こんな感じで書くことができます。
drawImage
に関してはMDNのドキュメントが一番詳しいですが、要約すると、
ctx.drawImage(元のデータ,切り取る領域の始点x,切り取る領域の始点y,切り取る領域の幅,切り取る領域の高さ,描画先の始点x,描画先の始点y,描画先の幅,描画先の高さ);
といった感じで指定することで、画像の分割ができます。
あとはこれを4つ分行い、1コマ取得と分割を定期的に行うことで、映像の分割ができます。
配信
分割した映像を配信するためにはMediaStream
を取得する必要があります。
MediaStream
の取得にはcaptureStream
メソッドを使用します。引数はフレームレートです。
今回は、
for (let i = 0; i < splitCanvases.length; i++) {
localStreams[i] = splitCanvases[i].captureStream(10);
}
こんな感じで分割したcacnvas
4つ分を取得しています。
あとは、localStreams
にMediaStream
が4つ分入った状態になるので、クライアントごとに、それぞれ送ってあげればOKです。
SkyWayでMediaStream
を配信する部分はp2p-broadcastのコードを参考にしました。
配信側では、clientscount
という変数を準備しておき、クライアントが接続するたびに1増やすようにしています。
クライアント側に配信するMediaStream
は配列に入っているので、クライアントが接続するたびにまだ配信していない分を配信するようにしています。
クライアント側では、ページにアクセスするときにURLにクエリパラメータとしてsid=xxxx
という形式で、配信側のidを指定します。
映像を受信する際は、特に操作は不要で、ページにアクセスするだけで分割された映像が送られてきます。
まとめ
このアプリケーションの使い道として、例えばベゼル幅が狭いFHDモニター4枚と4台のPCで疑似的に4K映像を表示する。といったことができます。
今回はP2Pで通信を行っているため、LAN内であればそれほど遅延は気になりません。
配信側のPCスペックに応じてコマ取得のレートを調節するなどすれば、よりスムーズに動くと思います。
SkyWayのライブラリは映像の取得を自分でコントロールできるため、今回のように加工したストリームを流すこともできます。
アイディア次第で面白いアプリケーションが作れるところもSkyWayの良いところだと感じています。
皆さんもSkyWayを使って、アプリケーションを作ってみてはいかがでしょうか?