プレイヤー識別の方法や、APIの制限対策、重複チェックなど、いくつか試行錯誤したので、その辺りをメモしておきます。
Switchのキャプチャ環境についても、記事後半の「キャプチャ環境について」に記載しています。
スポンサーサイト
目次
・背景と経緯
・作ろうとしたもの
・最初はOCRを試した
・Gemini APIについて
・Gemini APIでの試行錯誤
- モデル選定とAPI制限対策
- プレイヤー識別の工夫
- 時刻のずれ
- ステージ名認識の揺れ
・キャプチャ環境について
・現在の運用と今後
背景と経緯
スプラ3をプレイしていて、自分の戦績を記録して振り返りたいと思ったのですが、Nintendoの非公式APIを使った既存のツールは仕様変更で動かなくなっていました。
調べてみると、今から使うにはそれなりに手間がかかりそうだったのと、非公式なので将来的にまた使えなくなるリスクもあり、断念しました。
そこで、Switchの映像をキャプチャボードで取り込んで、リザルト画面をAIで解析すればいけるんじゃないかと思って、作ることにしました。
作ろうとしたもの
作ろうとしたのは、こんなツールです:
基本的な動作
(1) Switchのスプラトゥーン3の「最近のバトル」画面をキャプチャボードで取り込む
(2) Enterキーを押すと画像として保存
(3) Gemini APIで画像を解析して、戦績データ(日時、ステージ、ルール、勝敗、キル、デス、スペシャル)を抽出
(4) CSV形式で保存
コーディングについて
実装はClaude Codeに任せました。私からは「こういう機能が欲しい」と指示を出して、あとはClaude Codeが実装してくれました。
最初はOCRを試した
最初は
pytesseractなどのOCRライブラリで文字認識を試してみました。ただ、スプラ3の特殊なフォントせいか認識精度が低かったです。また、戦歴の画面では、自分の戦績の表示位置が固定されていません。固定座標で文字を切り出せないのもあって、認識しにくく、今回は断念しました。
そこで、生成AIのGemini APIを試すことにしました。Gemini APIなら、ある程度は無料で使えますし。
Gemini APIについて
Gemini APIは、Googleが提供する生成AI「Gemini」のAPIです。画像を解析してテキストを抽出するような用途にも使えます。
Google AI StudioでAPIキーを発行すれば、Googleアカウントがあれば誰でも無料で使い始められます。
Gemini APIは無料の枠があり、1日あたり一定回数まで無料で使えます。
モデルごとに「RPD」(Requests Per Day:1日あたりのリクエスト数)が設定されています。
Google AI Studioの画面で、各モデルの利用状況を確認できます:
例えば、
gemini-2.5-flash-liteは1日20回、gemini-2.5-flashも1日20回という制限があります。Gemini APIでの試行錯誤
Claude Codeに基本的な仕様を伝えて、PythonでOpenCVとGemini APIを使ったツールを作ってもらったのですが、実際に動かしてみると、いくつか問題が出てきました。
(1) モデル選定とAPI制限対策
開発中、すぐに気づいたのがGeminiの無料枠の制限です。
最初に使っていたモデルは1日20回までで、開発中はプロンプトを試行錯誤するのもあって、すぐ制限に達してしまいました。
1日に20試合以上することもあるし、どうしようかなと思っていました。
複数モデルの自動切り替え
そこで、複数のモデルを自動で切り替えることにしました。
具体的には、利用可能なモデルをリストアップしておいて、制限エラーが出たら次のモデルに自動で切り替えて再試行します。
最初は「どのモデルが使えるのか」もよくわからなかったので、簡単なテストスクリプトを作って、実際に画像を投げてみて、使えるモデルを探しました。
最終的には3つのモデルファミリーを使い分けることで、合計60回/日まで使えるようになりました。
1日に60試合もすることはまずないので、実用上は十分です。
# 利用モデルの自動切り替え
self.available_models = [
'gemini-2.5-flash-lite', # 20回/日
'gemini-2.5-flash', # 20回/日
'gemini-3-flash-preview', # 20回/日
]
今はこれですが、定期的な見直しが必要になります。
モデル名の罠
ここで混乱したのが、API側のモデル名と画面の表示名が微妙に違うことです。
例えば、コードで
gemini-3-flash-previewを指定して使うと、この画面ではgemini-3-flashの使用回数が増えていきます。つまり、同じモデルの中でもバージョン違いのようなものがあるようですが、使用制限はまとめてカウントされるのかもしれません。
このあたりの仕様はよくわかっていません。
(2) プレイヤー識別の工夫
画面上には8人の成績が並んでいるので、この中から自分がどれなのかをGeminiに判断してもらう必要があります。
最初の方法:ユーザー名で指定
最初は、プロンプトでプレイヤーを指定していました。
しかし、Xマッチではプレイヤー名が表示されないことに気づきました。
正確には、表示されるのですが、一定時間ごとに装備の名前に切り替わってしまうので、キャプチャのタイミングによってはユーザー名が映っていないことがあります。
解決策:黄色いL字矢印で指定
そこで、プロンプトを「黄色いL字矢印があるプレイヤーのデータを取得」に変更しました。
ただ、画面上には黄色い要素は他にもあるし、矢印っぽい形もあるので、誤認識が起きていました。
最終的には、プロンプトで「画面中央やや右側のプレイヤーリストの中で、プレイヤー名のすぐ左側にある黄色いL字矢印」と、位置も含めて指定することで、精度が上がりました。
実際に使ったプロンプト(抜粋)
最終的に使っているプロンプトはこんな感じです:
この画像はスプラトゥーン3の試合結果画面です。
【重要な識別方法】
この画像はスプラトゥーン3の試合結果画面です。
【重要な識別方法】
画面の中央やや右側にプレイヤーリストがあります。
その中で、プレイヤー名の左側に「黄色いL字型の矢印マーク」が表示されているプレイヤーが自分(操作しているプレイヤー)です。
注意:
- この黄色いL字矢印は、プレイヤー名のすぐ左側にあります
- 画面左端のイカマークの矢印とは別のものです
- プレイヤーリストの中(画面中央やや右)を探してください
このL字矢印があるプレイヤーの行を見つけて、その行の右側に表示されている3つの数値を読み取ってください:
- 左の数値 = キル数(K)
- 中央の数値 = デス数(D)
- 右の数値 = スペシャル数(SP)
(3) 時刻のずれ
ここではじめて気が付いたのですが、画面によって表示される時刻が違っていました。
スプラ3では、同じ試合でも:
・戦歴画面:試合開始時刻
・メモリープレイヤー画面:試合終了時刻
が表示されるので、画面が違うと時刻が一致しません。
そこで、使う側で必ず戦歴画面をキャプチャするようにしています。
(4) ステージ名認識の揺れ
ステージ名の認識ミスが多く、特に「クサヤ」を「クツヤ」とか誤認識したりします。また、「マヒマヒリゾート&スパ」の&が全角になったり半角になったり、表記揺れが多発しました。そこで、プロンプトでステージ名を指定することにしました。
プロンプトを抜粋します。
以下の情報を抽出してください:
1. 日時(画面左上に表示されている時刻)
2. ステージ名(必ず以下のリストから正確に選んでください):
- オヒョウ海運
- カジキ空港
- キンメダイ美術館
- クサヤ温泉
- ゴンズイ地区
- コンブトラック
- ザトウマーケット
- スメーシーワールド
- タカアシ経済特区
- タラポートショッピングパーク
- チョウザメ造船
- デカライン高架下
- ナメロウ金属
- ナンプラー遺跡
- ネギトロ炭鉱
- バイガイ亭
- ヒラメが丘団地
- マサバ海峡大橋
- マテガイ放水路
- マヒマヒリゾート&スパ
- マンタマリア号
- ヤガラ市場
- ユノハナ大渓谷
- リュウグウターミナル
- 海女美術大学
3. マッチタイプ(バンカラマッチ (オープン)、バンカラマッチ (チャレンジ)、Xマッチ など)
4. ルール(ガチアサリ、ガチエリア、ガチホコバトル、ガチヤグラ など)
5. 勝敗(WIN/LOSE)
6. キル数(L字矢印があるプレイヤーの右側の3つの数値の左)
7. デス数(L字矢印があるプレイヤーの右側の3つの数値の中央)
8. スペシャル利用数(L字矢印があるプレイヤーの右側の3つの数値の右)
注意: ステージ名は必ず上記リストの表記と完全に一致させてください。特に「クサヤ温泉」「マヒマヒリゾート&スパ」(全角&)に注意してください。
以下のJSON形式で回答してください(JSONのみ、他の説明文は不要):
{
"日時": "2025/12/31 00:52",
"ステージ": "カジキ空港",
"マッチタイプ": "バンカラマッチ (オープン)",
"ルール": "ガチアサリ",
"勝敗": "WIN",
"キル": 10,
"デス": 8,
"スペシャル": 4
}
キャプチャ環境について
最後に、私のSwitch/Switch2のキャプチャ環境についても簡単に紹介します。
接続構成
Switch → HDMI分配器 → キャプチャボード → PC → ヘッドホン
└→ ゲーム用ディスプレイ
HDMI分配器を使って、一方をキャプチャボードに、もう一方をゲーム用のディスプレイに接続しています。
キャプチャボード経由だと遅延が発生するので、ゲームプレイ用には分配器の直接出力を使うためです。
音声の統合
ゲームの音声は、PCのUSBから入力された音声を「このデバイスを聴く」に設定して、PCのヘッドホンで聞いています。
私は普段、YouTubeを見ながらゲームをするので、PCの音(YouTube)とゲーム音をひとつのヘッドホンで聞きたかったので、こうしています。
こういう構成なので、キャプチャボードは比較的安いもので十分です。
現在の運用と今後
現在は、試合が終わったら戦歴画面を表示した状態でEnteryキーを押すだけで、自動的に画像保存 → Gemini解析 → CSV保存まで完了します。
ある程度の誤認識はありますが、その場合はExcelでCSVを手修正しています。
ひとつ注意が必要なのは、CSVファイルをExcelで開いたまま次の解析を実行すると、ファイルがロックされていて書き込みエラーになってしまうことです。
そのため、修正したら必ずExcelを閉じてから次のキャプチャをする、という運用にしています。若干面倒ですので、この辺りも改善できそうです。
現状、CSVファイルをExcelで取り込んで、分析したり、グラフ化したりしています。
今後はこれをWebツールにでもしてみようかと考えています。
同じように戦績記録したい方や、Gemini APIで画像解析をしたい方の参考になれば幸いです。
スポンサーサイト
