
Muse Secure VMに自作サーバーを置いて、M5Stack StopWatchから接続できるか試した
はじめに
前回は、Muse Gadget SDK標準のリアルタイム音声通話をM5Stack StopWatchで試しました。Muse Secure VM(以下、VM)への接続は成功したものの、通話開始のPOST /voice/realtimeがHTTP 404となり、音声会話には進めませんでした。
そこで、Muse Secure VMに自作の中継サーバーを置き、OpenAI Realtime APIへ接続する方法を試しました。VMへ接続できるなら、その中で動くサーバーにも音声を渡せるのでは、と考えたためです。
試した構成
StopWatchが録音・再生を担当し、OpenAIへの接続や会話の制御をVM側へ移す構成です。モデル・声・指示文の変更を、端末のファームウェアを書き換えずに試すことを狙いました。

ペアリングとVM接続に使う3種類のトークンは、図の1から4の順に受け渡します。接続確認には、認証情報を保存済みのStopWatchを使いました。
自作サーバーはVM内の127.0.0.1:8787で起動しました。8787は今回選んだ待ち受けポートで、Muse指定の番号ではありません。既存のMuseデーモンや公式ルートは変更していません。
| 用途 | パス |
|---|---|
| Muse公式の音声通話 | POST /voice/realtime |
| 自作サーバーの音声中継 | WebSocket /realtime |
| 自作サーバーのecho確認 | GET /probe/echo?nonce=... |
VM内にサーバーを用意する
echo確認とOpenAI音声中継を、1つのサーバーに実装しました。
MuseへリポジトリのURLを渡してセットアップを依頼しました。OpenAIのAPIキーは専用入力画面からMuseの認証情報ストアへ登録し、実キーをチャットや中継の.envに保存しない方法を指定しました。

OpenAI APIキーの発行とMuseへの登録
OpenAI Platformで検証用のAPIキーを発行しました。有効期限は1日にしています。

今回はPermissionsを「All」のまま発行しましたが、継続して使うキーは「Restricted」で必要な権限に絞るのが望ましいです。
Museが提示したOpenAIコネクターの「連携する」から、認証情報ストアへ登録しました。

中継は代替トークンを使い、外部通信時にSentinelが実キーへ置き換えます。
検証結果
VM内のechoとOpenAI接続は成功
VM内では、次のcurlでechoも確認しました。
curl --fail 'http://127.0.0.1:8787/probe/echo?nonce=0123456789abcdef0123456789abcdef'
HTTP 200と、送信したものと同じnonceが返りました。
Museからは、この方式でPython SDKのWebSocket接続と音声往復に成功したとの報告がありました。ここで確認できたのは、VM内の中継からOpenAIまでの通信です。
StopWatchから接続すると403になる
Gadget SDKに、黄ボタンでecho確認を実行する検証モードを追加しました。CONFIG_MUSE_VM_PROBE=yでビルド・書き込みし、ペアリング済みの端末から既存の認証済みVM接続を使ってリクエストを送ります。
端末の画面には、次の結果が表示されました。VM内でサーバーが起動していることを確認しても、結果は変わりませんでした。

中継まで届いているかをログで切り分ける
403だけでは、どこで拒否されたか分かりません。Museに中継サーバーの到達ログを追加してもらい、VM内のcurlが記録されることを確認してから、StopWatchの黄ボタンをもう一度押しました。このログ追加はVM内だけの診断用変更です。

Museから共有されたログの確認結果では、記録されたのは対照アクセスだけでした。自作echoも403を返す実装ではないため、今回のリクエストは中継へ届く前に拒否されたと判断しました。
VMへの接続と、自作サーバーへの転送は別だった
SDKの送信処理では、アプリリクエストをNoise上のDaemonサービス宛てに送ります。
/probe/echoを指定しても、VM内の127.0.0.1:8787へ接続する指示にはなりません。
Museに転送方法も調べてもらいましたが、CLI・VM内の設定ファイル・ドキュメントから、独自サーバーへ転送する設定手段は見つかりませんでした。403を返した内部のルールやログは参照できていないため、「未許可のルートだから拒否された」という詳細までは確認できていません。
今回分かったのは、MuseのVM認証を通過しても、任意のVM内プロセスにアクセスできるわけではない、という点です。サーバーの起動やポート番号の変更だけでは、この接続経路は作れませんでした。
常駐化にも制約があった
サーバーの削除を依頼した際、既にプロセスが消えていたとの報告があり、常駐化できなかった理由をMuseに確認しました。

接続経路とは別に、サーバーを動かし続ける点でも問題がありました。Museに常駐化を依頼しましたが、systemctl --userはFailed to connect to busとなり、ユーザーサービスを登録できませんでした。代わりにnohupで起動したプロセスも翌朝には停止していました。
MuseからはVMの入れ替えでプロセスが失われるとの説明がありましたが、今回の停止原因は未特定です。継続稼働や自動復旧の方法も確認できておらず、常時利用する中継サーバーの配置先としては、この点も課題になりました。
さいごに
今回は、Muse Secure VMに自作APIを置き、StopWatchから音声を渡して会話する構成を試しました。VMへの接続とVM内でのAPI実行はできたものの、その間をつなぐ転送経路を用意できず、音声会話までは実現できませんでした。
このような用途では、Muse Secure VMに中継を任せるのではなく、端末からOpenAIへ直接接続する実装も選択肢になります。その場合、長期有効なOpenAI APIキーを端末に持たせるなら、端末からキーを取り出されるリスクも考える必要があります。
もちろん、自分で中継APIと端末向けのトークン発行・認証を用意し、OpenAIのキーをそのサーバー側で管理する方法もあります。ただ、その分サーバーの運用も必要です。今回はそこをMuse Secure VMに任せられないかと考えましたが、調べた範囲では難しい、という結果になりました。





