OBS連携機能(#162 / 本体側#181 / オーバーレイ#182

refs #162

概要

beatoraja に OBS 配信連携を追加(親 #162 / 本体側 #181 / オーバーレイ #182)。本体に localhost ローカル HTTP サーバを1本立て、/state.json(現在状態スナップショット)と ./obs のオーバーレイを配信。OBS ブラウザソース1つで、プレイ状況・リザルト・セッション統計・選曲履歴を表示する。obsEnabled=false 時は完全に無効で既存挙動にゼロ影響。

変更点

本体側 (#181)

  • 新規パッケージ bms.player.beatoraja.stream.obsObsHttpServer(localhost 固定・/state.json./obs 静的配信・パストラバーサル防止・仮想スレッド)、ObsStatevolatile な不変スナップショット+キャッシュ済み JSON、ゲームスレッド単一ライタ/HTTP は読みのみでロック不要)、SessionStatsObsControllerObsFormat(整形)。
  • MainController.changeState() を更新 funnel に select / nowPlaying / play / result / courseResult を反映。BMSPlayer の GAS 処理直後に種別変化時のみゲージをライブ更新(毎フレーム生成しない)。
  • 難易度は難易度表テーブル表記(例 sl9 / ★13)、表外は +PLAYLEVEL にフォールバック。
  • 選曲履歴(直近最大5件・新しい順)を /state.jsonhistory に追加。
  • 設定:Config.obsEnabled / obsPortPlayerConfig.dan / obsComment(各 PersistenceDto 同期)、ランチャー Stream タブに UI 追加。

オーバーレイ (#182)

  • 単一 overlay.html(背景透過・全画面絶対配置・約1秒ポーリング・DOM 差分更新・?blocks= で表示ブロック選別)。
  • レイアウト(design.jpg 準拠):ゲーム画面フレーム #stage(16:9・透過・クリックスルー)/右レール(時刻・セッション・プロフィール・心拍予約、均一間隔)/下部フル幅の曲情報バー(1行・タイトル/アーティストのフォント自動フィット)/プレイオプション帯/中央リザルト/右下に選曲履歴(レベル・曲名・ランプ・スコア)。
  • ビジュアル:Claude 製「control deck」HUD(ライム×インク、Chakra Petch + Zen Kaku Gothic New、スキャンライン・コーナーフレーム・staggered 演出)。
  • 心拍数 #heartrate#185(将来要望)の予約枠のみ(データ到来時のみ表示)。

テスト

  • xvfb-run -a ./gradlew test : 成功(Java 変更の各段階で再検証)
  • overlay : node --check OK・CSS ブレース整合・DOM シムで data-field 流し込み/phase・隠蔽クラス/fit-to-width/clock tick/history 行描画(曲名は textContent でインジェクション安全)の契約を実証。

動作確認(Windows ホスト推奨)

  • ランチャー Stream タブで OBS 有効化+ポート設定 → OBS ブラウザソースに http://localhost:7322/overlay.html(キャンバス解像度・背景透過)。
  • 難易度表フォルダの 7K 譜面を RANDOM + GAS=BEST CLEAR でプレイ:Now Playing/プレイオプション(ゲージが GAS で1秒ポーリングによりライブ変化・GAS バッジ・レーン列)/難易度表表記/プロフィール(名前・段位・一言)/中央リザルト(ランプ・ランク・EX・diff・新記録 UPDATE)/セッション統計/右下の選曲履歴を確認。
  • 起動順:ページは beatoraja 稼働中に1回読み込めばよい(以後ポーリングで自動復帰)。空白時はブラウザソースを Refresh。

レビュー観点

  • スレッド安全(単一ライタ+volatile、HTTP は volatile スナップショット読みのみ)。
  • changeState funnel + GAS 副経路、lastResult の diff/updated 取得経路(MusicResult.updateScoreDatabaseonResultScore)。
  • obsEnabled=false 時のゼロ影響。

🤖 Generated with Claude Code

マージリクエストレポート

読み込み中