9
1

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.

SkyWayAdvent Calendar 2018

Day 9

カメラ映像を分割してSkyWayで配信するアプリケーションを作ってみた

Posted at

はじめに

この記事は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です。今回は映像のみを扱うため、audiofalseを指定しています。
解像度の指定は1280x720としています。
映像が取得できたらvideosrcObjectに取得したストリームを指定し、映像を表示させます。
その後、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);

こんな感じで指定します。
canvascontextをあらかじめ取得して配列に格納しているので、こんな感じで書くことができます。
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);
}

こんな感じで分割したcacnvas4つ分を取得しています。
あとは、localStreamsMediaStreamが4つ分入った状態になるので、クライアントごとに、それぞれ送ってあげればOKです。
SkyWayでMediaStreamを配信する部分はp2p-broadcastのコードを参考にしました。
配信側では、clientscountという変数を準備しておき、クライアントが接続するたびに1増やすようにしています。
クライアント側に配信するMediaStreamは配列に入っているので、クライアントが接続するたびにまだ配信していない分を配信するようにしています。
クライアント側では、ページにアクセスするときにURLにクエリパラメータとしてsid=xxxxという形式で、配信側のidを指定します。
映像を受信する際は、特に操作は不要で、ページにアクセスするだけで分割された映像が送られてきます。

まとめ

このアプリケーションの使い道として、例えばベゼル幅が狭いFHDモニター4枚と4台のPCで疑似的に4K映像を表示する。といったことができます。
今回はP2Pで通信を行っているため、LAN内であればそれほど遅延は気になりません。
配信側のPCスペックに応じてコマ取得のレートを調節するなどすれば、よりスムーズに動くと思います。

SkyWayのライブラリは映像の取得を自分でコントロールできるため、今回のように加工したストリームを流すこともできます。
アイディア次第で面白いアプリケーションが作れるところもSkyWayの良いところだと感じています。
皆さんもSkyWayを使って、アプリケーションを作ってみてはいかがでしょうか?

9
1
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
9
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?