Help us understand the problem. What is going on with this article?

OBS をスマホや M5GO(M5Stack)から遠隔制御 〜 MQTT や obs-websocket を利用 〜

はじめに

この記事は、ライブ配信などで使われる OBS Studio(以下、OBS と記載) を遠隔制御してみたという内容です。

まずは、その仕組みを実際に動作させている様子をご覧ください。


この動画の内容について補足すると、PC上で OBS が動いており、その OBS では以下の 3つのシーンが設定されています。
  1. 「休憩中」という文字を表示するシーン
  2. PC のカメラ映像を画面いっぱいに表示するシーン
  3. スライドを画面いっぱいに表示しつつ PC のカメラ映像も同時に表示しているシーン

上記の 3つのシーンの切り替え操作を、スマホや M5GO(M5Stack)といた別デバイスから制御しています。全体の構成は以下のとおりです。
全体の構成図.jpg

以下で、その仕組みの詳細について書いていきます。

利用している仕組み

ここでは、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-websocket_-_Remote-control_OBS_Studio_from_WebSockets_OBS_Forums.jpg
このプラグインを 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-websocket_Client.jpg
どうやら、ブラウザ上で動作するクライアントが、以下のリンクから簡単に試せるようです。
●OBS Tablet Remote
 http://t2t2.github.io/obs-tablet-remote/
OBS_Tablet_Remote.jpg

obs-websocket-js

上記の obs-websocket のプロトコルに合わせた通信部分の処理を書いてやれば、外部プログラム・アプリからの制御はできるようなのですが、まずは手軽に試せればと思い obs-websocket-js を使いました。

これは、obs-websocket の GitHub のページ 内(以下の画像の部分)で紹介されていたもので、obs-websocket の通信部分をより簡単に書けるようにしてくれるもののようでした。
obs-websocket_APIs.jpg
様々な言語向けのものが(様々な方によって)準備されているようですが、自分はこの画像内のリストで一番上に書かれた「Javascript (browser & nodejs): obs-websocket-js by Brendan Hagan」を使いました(選定に関しては、比較評価をして選択したのではなく、単に自分が Node.js・JavaScript を使い慣れているという理由で選択)。

obs-websocket-js のページには以下のサンプルが書かれており、これを参考にすると「認証+接続の処理」や「設定したシーンの一覧の取得」・「シーンの切り替えの指定」を用いる処理はすぐに実装できそうです。
obs-websocket-js_Sample.jpg
実際に、このサンプルの一部を自分の 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.fx(GUIベースの MQTTクライアントアプリ)

これは、利用した仕組みではなく、開発の途中で用いたアプリの話になるのですが、便利に使えるものなので紹介します。

冒頭で紹介した今回の構成で、MQTT のメッセージを受信側の PC上の処理を実装した時点で、MQTT の処理部分を軽くテストするために MQTT.fx というアプリを使いました(※ このアプリが冒頭の構成図の左にある、2つのデバイスの役割を代替する形)。
MQTTfx.jpg
このアプリは Javaベースで作られた MQTTクライアントで、 MQTTブローカーやトピック・メッセージの設定などを GUI上で行うことができ、MQTT のメッセージ送受信(Publish/Subscribe)の操作・受信内容の確認等も同じく GUI上で行えて便利です。
マルチプラットフォーム対応であるため、普段は Mac をメインで使いつつ Windows も併用している自分にとって、どちらの環境でも使えるのもありがたい点です。

UIFlow

冒頭の動画の前半で使っていたボタン付のデバイス M5GO(M5Stack) のプログラムは、M5Stack用のビジュアルプログラミング環境である「UIFlow」を使いました(※ 以前、UIFlow を使って MQTT を用いるプログラムを作成したことがあったため)。
UIFlow は、以下の画像にあるようなブロック型のビジュアルプログラミングでプログラムを作成できます。
UIFlow.jpg
デバイスに内蔵された画面・ボタン等などの処理や、外付けできるセンサー等の専用部品(ユニット)に関する処理なども使えますが、さらに HTTPリクエストや MQTT といった、IoT に役立つ処理もビジュアルプログラミングで作成することができます。

利用するためには、デバイスでのセットアップやブラウザ上(UIFlow上)での端末に紐付いた API Key の指定などが必要ですが、今回の記事では割愛します。詳細は、公式ドキュメントや Web上の記事などをご覧ください。

obs-websocket(プラグイン)を使った事例

今回の仕組みを作る中で、この obs-websocket を使っている事例を軽く検索してみました。
ひとまず日本語に限定した検索結果にして、見つかった記事をいくつかざっと見てみました。

今回の記事に出てくる obs-websocket-js やシーンの切り替えの話以外に、M5Stack用のプログラム(C言語での実装)に obs-websocket との WebSocket での通信を実装した例や、Pythonライブラリを使った話、OBS上で YouTubeライブチャット欄を表示する設定(URL指定)を自動で更新する話などがありました。

これらを見ていて、シーン切り替え以外のことをやっている事例が混じっていて、様々な OBS の操作や設定変更を外部から制御する話を、もっと調べたり試してみたくなりました。

プログラム

ここでは、以下の図の赤矢印で示した 2箇所のプログラムについて記載します。
構成図で説明する部分.jpg
スマホの部分はシンプルな内容でもあるため、今回は割愛します。
おおまかには、HTML で 3つのボタンを表示させるようにし、JavaScript でそれらのボタンがクリックされた時に 押されたボタンによって異なる MQTT のメッセージが送信されるように実装しています(※ 他に MQTT関連の処理で、MQTT.js を読み込んで MQTTブローカーとやりとりするための設定を行っています)。

PC上の Node.js のプログラム

今回の切り替え操作の対象となる 3つのシーンは、OBS上で以下のように設定しており、これらを Node.js のプログラムから指定して切り替えることになります。
OBS_シーン.jpg

ここで記載するプログラムでは、2つのパッケージ(obs-websocket-js・mqtt)を利用します。
そのために、npmコマンドで obs-websocket-jsmqtt の 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種類)

UIFlowのプログラム.jpg

プログラムを 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

【追記2】 M5Stack Core2 に対応させてみました

M5Stack Core2 のタッチスクリーンを利用した仕組みも試してみました。
処理は UIFlow で実装しています(ファームウェアは、実装時点でベータ版の「Beta2-core2」でした)。

また、OBS と WebSocket で通信する部分は、Node.js から Node-RED に置きかえてみました。
以下が、UIFlow と Node-RED で実装したプログラムです。

youtoy
プライベートでの活動で、ビジュアルプログラミング・IoT・ロボットトイを扱う技術コミュニティを単独・共同で主催したり、登壇をしたりしています。Qiitaの記事で書いていることは、このプライベートでの活動に関することです。また、普段は通信会社の研究所で働いていて、ガジェットが大好きです。
http://yo-to.hatenablog.com/
kddi
KDDIは、通信を中心に周辺ビジネスを拡大する「通信とライフデザインの融合」をより一層推進し、国内はもとよりグローバルにおいても、5G/IoT時代における新たな価値創造を実現し、お客さまの期待を超える新たな体験価値の提供を追求してまいります。
http://www.kddi.com
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした