はじめに
この記事は、ライブ配信などで使われる OBS Studio(以下、OBS と記載) を遠隔制御してみたという内容です。
まずは、その仕組みを実際に動作させている様子をご覧ください。
この動画の内容について補足すると、**PC上で OBS が動いており、その OBS では以下の 3つのシーンが設定されています。**MQTTを利用し、PC上で動くOBSのシーンの切り替え操作を、他デバイスから制御してみた!
— you (@youtoy) August 20, 2020
UIFlowでプログラムを書いたM5GOと、JavaScriptで処理を書いたWebサイトを表示したスマホの、2つのデバイスを操作し、3つのシーンを切り替えてみました。 pic.twitter.com/fg3QAauCB6
- 「休憩中」という文字を表示するシーン
- PC のカメラ映像を画面いっぱいに表示するシーン
- スライドを画面いっぱいに表示しつつ PC のカメラ映像も同時に表示しているシーン
**上記の 3つのシーンの切り替え操作を、スマホや M5GO(M5Stack)といた別デバイスから制御しています。**全体の構成は以下のとおりです。
以下で、その仕組みの詳細について書いていきます。
利用している仕組み
ここでは、OBS を遠隔制御するために用いた以下のプラグインやパッケージ・サービスについて記載します。
- obs-websocket(プラグイン)
- obs-websocket-js
- MQTT.js
- shiftr(MQTTブローカー)
- UIFlow
また、今回用いた仕組みの話ではないのですが、MQTT の開発に便利に使えるアプリ(MQTT.fx)についても少し記載しています。
今回の仕組みで用いたプログラムの詳細に関しては、この後の「プログラム」の項目でまとめて記載します。
OBS関連
obs-websocket(プラグイン)
今回、OBS を外部から制御する一番のポイントは obs-websocket というプラグインです。
●obs-websocket - Remote-control OBS Studio from WebSockets | OBS Forums
https://obsproject.com/forum/resources/obs-websocket-remote-control-obs-studio-from-websockets.466/
●Palakis/obs-websocket: Remote-control OBS Studio through WebSockets
https://github.com/Palakis/obs-websocket
このプラグインを OBS に追加してやることで、外部のプログラムやアプリから OBS を制御することができるようになります(自分が見つけたきっかけは、MQTT や WebSocket を使ったライブラリ等を、GitHub上でキーワード検索を行ったことでした)。
プラグインの名称にあるとおり、OBS の制御には WebSocket を用いる形です。
**以下の提供元のページに書かれたプロトコルに沿って WebSocket を用いた通信を行うことで、**冒頭に紹介したシーンの切り替えだけでなく、様々な OBS の操作を外部のプログラムやアプリから行うことができます。
●obs-websocket/protocol.md at 4.x-current · Palakis/obs-websocket
https://github.com/Palakis/obs-websocket/blob/4.x-current/docs/generated/protocol.md
WebSocket で通信させることができれば、OBS が動いている PC内の別プログラム・アプリからでも制御できますし、PC の外の別デバイスから制御することも可能です。
obs-websocket のセットアップ
このプラグインを使うための手順はシンプルで、プラグインのインストールを行ってしまえば OBS を起動した際に WebSocketを利用するためのサーバが連動して立ち上がります。
なお、ポート番号やパスワード認証といったプラグインに関わる設定を変更することもでき、具体的には OBS を起動後のメニューの中から「ツール ⇒ Web Server Settings」とたどった先で変更が可能です(自分は、PC内の別のプログラムがこのプラグインのデフォルト設定のポート番号を利用していたため、競合しないようにデフォルトのポート番号ではないものに変更し、その話とは別になりますが、認証の設定の有効化も行いました)。
obs-websocket のクライアントのサンプル
obs-websocket のページに、以下のような記載がありました。
どうやら、ブラウザ上で動作するクライアントが、以下のリンクから簡単に試せるようです。
●OBS Tablet Remote
http://t2t2.github.io/obs-tablet-remote/
obs-websocket-js
上記の obs-websocket のプロトコルに合わせた通信部分の処理を書いてやれば、外部プログラム・アプリからの制御はできるようなのですが、まずは手軽に試せればと思い obs-websocket-js を使いました。
これは、obs-websocket の GitHub のページ 内(以下の画像の部分)で紹介されていたもので、obs-websocket の通信部分をより簡単に書けるようにしてくれるもののようでした。
様々な言語向けのものが(様々な方によって)準備されているようですが、自分はこの画像内のリストで一番上に書かれた「Javascript (browser & nodejs): obs-websocket-js by Brendan Hagan」を使いました(選定に関しては、比較評価をして選択したのではなく、単に自分が Node.js・JavaScript を使い慣れているという理由で選択)。
obs-websocket-js のページには以下のサンプルが書かれており、これを参考にすると「認証+接続の処理」や「設定したシーンの一覧の取得」・「シーンの切り替えの指定」を用いる処理はすぐに実装できそうです。
実際に、このサンプルの一部を自分の obs-websocket のプラグイン設定に合わせた形で書きかえ(※ OBS側で自分がデフォルトから変更したポート番号と、設定した認証用のパスワードの部分を書きかえ)、プログラムを実行してみて OBS の外部からシーンの切り替え等が行えることを確認できました。
この後、keypress を組み合わせて、PC の特定のキーを押したら OBS のシーンが押下したキーと対応づけられたシーンに切り替わる、というものをお試しで実装したのですが、今回の本題と少しズレる部分であるため詳細については省略します。
MQTT関連
obs-websocketプラグインと obs-websocket-js(または、JavaScript以外の言語向けのもの)を使うことで、obs-websocket のプロトコルの詳細まで踏み込むことなく OBS を制御をすることが可能になりました。
ここまで試せたところで、自分がこの OBSプラグインを見つけた際にやりたいと思った「OBS の操作を PC の外の別デバイスから行う」という内容に着手することにしました。
やり方の 1つとして、PC上で動かした Node.js のプログラム(obs-websocket-js を用いたプログラム)に Webサーバの処理・Webページ用のファイルなどを追加して操作用の Webページを用意し、そこへスマホでアクセスして操作する方法がありそうです。
ただ、スマホ以外のマイコンモジュール等とも連携させたいと思い、さらに PC側の実装はそれらの端末用に別で用意するのではなく共通化できれば、と思いました。そこで、マイコンモジュール等を含めたデバイス間連携で最近よく使っている MQTT を組み合わせてみることにしました。
MQTT.js と shiftr(MQTTブローカー)
「はじめに」の項目で掲載した図の構成のとおり、PC と他デバイスの間の通信に MQTT を用いることとし、PC上の Node.js のプログラムで MQTT.js を用いた処理を追加しました(※ 構成図のスマホの部分の JavaScript実装でも MQTT.js を利用しています)。
MQTT の通信を仲介する MQTTブローカー に関しては、自分が今回使う用途はローカルネットワーク内での通信が行えれば十分であったため、OBS が動いている PC上で動かす形でも良かったのですが(※ 例えば Mosquittoを使う等)、過去に作成したプログラムで外部の MQTTブローカーを提供するサービスの 1つである「shiftr」を使うものが手持ちであったので、shiftr を使う構成にしました。
ここでは、MQTT・MQTT.js・shiftr の詳細な説明は割愛しますが、以下に参考となりそうな記事のリンクを記載します。
- MQTT.js と shiftr を組み合わせて使うサンプル
- MQTT.js と shiftr 等を組み合わせて使うサンプルや MQTT の解説など
【余談】 MQTT.fx(GUIベースの MQTTクライアントアプリ)
これは、利用した仕組みではなく、開発の途中で用いたアプリの話になるのですが、便利に使えるものなので紹介します。
冒頭で紹介した今回の構成で、MQTT のメッセージを受信側の PC上の処理を実装した時点で、MQTT の処理部分を軽くテストするために MQTT.fx というアプリを使いました(※ このアプリが冒頭の構成図の左にある、2つのデバイスの役割を代替する形)。
このアプリは Javaベースで作られた MQTTクライアントで、 MQTTブローカーやトピック・メッセージの設定などを GUI上で行うことができ、MQTT のメッセージ送受信(Publish/Subscribe)の操作・受信内容の確認等も同じく GUI上で行えて便利です。
マルチプラットフォーム対応であるため、普段は Mac をメインで使いつつ Windows も併用している自分にとって、どちらの環境でも使えるのもありがたい点です。
UIFlow
冒頭の動画の前半で使っていたボタン付のデバイス M5GO(M5Stack) のプログラムは、M5Stack用のビジュアルプログラミング環境である「UIFlow」を使いました(※ 以前、UIFlow を使って MQTT を用いるプログラムを作成したことがあったため)。
UIFlow は、以下の画像にあるようなブロック型のビジュアルプログラミングでプログラムを作成できます。
デバイスに内蔵された画面・ボタン等などの処理や、外付けできるセンサー等の専用部品(ユニット)に関する処理なども使えますが、さらに HTTPリクエストや MQTT といった、IoT に役立つ処理もビジュアルプログラミングで作成することができます。
利用するためには、デバイスでのセットアップやブラウザ上(UIFlow上)での端末に紐付いた API Key の指定などが必要ですが、今回の記事では割愛します。詳細は、公式ドキュメントや Web上の記事などをご覧ください。
obs-websocket(プラグイン)を使った事例
今回の仕組みを作る中で、この obs-websocket を使っている事例を軽く検索してみました。
ひとまず日本語に限定した検索結果にして、見つかった記事をいくつかざっと見てみました。
- node.jsからWebsockets経由でOBSを操作する|きりみんちゃんノート|note
- OBSのYouTubeライブチャット欄のURLを自動で更新する|きりみんちゃんノート|note
- OBSをM5Stackでコントロールする|Mori Naoyuki|note
- obs-websocket-pyの使い方ほか - Mokerの徒然日記2.0
- 動画配信ソフト「OBS」をPythonで操るぞ~ - KAYAC engineers' blog
今回の記事に出てくる obs-websocket-js やシーンの切り替えの話以外に、M5Stack用のプログラム(C言語での実装)に obs-websocket との WebSocket での通信を実装した例や、Pythonライブラリを使った話、OBS上で YouTubeライブチャット欄を表示する設定(URL指定)を自動で更新する話などがありました。
これらを見ていて、シーン切り替え以外のことをやっている事例が混じっていて、様々な OBS の操作や設定変更を外部から制御する話を、もっと調べたり試してみたくなりました。
プログラム
ここでは、以下の図の赤矢印で示した 2箇所のプログラムについて記載します。
スマホの部分はシンプルな内容でもあるため、今回は割愛します。
おおまかには、HTML で 3つのボタンを表示させるようにし、JavaScript でそれらのボタンがクリックされた時に 押されたボタンによって異なる MQTT のメッセージが送信されるように実装しています(※ 他に MQTT関連の処理で、MQTT.js を読み込んで MQTTブローカーとやりとりするための設定を行っています)。
PC上の Node.js のプログラム
今回の切り替え操作の対象となる 3つのシーンは、OBS上で以下のように設定しており、これらを Node.js のプログラムから指定して切り替えることになります。
ここで記載するプログラムでは、2つのパッケージ(obs-websocket-js・mqtt)を利用します。
そのために、npmコマンドで obs-websocket-js
と mqtt
の 2つのパッケージをインストールしてください。
npm i obs-websocket-js mqtt
プログラムの具体的な内容は、以下のとおりです。
プログラム中に 【 】 で囲まれた部分が複数ありますが、ご自身の環境に合わせて書きかえをしてください。
- 書きかえが必要な部分のリスト
- obs-websocket のポート番号
- obs-websocket のパスワード(※ 認証を有効にした場合に利用する)
- shiftr の ID
- shiftr の PASS
- MQTTクライアントのクライアントID
- MQTT のトピック
- MQTT でやりとりする文字列(※ 今回は 3つのシーンを用意したため、3種類)
const OBSWebSocket = require('obs-websocket-js');
const mqtt = require('mqtt');
const obs = new OBSWebSocket();
obs.connect({
// obs-websocket に関わる設定
address: '127.0.0.1:【ポート番号】', // 同じPC内で接続、ポート番号のデフォルトは「4444」
password: '【パスワード】' // 認証を有効にした場合に必要
}).then(() => {
console.log(`Success! We're connected & authenticated.`);
return obs.send('GetSceneList');
}).then(data => {
// 取得したシーンのリストを出力(サンプルそのまま)
console.log(`${data.scenes.length} Available Scenes!`);
data.scenes.forEach(scene => {
console.log(`${scene.name}`);
});
// OBSのシーン情報を取得できた後に、MQTT関連の設定を行う
const client = mqtt.connect('mqtt://【shiftrのID】:【shiftrのPASS】@broker.shiftr.io', {
clientId: '【MQTTのクライアントID(文字列を設定する)】'
});
client.on('connect', function(){
console.log('MQTT: client has connected!');
client.subscribe('【MQTTのトピックを設定する】');
});
client.on('message', function(topic, message) {
console.log('new message:', topic, message.toString());
// MQTT で受信したメッセージの内容によって切り替えるシーンの指定を変える
switch (message.toString()) {
case '【MQTTでやりとりする文字列1(シーン1つ目に対応)】':
obs.send('SetCurrentScene', {
'scene-name': data.scenes[0].name
});
break;
case '【MQTTでやりとりする文字列1(シーン2つ目に対応)】':
obs.send('SetCurrentScene', {
'scene-name': data.scenes[1].name
});
break;
case '【MQTTでやりとりする文字列1(シーン3つ目に対応)】':
obs.send('SetCurrentScene', {
'scene-name': data.scenes[2].name
});
break;
}
});
}).catch(err => {
console.log(err);
});
obs.on('SwitchScenes', data => {
console.log(`New Active Scene: ${data.sceneName}`);
});
// You must add this handler to avoid uncaught exceptions.
obs.on('error', err => {
console.error('socket error:', err);
});
今回、元のサンプルをできるだけ流用する形にしたため、3つのシーンの名前を取得する処理の後にシーンの切り替え処理を実装し、そこで指定するシーンの名前を data.scenes[0].name
などという形で書いています。
この部分は、わざわざプログラムで OBS からシーン名を取得するのではなく、それら 3つの名前をプログラム上に直接書いて利用する形でも良いかもしれません。
なお、こちらのプログラムを動作させて使う際は、プラグイン(obs-websocket)をインストール済みの OBS を先に立ち上げておいてください。
UIFlow のプログラム
M5GO(M5Stack)用に作成したプログラムは以下の画像のとおりです。
画像中に 【 】 で囲まれた部分が複数ありますが、ご自身の環境に合わせて書きかえてください。
なお、説明の都合上、文字列を記載する箇所に日本語の文字を書いていますが、UIFlow で日本語の文字は利用できないため、半角英数字・半角記号のみを書くようにしてください。
書きかえが必要な部分は以下にまとめました。この中の「MQTT のトピック」と「MQTT でやりとりする文字列(※ 3種類)」は、Node.js のプログラムで指定したものと同じものにする必要があります。
- 書きかえが必要な部分のリスト
- MQTTクライアントのクライアントID
- shiftr の ID(※ 画像では見きれていますが、上から2つ目のブロックの右のほうの「ユーザー名」のところで指定できます)
- shiftr の PASS(※ 画像では見きれていますが、上から2つ目のブロックの右のほうの「パスワード」のところで指定できます)
- MQTT のトピック
- MQTT でやりとりする文字列(※ 今回は 3つのシーンを用意したため、3種類)
プログラムを M5GO(M5Stack)に書き込んだら、あとは OBS と Node.js のプログラムを動作させた状態で、M5GO(M5Stack)の3つのボタンを押すだけです。3つのボタンの何れかを押すと、OBS の表示が押したボタンに対応したシーンへと切り替わります。
おわりに
今回、OBS のプラグイン「obs-websocket」と MQTT などを組み合わせて、スマホや M5GO(M5Stack)から OBS を遠隔で制御するという内容を試しました。
今回試している制御内容は、自分が一番多く使いそうだったシーンの切り替え操作だけでしたが、本文中に書いたようにこのプラグインで制御可能な操作は他にも様々あるようです。OBS の利用を便利にしてくれそうな仕組みを他にも作れそうなので、シーン切り替え以外の制御などを引き続き調べて試してみようと思います。
【追記】 Node-RED からの遠隔制御もやってみました
OBS のシーンの切り替えを Node-RED から行うものも試してみました。
こちらは、Node-RED から OBS へ直接 WebSocket で JSON を送って遠隔制御をしています。
●Node-RED を使って OBS を遠隔操作してみた話(obs-websocket を利用)|豊田 陽介|note
https://note.com/youtoy/n/nf404040a91c0
Node-RED から WebSocket で JSON を送り、OBS のシーン切り替える動作をさせた様子を動画にしてみた! https://t.co/dBO6E7sGyV pic.twitter.com/magcQoUwpl
— you (@youtoy) September 19, 2020
【追記2】 M5Stack Core2 に対応させてみました
M5Stack Core2 のタッチスクリーンを利用した仕組みも試してみました。
処理は UIFlow で実装しています(ファームウェアは、実装時点でベータ版の「Beta2-core2」でした)。
#M5Stack_contest に作品を応募する作業で、撮り直した動画。#M5Stack_Core2 のタッチスクリーンを押して、OBS のシーンが切り替わる様子の動画ですが、そのタッチ操作をしている時のトークをイベント時の内容っぽいものにしてみました。#M5Stack https://t.co/MKQ5YpdjPV pic.twitter.com/lCv9vuL2h2
— you (@youtoy) September 22, 2020
また、OBS と WebSocket で通信する部分は、Node.js から Node-RED に置きかえてみました。
以下が、UIFlow と Node-RED で実装したプログラムです。
#M5Stack_contest 用に行っている作業、 #M5Stack_Core2 の画面上での表示周りの処理をがっつり足したり(実装は #UIFlow )、前の作品では Node.js が仲介役になってた部分を Node-RED に置きかえてみたりもしました。#M5Stack pic.twitter.com/mOktQkWFT1
— you (@youtoy) September 22, 2020
【追記3】 obs-websocket に直接 JSON を送る場合の話
obs-websocket のプロトコルに合わせて、WebSocket で JSON を送るパターンで、認証周りが少し面倒なので、そのあたりの仕様を調べてみて、以下にメモしました。
●OBS の obs-websocketプラグインの認証に関する仕様・試したことのメモ - Qiita
https://qiita.com/youtoy/items/8987f9d0fb8ab696766f