ライブ配信レイアウトを作るNode.jsのフレームワーク

ライブ配信レイアウトを作るNode.jsのフレームワーク:

こんにちは。普段フロントエンド(とか)エンジニアをしていますが、趣味でRTAをやっている繋がりでオンラインやオフラインのゲームイベントの運営もやってたりします。

この記事、別の話をしようと思っていましたが、悩んだ結果、運営をやっている繋がりでNodeCGというフレームワークを使ったりmaintainerをしたりしている話をしようと思います。


NodeCG

https://nodecg.com
https://github.com/nodecg/nodecg



NodeCG


一言で言うと「ライブ配信のレイアウトをWeb技術で作るフレームワーク」です。

ちょっと何言っているのかわからないですね。

噛み砕くと

  • Twitch、YouTube Live、ニコニコ生放送などのライブ配信で
  • 動的でリッチな見た目の画面表示を作るための
  • 大枠の仕組みを提供するフルスタックフレームワーク
です。

まだどんなものかよくわからないので、サンプルを動かしてみましょう。下のはGamesDoneQuick1というRTAイベントで使われた、NodeCGで作られたレイアウトです。(https://github.com/gamesdonequick/sgdq18-layouts)


Kapture 2018-12-08 at 3.31.39.gif


ついでなので、実際のイベントで動いているところを見てみましょう
https://youtu.be/tsUvZ9yiN_U?t=1433


おおざっぱな説明

バックエンドにexpressが使われ、HTML+CSS+JSでブラウザにレイアウトを表示します。

NodeCGでレイアウトを構築するときにつくる、フロントエンドとバックエンドがセットになったものをbundleと呼んでいます。1つまたは複数のbundleを組み合わせて1つのNodeCGアプリを作るイメージです。

1つのbundleは


  • dashboard: レイアウトを操作するページ

  • graphics: 表示するレイアウトのページ

  • extension: サーバーサイド (今回は省略)
の3つに分かれています。

dashboardで操作すると、NodeCGのサーバーサイドを通してgraphicsに反映され、追加でサーバーサイドのロジックを書きたい場合extensionを定義する、といったものです。



nodecg bundle architecture (1).png



つくってみる

せっかくなので何か作ってみましょう。必要なものはNode 8以上です。


NodeCGをcloneして準備する

なかなかセットアップが原始的ですが、許してください。2018年ですが本当にbowerという文字が見えています。許してください。(ここでしか使う必要はないです。)

$ npm i -g nodecg-cli bower 
$ nodecg setup 
$ mkdir bundles/hoge-layout 
$ cd $_ 
$ npm init -y 


bundleの設定を書く

bundles/hoge-layoutのほうのpackage.jsonに設定を書いていきます。https://nodecg.com/tutorial-5_manifest.html

package.json
{ 
  "nodecg": { 
    "compatibleRange": "^1.0.0", 
    "dashboardPanels": [ 
      { 
        "name": "sample-panel", 
        "title": "Sample Panel", 
        "file": "sample-panel.html" 
      } 
    ], 
    "graphics": [ 
      { 
        "file": "index.html", 
        "width": 1280, 
        "height": 720 
      } 
    ] 
  } 
} 


dashboardを書く

dashboardディレクトリを作り、dashboardに数字をカウントアップするボタンを付けてみます。

dashboard/sample-panel.html
<!DOCTYPE html> 
<html> 
<body> 
    <button id="increment">+1</button> 
    <script> 
        const incrementEl = document.getElementById('increment') 
        const countReplicant = nodecg.Replicant('count') 
 
        incrementEl.addEventListener('click', () => { 
            countReplicant.value += 1 
        }) 
    </script> 
</body> 
</html> 


graphicsを書く

graphicsディレクトリを作り、数字を表示するレイアウトを作ってみます。

graphics/index.html
<!DOCTYPE html> 
<html> 
<body> 
    <div id="count"></div> 
    <script> 
        const countEl = document.getElementById('count') 
        const countReplicant = nodecg.Replicant('count', {defaultValue: 0}) 
 
        countReplicant.on('change', newValue => { 
            countEl.innerText = newValue 
        }) 
    </script> 
</body> 
</html> 


動かす

$ cd ../.. 
$ node . 
これでNodeCGが起動するので、localhost:9090でdashboardを出してみます。


Screen Shot 2018-12-08 at 01.42.41.png


右上のGRAPHICSから、配信レイアウトを出せます


Screen Shot 2018-12-08 at 01.43.56.png


...他に何も書いていないので数字しかいません。実際にレイアウトを作る際は、HTML、CSS、SVGなどを駆使して上の動画みたいなレイアウトを作ります。

さておき、dashboardのボタンを押してみましょう。


Kapture 2018-12-08 at 1.52.14.gif


いい感じでリアルタイムに動いています。


実際の配信での使い方

今までブラウザでレイアウトを表示してきましたが、実施の配信で使うときはブラウザに写しません。何を使うかというと配信ソフトについているブラウザソースの機能です。



Screen Shot 2018-12-08 at 03.39.53.png

Screen Shot 2018-12-08 at 03.40.24.png


例えばOBS Studioは、内蔵のChromiumを使って配信に直接表示することができ、ブラウザに写してそれをキャプチャ、といった煩わしい手順がいらないです。こういった理由で、このような動的なレイアウトはNodeCGでなくてもHTML+CSS+JSが使われることが多いです。


すこし詳しく説明

全機能紹介するとキリがないので、抜粋しつつ


機能

dashboardとgraphicsの中のJSでは、window.nodecgが定義されていて、いろいろなプロパティがいますが、例で使ったのはnodecg.Replicantです。

これはNodeCGの中にある簡易的なデータベースのためのAPIで、代入された値を保存して同時に変更をlistenerに伝える仕組みです。dashboardで数を増やしたら、その瞬間サーバーを通してgraphicsに'changed'イベントが伝えられ、新しい値が伝わります。

Replicantは実際にファイルに保存されるため、何かの不具合でサーバーが落ちたとしても値が保存されます。(やり直しがないライブ配信ではかなり大事な機能です)

他にもいろいろ機能があります


  • message: データのやり取りでなく、イベントを直接やり取りできる機能

  • sound: 音声ファイルをアップロードしておき、キューを送ることでレイアウトで音を再生できる機能

  • asset: 画像や動画ファイルをアップロードして、レイアウトやダッシュボードから参照できる機能
など。

基本的に薄く、unopinionatedに作られているため、例のようにplainなHTMLで作ったり、Reactで書いたりVueで書いたりなんでもできます。 (フレームワークの部分はPolymer 2でできていますが、中身を作る際は関係ありません)


中身の技術

Replicantの代入、変更、mutateに対してJSのProxyを挟むことで、変更を検知して各場所にWebSocketを通じて通知することで、すべての場所で同じデータを見ているような仕組みになっています。。

Proxyは興味深く、IE11で使用できずPolyfillも不可能なためまだ流行っていませんが、IE11を最初からサポートしていないNodeCGではこのような使い方ができています。(将来VueがリアクティビティをProxyで作り直すことも発表されています。)

(dashboardで値の変更)→(proxyがサーバーに通知)→(サーバーがgraphicsに通知)→(graphicsの表示が変更)

フロントエンドのリアクティブなフレームワークがHTMLとJSの間でリアクティビティを実現しているのと同じような関係を、クライアントとサーバーの壁を超えて実現しているあたり面白い仕組みだと思っています。


Maintainerとして

個人的な話をすると、1年半くらい前、このフレームワークを使って関わっているイベントのレイアウトを作るのが、本格的にプログラミングを始めるきっかけでした。

その後、TypeScriptの型定義をつけたり、テストのリファクタリングしたりしていたら、maintainerにならないかと誘われました。それまでは作者のLangeが1人でメンテナンスしてきたこともあり、まだまだ発展途上なフレームワークなので、できるだけ貢献していきたいです。

あと、海外では幅広いイベントで使われているのですが、日本で使っているのが自分ともう1人しか知らないので、もっと流行ってほしいですね!



  1. 同時視聴10万人以上、1週間で2億円以上寄付金を集めるマンモスチャリティイベント。RTAを披露して視聴者から寄付金を募る。 


コメント

このブログの人気の投稿

投稿時間:2021-06-17 05:05:34 RSSフィード2021-06-17 05:00 分まとめ(1274件)

投稿時間:2021-06-20 02:06:12 RSSフィード2021-06-20 02:00 分まとめ(3871件)

投稿時間:2020-12-01 09:41:49 RSSフィード2020-12-01 09:00 分まとめ(69件)