🐷

ElixirからWebSocketでOBSとやり取りするobs_websocket_exを作りました

2023/12/22に公開

録画・配信アプリケーションのOpen Broadcaster Software(OBS)は、WebSocketで外部から制御したり、OBS内のイベントを受け取ったりできます。しかし、ElixirからOBSを制御するライブラリは見当たらなかったので、obs_websocket_exというライブラリを作ってみました。

https://github.com/kentaro/obs_websocket_ex

本記事では、使い方を簡単に紹介します。

obs_websocket_exの使い方

基本的な使い方

もっとも基本的な使い方は、以下の通りです。このスクリプトでは、WebSocketサーバの設定は認証を有効にしない状態を前提としています。

ハンドラとなるモジュールを定義し、use ObsWebSocketした上で処理を書いていきます。

https://github.com/kentaro/obs_websocket_ex/blob/main/examples/basic.exs

実行すると、以下の通りのデバッグログと、ハンドラーに渡されたメッセージが表示されます。

$ mix run ./examples/basic.exs

22:48:42.912 [debug] Hello (authentication not required): %{"obsWebSocketVersion" => "5.3.4", "rpcVersion" => 1}
Received Message - Type: :text -- Message: %{"d" => %{"negotiatedRpcVersion" => 1}, "op" => 2}

WebSocketに接続すると、Hello (OpCode 0)というメッセージが送信されてくるので、Identify (OpCode 1)というメッセージを送り返してやる必要があります。そのへんを、obs_websocket_exが自動的にやってくれています。

認証を有効にする

OBSのWebSocketサーバの設定で認証を有効にした場合は、以下のように書きます。先ほどのコードとの違いは、以下の通りです。

  • ハンドラとなるモジュールのstart_link/2関数呼び出し時に、パスワードをわたす
  • ハンドラとなるモジュールに、オプションとしてわたされたパスワードを取得するためのpassword/0という関数を定義する

https://github.com/kentaro/obs_websocket_ex/blob/main/examples/authentication.exs

実行すると、以下の通りのデバッグログと、ハンドラーに渡されたメッセージが表示されます。

$ mix run ./examples/authentication.exs

22:55:51.013 [debug] Hello (authentication required): %{"authentication" => %{"challenge" => "jcja23BkFABk2l4nhzAPI/gSjGMiDqz5szLL6IZ2fiE=", "salt" => "GZVpXFCJANfNgEPs8H1P5PZIeZZGu+g0EqBikMcU3SA="}, "obsWebSocketVersion" => "5.3.4", "rpcVersion" => 1}
Received Message - Type: :text -- Message: %{"d" => %{"negotiatedRpcVersion" => 1}, "op" => 2}

さきほどと異なり、authenticationなどのフィールドが増えています。このデータを用いて、Creating an authentication stringの説明に従い、認証に用いる情報をIdentify (OpCode 1)というメッセージで返してやる必要があります。

リクエストを送信する

接続がうまくいったら、なにかしら操作してみたいですよね。ここでは、よく使うであろうテキストの表示をしてみます。

まずは、テキスト欄を追加します。以下の画像の通り、messageという名前のテキスト欄を追加しましょう。

実行するコードは以下の通りです。

https://github.com/kentaro/obs_websocket_ex/blob/main/examples/request.exs

実行すると、以下の通りのデバッグログと、ハンドラーに渡されたメッセージが表示されます。

$ mix run .\examples\request.exs

23:06:12.152 [debug] Hello (authentication required): %{"authentication" => %{"challenge" => "7XkY0E1apBsH10Rf1rrzM0lW9WZB4kDDps/SpsGCpds=", "salt" => "GZVpXFCJANfNgEPs8H1P5PZIeZZGu+g0EqBikMcU3SA="}, "obsWebSocketVersion" => "5.3.4", "rpcVersion" => 1}
Received Message - Type: :text -- Message: %{"d" => %{"negotiatedRpcVersion" => 1}, "op" => 2}
Received Message - Type: :text -- Message: %{"d" => %{"requestId" => "43d37820-a0d3-11ee-9093-2cf05de4c937", "requestStatus" => %{"code" => 100, "result" => true}, "requestType" => "SetInputSettings"}, "op" => 7}

そして、以下の画像の通りmessageという名前のテキスト欄にHello OBS!と表示されています。

このコードの肝は、以下のリクエストを送信している箇所です。SetInputSettingsという名前のリクエストで、先ほど追加したテキスト欄の名前を指定しつつテキストを設定しています。

conn |> ObsWebSocket.request(:SetInputSettings, %{
  inputName: "message",
  inputSettings: %{text: "Hello OBS!"}
})

その他の例

その他の有用な例として、たとえばプログラムから録画や配信の開始・終了を制御したいということがありそうです。StartRecord / StopRecordあるいはStartStreaming / StopStreamingというリクエストを送信することで、それらの操作を行うことができます。

おわりに

ElixirからWebSocketでOBSとやり取りするobs_websocket_exの簡単な使い方を紹介しました。ElixirからもOBSを簡単にやりとりできるようになったので、ぜひお試しください。

GitHubで編集を提案

Discussion