you が 2021年05月16日19時44分23秒 に編集
初版
タイトルの変更
obniz Board のみでできる!シンプルな OBS のシーンスイッチャー
タグの変更
obniz
obnizBoard
obnizBoard1Y
obnizIoTコンテスト
OBS
JavaScript
Nodejs
本文の変更
今回作ったものは、オンラインイベント配信などでも利用される [OBS Studio(以下、OBS)](https://obsproject.com/ja)に関するものです。 具体的には、[obniz](https://obniz.com/ja/) を操作することで OBS で作った複数の画面構成(カメラ映像とスライドを合成した画面や、テキストを表示した画面、カメラのみを表示した画面など)を切り替えるものです。 この切り替えは、通常は OBSアプリ上のボタンを操作して行うのですが、今回はこれをアプリの外での操作(obniz Board のスイッチ操作)で実現します。 # デモ動画 まずは以下のデモで、どのような動きをするものであるかをご覧ください。 obniz Board のスイッチを操作することで、OBS上で用意した 3つのシーン(画面構成)の切り替えが行えています。 @[youtube](https://www.youtube.com/watch?v=9oFZiT7dlKQ) # 必要なもの(デバイス・部品・アプリ) 今回、用いるデバイス・アプリは以下のとおりです。 obniz関連の部分は、外付けのボタン等の部品を用いないですむような構成で実現しています。そのため obniz さえ用意できればシンプルにお試しいただけます。 - obniz Board(今回は、obniz Board 1Y) - PC - OBS Studio(+プラグイン) ## OBS のプラグイン関連の補足 ここで少し OBS 関連の内容を補足します。 OBS のアプリは、[公式のダウンロードページ](https://obsproject.com/ja/download)からダウンロードします。 それと合わせて、今回の OBS の外部からの操作にはプラグインの追加が必要です。具体的には、[obs-websocket](https://github.com/Palakis/obs-websocket) というプラグインを用います。インストールに必要なファイルは、[GitHub にある obs-websocket の Releases のページ](https://github.com/Palakis/obs-websocket/releases)から入手できます。 手順としては、OBS のインストール後に obs-websocket のインストールを行ってください。それと OBS上でのプラグインの設定も必要になるのですが、それについては以下のソースコードを掲載した部分の前に記載しています。 # 設計図・システム構成 上で書いたとおり、今回の構成は非常にシンプルです。 以下の図のように、obniz Board と OBS(+プラグイン)がインストールされた PC だけがあれば OK です。 ![構成図](https://camo.elchika.com/82fd60751d12fe9e9273324e1ef8070513d503ba/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f39643166303338632d613130612d343237612d393435312d3862313266633865313763382f64643036373261662d663064622d346336312d613463392d323932393862326432643230/) なお、この後に出てくる obniz のプログラムは、今回は OBS がインストールされた PC上で動作させることとします。 # アプリの設定・ソースコード ## アプリ(OBS)の設定 上で書いた手順を進めていると、この時点で PC には OBS(+プラグイン)がインストールされた状態になっていると思いますが、あともう少し準備が必要です。 ### シーンの準備 ここで、obniz を操作して切り替えるシーン(画面構成)を設定します。 今回のプログラムでは 3つのシーンを使います。以下でシーンの追加手順を簡単に説明していきます。 まずは以下の図にあるとおり、OBS上でシーン・ソースの追加を行います。 ![シーンの追加](https://camo.elchika.com/68eeda5968bd23ce4922b19143d664504a9e11cd/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f39643166303338632d613130612d343237612d393435312d3862313266633865313763382f35383034333834622d653362342d343735642d383037362d393061623733386431356436/) シーンを 3つ準備し、さらに 3つのシーンそれぞれに対してソースを追加します。 ソースというのは画面に表示させる要素のことで、以下の画像に出ているようにたくさんの種類から選ぶことができます。さらに、それらを複数組み合わせることもできます。 ![シーンで追加できる内容の一覧](https://camo.elchika.com/900b1720c7fe2e52de4500df073e996b24845227/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f39643166303338632d613130612d343237612d393435312d3862313266633865313763382f32343437346132612d393235302d346439302d613837652d653934323732373065306536/) 今回の記事の例では「ウィンドウキャプチャ(PC上の特定の領域を取得して表示)」、「テキスト(文字を表示)」、「映像キャプチャデバイス(カメラ等)」を組み合わせて利用しています。 この後で利用するシーンの種類は以下のとおりです。 - 休憩中の表示 - 内蔵カメラの映像 - カメラと画像 ![今回利用する 3つのシーン](https://camo.elchika.com/e52c2e43a5683ef71ab55fea70c9a24fbf6d216c/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f39643166303338632d613130612d343237612d393435312d3862313266633865313763382f39303566666534642d326539382d346538622d393136662d393038643064333231623965/) これらの 3つのシーンの名称は、後に出てくるソースコードの中で利用します。 ### プラグインの有効化 次に、obniz との接続に使う Websocket のプラグインの設定を行います。 OBS のメニューから「ツール」を選び、その中にある「Websocket サーバー設定」を選んで以下のウィンドウを表示させてください。その後、「Websockets サーバーを有効にする」にチェックを入れてください。 ![Websocket サーバー設定](https://camo.elchika.com/6eed6b7fdd08759478440b85f0f60631bbc0508c/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f39643166303338632d613130612d343237612d393435312d3862313266633865313763382f31323532313063632d383639622d343766332d613862332d313165646135343065323334/) また、サーバーポートはデフォルトの 4445 をそのまま利用することにします。後で使う番号なので、念のためここで設定を確認しておきましょう。 その下の「認証を有効にする」は今回は無効にしています。ローカルのPC内で Websocket の通信を行うだけで PC の外部から OBS へのアクセスはできない状態(※ 自分で準備するプログラム経由で obniz Cloud とつながる部分はありますが)で、また、OBS を起動中にしか利用しない一時的なものなので、プログラムをシンプルに組むためにもこの内容にしています。 ## ソースコード あとは、プログラムを実行して obniz を操作すれば、今回の内容は実現可能です。 プログラムについては、ブラウザ上で実行するバージョンと、Node.js を用いて実行するバージョンの両方を用意してみました。どちらかお好みのほうをご利用ください。 ### 【ブラウザ版】ブラウザ上で実行するためのプログラム 以下のプログラムはブラウザ上で実行して利用するものです。 以下の内容を書いた HTMLファイルをブラウザで直接開いて利用することもできます。 ```html:ブラウザで実行するためのプログラム <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>OBSコントローラー</title> <script src="https://unpkg.com/obniz@3.14.0/obniz.js"></script> </head> <body> <script> let sceneNum = 0; const message = [ { "request-type": "SetCurrentScene", "message-id": 【任意のID】, "scene-name": 【OBSのシーンの名称(1つ目)】, }, { "request-type": "SetCurrentScene", "message-id": 【任意のID】, "scene-name": 【OBSのシーンの名称(2つ目)】, }, { "request-type": "SetCurrentScene", "message-id": 【任意のID】, "scene-name": 【OBSのシーンの名称(3つ目)】, }, ]; const socket = new WebSocket("ws://localhost:4445"); socket.addEventListener("open", function (event) { console.log(event); }); console.log("start!!"); let obniz = new Obniz("OBNIZ_ID_HERE"); console.log(obniz.connectionState); console.log("connecting..."); obniz.onconnect = async function () { console.log(obniz.connectionState); obniz.switch.onchange = function (state) { switch (state) { case "push": console.log("push"); sceneNum = 0; break; case "right": console.log("right"); sceneNum += 1; sceneNum = sceneNum > 2 ? 0 : sceneNum; break; case "left": console.log("left"); sceneNum -= 1; sceneNum = sceneNum < 0 ? 2 : sceneNum; break; } sendWebSocket(message[sceneNum]); }; }; function sendWebSocket(message) { console.log(message); socket.send(JSON.stringify(message)); } </script> </body> </html> ``` ソースコードの補足は、Node.js用のプログラムを書いた後の部分に記載します。 ### 【Node.js版】Node.js で実行するためのプログラム 以下のプログラムは Node.js を使って実行するものです。 プログラムを実行する準備として `npm install obniz` というコマンドで、obniz を利用できるようにしておいて、以下のプログラムを `node 【以下の内容を書いたファイル名】` で実行してください。 ```javascript:Node.js で実行するためのプログラム const WebSocket = require("ws"); const Obniz = require("obniz"); const ws = new WebSocket("ws://localhost:4445"); const obniz = new Obniz("【自分の obniz ID】"); let sceneNum = 0; const message = [ { "request-type": "SetCurrentScene", "message-id": 【任意のID】, "scene-name": 【OBSのシーンの名称(1つ目)】, }, { "request-type": "SetCurrentScene", "message-id": 【任意のID】, "scene-name": 【OBSのシーンの名称(2つ目)】, }, { "request-type": "SetCurrentScene", "message-id": 【任意のID】, "scene-name": 【OBSのシーンの名称(3つ目)】, }, ]; ws.on("open", function open() { console.log("open"); }); console.log(obniz.connectionState); console.log("connecting..."); obniz.onconnect = async function () { console.log(obniz.connectionState); obniz.switch.onchange = function (state) { switch (state) { case "push": console.log("push"); sceneNum = 0; break; case "right": console.log("right"); sceneNum += 1; sceneNum = sceneNum > 2 ? 0 : sceneNum; break; case "left": console.log("left"); sceneNum -= 1; sceneNum = sceneNum < 0 ? 2 : sceneNum; break; } sendWebSocket(message[sceneNum]); }; }; function sendWebSocket(message) { console.log(message); ws.send(JSON.stringify(message)); } ``` ソースコードの補足は、この後に書いていきます。 ### 2種類のソースコードの補足 ここから、ブラウザ版・Node.js版のそれぞれのソースコードに関する補足を記載します。 #### obniz ID の指定 obniz ID を指定する部分について、ブラウザ版では `new Obniz("OBNIZ_ID_HERE");` と書いているため、HTMLファイルをブラウザで開いた時に obniz ID を入力するためのポップアップが表示されます。もちろん、 `"OBNIZ_ID_HERE"` の部分は、直接ご自身の obniz ID を書き込んでいただいても構いません。 Node.js版については `new Obniz("【自分の obniz ID】");` という部分がありますので、ご自身の obniz ID を記載してご利用ください。 #### WebSocket の接続先の指定 WebSocket の接続先について、ブラウザ版も Node.js版も `new WebSocket("ws://localhost:4445");` という形で指定しています。 今回、OBS が動作している PC上でプログラムを動かしているため、接続先を `localhost` で指定できています。また、上で出てきた OBS上での設定(Websocket サーバー設定)でポート番号は 4445 としていたので、ここでも同じポート番号を指定しています。 #### シーンの切り替えを指示する JSON WebSocket を使って OBS のシーン切り替えを行う際に、OBS へはシーンの名称等を含んだ JSON を送ります。ソースコードの中では以下のように書いている部分です。 ```javascript:ソースコードの記載例 const message = [ { "request-type": "SetCurrentScene", "message-id": 【任意のID】, "scene-name": 【OBSのシーンの名称(1つ目)】, }, { "request-type": "SetCurrentScene", "message-id": 【任意のID】, "scene-name": 【OBSのシーンの名称(2つ目)】, }, { "request-type": "SetCurrentScene", "message-id": 【任意のID】, "scene-name": 【OBSのシーンの名称(3つ目)】, }, ]; ``` 自分が実際に使ったものは、以下のような内容になります。 ```javascript:シーンを指定をするためのJSON const message = [ { "request-type": "SetCurrentScene", "message-id": "id001", "scene-name": "休憩中の表示", }, { "request-type": "SetCurrentScene", "message-id": "id002", "scene-name": "内蔵カメラの映像", }, { "request-type": "SetCurrentScene", "message-id": "id003", "scene-name": "カメラと画像", }, ]; ``` #### 動作中の出力 ブラウザ版も Node.js版も、それぞれ動作中の状態などをコンソールに出力しています。 ブラウザ版のほうの出力を確認する際には、開発者ツールのコンソールを開いてご確認ください。 #### obniz での操作とシーンの対応付け 今回、自分が動画をのせていた例では、以下の 3つのシーンを切り替えていました。 1. 休憩中の表示 2. 内蔵カメラの映像 3. カメラと画像 これらの切り替えと、obniz Board のスイッチ操作との関係ですが、以下のようになっています。ソースコード内でいうと、switch文を書いている部分がが処理の該当箇所です。 - スイッチを押す【push】 ⇒ 1つ目の「休憩中の表示」に切り替わる。 - スイッチを右に操作【right】 ⇒ 1つ後のシーンに切り替える。3つ目のシーンで操作をした場合は1つ目のシーンに切り替え。 - スイッチを左に操作【left】 ⇒ 1つ前のシーンに切り替える。1つ目のシーンで操作をした場合は3つ目のシーンに切り替え。 ## 今回の内容を動かしてみる ここまで準備ができれば、あとは冒頭に掲載していた動画のように、obniz のスイッチを操作してシーンの切り替えを実行するだけです! # おわりに 今回、obniz Board さえ準備できれば、PC で動いている OBS のシーン切り替えを外部から実行できる仕組みを実現しました。 まだコロナ禍が続く今、オンラインでのイベント配信やカメラ映像の提示をする機会が出てくると思います。そのような機会に、ちょっとシーン切り替えを便利にしてくれる今回のシーンスイッチャーを是非、ご利用ください!