スプラトゥーン3で、やられたシーンをOBSのリプレイバッファで自動保存する

# この記事は

スプラトゥーン3の**試合中に**、やられる直前15秒の動画を自動作成するシステムを開発したので紹介します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334798/18c1ba40-10f1-095d-7543-35fefabb2f3b.png)

ここに至るまでの15秒の動画を**試合中に**自動作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334798/0eb21099-e537-f8f1-9d41-0c86155830c5.png)

# スプラトゥーン2の時に開発した、やられたシーン自動抽出システムは、時間がかかる

スプラトゥーン2に引き続きスプラトゥーン3もやりこんでいますが、対面力に課題ありです。そこで、やられたシーンを録画で振り返りつつXマッチに潜っています。

その振り返りの効率化のため、スプラトゥーン2の時にプレイ録画から、やられたシーンを自動抽出するシステムを作りました。その様子はこちらの記事で解説しています。

* [スプラトゥーン2のプレイ動画から、やられたシーンだけをディープラーニングで自動抽出する](https://qiita.com/tfandkusu/items/acbc0906046bb7b2b1db)
* [Flutter Webで画像分類を行う(AutoML Vision, TensorFlow.js)](https://qiita.com/tfandkusu/items/b8b498d60ddff3db4d50)

しかしこのシステムには問題があります。試合が終わってから、少なくとも1試合分の録画に対して、やられたシーンを抽出するので時間がかかります。
![ikut_progress.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334798/43aec65c-ae61-ef86-27be-b9dfbb59057e.gif)
そこで今回は試合をしながら、やられる直前15秒の録画を自動で作成する方法を考えました。

# ⁠画像の引用

この記事では任天堂株式会社のゲーム、スプラトゥーン3のスクリーンショットを引用しています。

# OBSのリプレイバッファを使う

録画やライブ配信で使われる[OBS](https://obsproject.com/ja)には、リプレイバッファという機能があります。「リプレイを保存」ボタンを押すと、ボタンを押した直前N秒の動画を保存します。[Nintendo Switch にあるキャプチャーボタン長押しで30秒前からの動画を撮影する機能](https://support.nintendo.co.jp/app/answers/detail/a_id/35057)と同様の機能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334798/43e1a64f-6352-a23c-30b0-477f4e03ebe3.png)
[やられたシーンの分類モデル](https://qiita.com/tfandkusu/items/acbc0906046bb7b2b1db#%E5%88%86%E9%A1%9E%E3%83%A2%E3%83%87%E3%83%AB)(※1)はすでにあるので、現在キャプチャしているフレーム画像を認識して「リプレイを保存」ボタンを押してくれるOBSプラグインを作ることができれば問題を解決できそうです。

しかし[OBSプラグイン](https://obsproject.com/wiki/Getting-Started-with-OBS-Studio-Development)はC++言語で開発する必要があり、またフレームワークは[Qt](https://www.qt.io/ja-jp/)を使っていて、普段はAndroidアプリを作っている私にとって技術的に距離が遠そうです。

※1 スプラトゥーン2の時に開発したものですが、スプラトゥーン2とスプラトゥーン3は、やられたシーンのレイアウトがほぼ同じなので分類できます。

# obs-websocket と仮想カメラを使う

そこでOBSの外からOBSを制御する方法を考えます。

OBSには [obs-websocket という Web Socket API](https://github.com/obsproject/obs-websocket) がバージョン28から標準搭載されています。

またOBSには仮想カメラという機能があり、OBSのキャンバスを仮想的なWebカメラとして出力する機能があります。

今回はその2つを外部から使用するアプリを作ります。

# ⁠システム概要

今回構築したシステムの全体像はこのようになっています。

![iKut 3 システム概要図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334798/74be8cc2-0b4d-d4f5-59af-5c73fa9c1870.png)

1. OBSでHDMIキャプチャを使い Nitendo Switch の映像をキャプチャします。
2. OBSでキャプチャした映像はOBSの仮想カメラで閲覧できるようにします。
3. Google Chrome で動作する自作Webアプリで仮想カメラの映像を取り込みます。
4. 映像のフレームの中にやられたシーンがあったら、[リプレイバッファ保存命令](https://github.com/obsproject/obs-websocket/blob/master/docs/generated/protocol.md#savereplaybuffer)を obs-websocket に送ります。
5. OBSはリプレイバッファを動画ファイルとして保存します。その結果、保存される動画は、やられる直前のシーンとなります。
6. 私は試合終了後すぐに保存された動画を見て、反省点を明確にして次の試合に活かします。

# ⁠自作アプリ

今回開発した自作アプリはこちらから誰でも使用できます。すべての処理はブラウザ内で完結し、 obs-websocket 以外には情報をアップロードしません。

https://s3.ikut.app/

ソースコードはこちらになります。

https://github.com/tfandkusu/ikut3

## 準備

OBSを以下のように設定します。

Nintendo Switch のHDMI出力をキャンバス全面に映します。
ソース→追加 → 映像キャプチャデバイス
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334798/b261970e-d8ce-58bf-e030-a30807f07da2.png)

obs-websocket を有効にします。

* 上部メニュー → ツール → obs-websocket 設定
* 「WebSocketサーバーを有効にする」にチェックをつける
* サーバポートはデフォルトの 4455 に設定する
* 「認証を有効にする」は解除する

自作アプリでのポート番号変更と認証への対応はまだ作っていないです。安全なローカルエリアネットワークに接続されているPCでご利用ください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334798/6294ed19-7673-de02-4902-b60a540ffd9a.png)

リプレイバッファを有効にします。
設定 → 出力 → 「リプレイバッファを有効にする」にチェックをつけます。
リプレイバッファの設定を必要に応じて行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334798/c959dcef-7a45-ae07-fa45-47298269397c.png)

設定画面を閉じて「リプレイバッファ開始」ボタンを押します。
仮想カメラを開始します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334798/0bdb421a-42f1-cc07-a98a-6a0b5f62d900.png)

## ⁠アプリの操作方法

基本的には黄色い記載に対応すれば良いです。
（PC設定がダークテーマの場合はアプリもダークテーマになります。）

1. Google Chrome で https://s3.ikut.app/ にアクセス
   * それ以外のブラウザではテストしていません。
2.  「カメラに接続」ボタンを押す
3. ブラウザからカメラの使用の許可を求められたら「許可する」ボタンを押す
   * OBS Virtual Camera 以外のカメラに接続されてしまった場合はアドレスバーのカメラボタンから設定する
4. OBSのキャンバスと同じ映像が映ることを確認
5. 「obs-websocket に接続してください」の下の「接続」ボタンを押す
6. 「obs-websocket に接続しました」ログが表示されることを確認

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334798/680686fe-219c-d5f5-92b4-d0b9e247324e.png)

この状態でスプラトゥーン3で敵にやられたら、リプレイバッファが自動で保存されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334798/258035b6-18a0-babe-de12-0fea177015bb.png)

# まとめ

この記事ではスプラトゥーン3をプレイ中、敵にやられてデスしたら、自動でOBSのリプレイバッファを作成するシステムを紹介しました。OBSで使われているC++やQtに馴染みが無くても、やられたシーンに対応した画像認識モデルがあれば、一般的なWebフロント開発の技術でOBSとやりとりすることで目的のシステムを構築することができました。