Stream Deckプラグイン「Volume Controller」をOSの音量ミキサーのWebScoket APIとして使う
Elgatoが提供しているStream DeckのVolume ControllerはOSやアプリの音量を操作できる公式プラグインです。
Windows 11の場合、設定 > システム > サウンド > 音量ミキサー
の画面を物理デバイスで操作できるようになり、私もとても重宝しています。
そんな中、勉強がてらプラグインのソースコード(minifyされている)を覗いていたんですが、どうやらElgatoAudioControlServerというプログラムがバックグラウンドで実行されていて、プラグインはそのプログラムとWebSocketで通信しているだけでした。
要するにOSの音量ミキサーのWebSocket APIが使える状態なわけです。
Volume Controllerでは実現できない細かい要望があったのですが、最近はこのAPIを利用して自分で開発したプラグインも併用しています。
WebScoket API (独自調べ)
接続先
ws://127.0.0.1:1844
グローバルメッセージ
すべてのクライアントに対して送信されるメッセージです。
OSやアプリの音量に関連する状態が変化した時に発生します。
WebSocketのaddEventListener
メソッドでmessage
イベントを監視しておきましょう。
フォーマット
{
"jsonrpc": "2.0", // 以下省略
"method": "ここに通信の種類を識別する文字列が入る",
"params": {
...
}
}
以降、抜粋して記載します
ボリューム変更
アプリのプロセスIDからアプリ名などを取得する方法は後ほど紹介します。
// 全体
{
"method": "currentSystemDefaultDeviceVolumeChanged",
"params": {
"volume": number // [0-1]
}
}
// アプリ
{
"method": "preferredSessionInstanceVolumeChanged",
"params": {
"processID": number,
"volume": number // [0-1]
}
}
ミュート変更
// 全体
{
"method": "currentSystemDefaultDeviceMuteChanged",
"params": {
"mute": true
}
}
// アプリ
{
"method": "preferredSessionInstanceMuteChanged",
"params": {
"mute": boolean,
"processID": number
}
}
アプリの追加・削除
アプリの起動・終了に伴って、アプリ一覧にアプリが追加・削除された時に発生します。
{
"method": "appInstanceAddRemove",
"params": {
"appAddedRemoved": "Added" | "Removed",
"processID": number
}
}
アクティビティ変更
アプリの音声出力の状態が変更された時に発生します。
- 2 (Active 音が鳴っている)
- 3 (InactiveShort 音が止まって短い時間が経過している)
- 4 (InactiveLong 音が止まって長い時間が経過している)
{
"method": "appInstanceActivityChanged",
"params": {
"activity": 2 | 3 | 4,
"processID": number
}
}
個別メッセージ
特定のフォーマットでデータを送信すると、そのクライアントにだけメッセージが返信されます。
クライアントから能動的にデータを取得したい場合に使用します。
送信フォーマット
WebSocketのsend
メソッドで送信する際のフォーマットです。
JSON.stringify()
で文字列にしてから渡しましょう。
{
"jsonrpc": "2.0", // 以下省略
"id": 任意の整数値, // 以下省略
"method": "ここに通信の種類を識別する文字列が入る",
"params": {
...
}
}
返信フォーマット
{
"id": 送信時に設定した任意の整数値, // 以下省略
"result:": {
...
}
}
どの送信に対応する返信かを識別するためにid
を設定しておきます。
文字列ではなく整数値なので注意してください。
ちなみに、Volume Controllerプラグインでは下記の方法でランダムに生成していました。
Math.floor(1e9 * Math.random())
執筆中