Go言語でElgato StreamDeckのプラグインを作る
アーキテクチャ説明
クリエイター・配信者御用達ツールのElgato StreamDeckのプラグインをGo言語(バックエンド)とHTML5/CSS3/JS で作成します。
StreamDeckプラグインのアーキテクチャ
StreamDeckのプラグインのアーキテクチャとしては、キーが押された際の外部へのリクエスト送信や、StreamDeck本体に対して直接働きかけるバックエンド部分と、ユーザーが設定画面を開いた時のみ作成されるPropertyInspector(フロントエンドに該当)が存在します。
今回はPropertyInspectorは簡易的に済ませて、バックエンドの開発に注力しますが、機会があればPIの詳細な実装やWebAssemblyを使ったより複雑なシステムや、新規ウィンドウから設定画面を開く方法なども纏めてみようと思います。
今回は指定したメソッドでURLにアクセスし、取得した結果によって成功/警告表示をするだけのシンプルなアプリケーションを開発します。
成果物: TODO
アーキテクチャ概要
アーキテクチャとしては、バックエンドのアプリケーションとStreamDeckアプリがWebSocketで相互に接続し、フロントエンド(PropertyInspector/PIと呼称)はStreamDeckソフトウェアを経由してバックエンドと情報をやり取りする形になります。
用語集
- StreamDeck: Elgato社が販売する配信者向けPCデバイスのこと。15ボタンのモデルやXL、Mini、Plusなど全てを含みます。
- PropertyInspector: SDアプリ上でボタンをクリックすると出てくる部分。HTML5/CSS3/JSで動きますが、便宜上「フロントエンド」ではなく正式名称である"PropertyInspector"か"PI"と呼称します。
-
Context: 一般的にはGo言語の
context.Context
インターフェイスを表しますが、今回はStreamDeck上で扱われる仮想ボタンを指します。物理的なボタンではなく、ユーザーが設定したボタンの情報をContextと呼ばれる文字列で扱います。ボタンが移動されてもContextは正しく残ります。 - Action: ボタンに設定できる動作のこと。
サポート言語とSDK
公式にはJavaScript、C++、C#、Objective-Cの対応が謳われていますが、中身としてはmanifest.json中で指定したバイナリを所定の引数(後述)で起動しWebSocket通信を行なっているだけなので、外部に依存しないバイナリを生成できる言語であればGoに限らずRustやnimなどでも可能です。
非公式SDKとライブラリ
いくつか非公式のSDKもOSSで存在します:
- Go (本記事で使用): github.com/FlowingSPDG/streamdeck
- Rust: github.com/mdonoughe/streamdeck-rs
- C#: github.com/FritzAndFriends/StreamDeckToolkit
- C#(関連ツール): github.com/BarRaider/streamdeck-tools
注意: GitHub上ではネイティブのStreamDeckプラグインではなく、StreamDeck本体をUSB経由で直接コントロールするOSSも一部存在します。ですが、今回はそのような形態やbitfocus/companionなどは使用せず、StreamDeckネイティブプラグインとして開発を行います。
PropertyInspector(設定画面)について
PI上では、外部から"connectElgatoStreamDeckSocket"関数を叩くことで起動・WebSocketへ接続するアプローチとなっており、関数名の変化や最適化が行われると支障が出る為、Vue、Reactなどのフレームワークは使用せず、代わりにBarRaider氏が公開しているEasyPIを使用します。
Elgato公式からもPI用のjsが公開されていますが、利便性の面から今回は使用しません。
開発
事前準備
環境設定
事前の環境設定として、以下のセットアップを行なってください:
- 各種IDEのセットアップ
- Go言語のインストール(Go 1.18以降が必要)
- バックエンドの処理でGenericsを使用する為、Go1.18以降が必要となります
- StreamDeckソフトウェアのインストール
使用ライブラリ
メインライブラリとして github.com/FlowingSPDG/streamdeck を使用します。
[github.com/samwho/streamdeck](https://github.com/samwho/streamdeck] をフォークし、最新機能に対応したバージョンです。
バックエンドのWebsocket通信に必要な処理を請け負ってくれます。
プラグインの実装
基本的な動作確認
StreamDeckソフトウェアにプラグインが読み込まれると、バックエンドのバイナリが起動しWebSocket通信を開始します。
正常に起動しているか確認するため、ログファイルを開いてみます:
-
Mac:
~/Library/Logs/ElgatoStreamDeck/
-
Windows:
%appdata%\Elgato\StreamDeck\logs\
StreamDeck上にボタンを配置すると、設定したWillAppearHandler
が起動します。その状態でボタンを押すとKeyDownHandlerが起動していることがわかります。
PropertyInspectorのデバッグ設定
PIはユーザーがボタンをクリックしてPIを開いた時のみHTMLの描画・WebSocketの接続が行われます。
PropertyInspectorの出力を確認するため、Chrome Dev Toolsで確認できるように設定を変更します:
Mac の場合
defaults write com.elgato.StreamDeck html_remote_debugging_enabled -bool YES
Windows の場合
レジストリキー html_remote_debugging_enabled
(DWORD)を"1"に設定:
HKEY_CURRENT_USER\Software\Elgato Systems GmbH\StreamDeck
その後、StreamDeckアプリを再起動し、http://localhost:23654/
にアクセスするとPropertyInspectorがリストで表示されます。
イベントの種類と実装
主要イベントの説明
WillAppear
ボタンが出現したときに発行されます。
WillDisappear
ボタンが消える際に発行されるイベント。今回は使用しません。
KeyDown
キーが押し込まれた際に発行されるイベント。設定情報も一緒についてくるので、このために内部でPIの設定を保持する必要はありません。今回は「ボタンを押下すると特定の設定でHTTPのリクエストを出す」というプラグインの為、このイベントをきっかけでリクエストの実行を行います。
DidReceiveSettings
PIから設定が保存された時に発行されます。今回はバックエンド側に情報を保持する必要が無いため、使用しません。
StreamDeckアプリ側でも設定情報は保持されますが、PI上で設定を保存した際にバリデーションを行い上書きすることが可能になります。
設定データの管理
StreamDeckのイベント以外でボタンに対して操作を行う場合:
基本的にKeyDownなど主要なイベントのpayloadに設定が含まれているため、バックエンド側で設定を保持する必要はありません。
しかし、CPU UsageやStreamDeck-vMixプラグインのように外部のイベントや恒常的にContextに対して変更を実施したい場合は、メモリ中に保持する必要があります。
その場合、event.Context
をキーとして設定を保持するmapを作成し、WillAppearやDidReceiveSettingsを受けてvalueを更新する形にすると良いでしょう。
PropertyInspector(PI)の開発
技術的な概要
Property Inspector(設定画面)の開発を行います。
技術的には設定画面が開かれたときにQtを使い指定したHTMLを描画し、グローバルに定義されたwindow.connectElgatoStreamDeckSocket
を起動しWebSocket経由で通信を行うというフローのようです。
前述した通り、今回はReact、Vueなどのフレームワークは使用せず、様々なプラグインの開発を行なっているBarRaider氏が公開しているEasyPIというjsを使用します。
実装詳細
各種actionごとにHTMLファイルを指定できるため、今回は"http_client.html"を作成し使用します。
設定項目としては、「対象のURL」「使用するメソッド」の2種類のため、まずバックエンドに対応した構造体を追加します。
設定とパッケージ化
manifest.jsonの設定
プラグインの設定はmanifest.json
で行います。詳細は公式ドキュメントを参照してください:
https://developer.elgato.com/documentation/stream-deck/sdk/manifest/
Distribution Toolでパッケージ化
最終的なパッケージ化には公式のDistribution Toolを使用します:
https://developer.elgato.com/documentation/stream-deck/sdk/packaging/
参考リンク
- メインライブラリ: github.com/FlowingSPDG/streamdeck
- サンプル集: examples
- 実装例: streamdeck-vmix-plugin
- EasyPI: github.com/BarRaider/streamdeck-easypi
- 公式開発者ドキュメント: developer.elgato.com
この記事はgithub.com/FlowingSPDG/streamdeckライブラリを使用したStreamDeckプラグイン開発の入門ガイドです。より詳細な実装例については、リポジトリのexamplesディレクトリやstreamdeck-vmix-pluginなどの実際のプラグインを参考にしてください。
Discussion