Slide 1

Slide 1 text

AIに実況させる motemen 2025/05/29 Kyoto Tech Talk #8

Slide 2

Slide 2 text

こんにちは ● id:motemen / @motemen / @motemen.works ● 株式会社はてな CTO ● 趣味はポケモン対戦です

Slide 3

Slide 3 text

はてな サマーインターンシップ 2025 3

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

ずんだもん ● 東北地方のマスコットキャラクター ● 音声合成ソフト VOICEVOX で利用できることで有名 ● 坂本アヒルさんの立ち絵とともに動画にも多数出演 ● この人にしゃべってもらいます

Slide 6

Slide 6 text

完成イメージ図 https://youtu.be/mnrNTDE8vkQ

Slide 7

Slide 7 text

Background: 対人戦勝てない問題 ● 勝てない → 続かない → 強くならない ○ ビジネスパーソンとして成長しない ● 勝つために ○ ① ふりかえりを行う ○ ② 場数を踏む

Slide 8

Slide 8 text

OBS Studio ● 無料で使える配信・録画ソフトウェア ● 複数の入力(ソース)を組み合わせること ができる ● WebSocket API などもあって高機能

Slide 9

Slide 9 text

1. 対戦の録画と分析 ● OBS Studio + 激安キャプチャカードによる録画 ● 動画を解析して相手の構築と勝敗などを記録する $ uv run eapu2.py video.mp4 INFO 対戦相手の構築: パオジアン/カイリュー/水オーガポン/キョジオーン/ハバタクカミ/ミミッキュ INFO Scene change detected: SceneKind.PARTY_SELECTION INFO Scene change detected: SceneKind.IN_BATTLE INFO [02:24] 対面: ブリジュラスvsミミッキュ INFO [02:44] メッセージ: 相手の ミミッキュの おにび! INFO [02:52] メッセージ: プリジュラスは やけどを負った! INFO [02:55] メッセージ: プリジュラスの ステルスロック! INFO [03:00] メッセージ: 相手の周りに とかった岩が ただよい始めた! INFO [03:05] メッセージ: プリジュラスは やけどのダメージを受けた! ...

Slide 10

Slide 10 text

2. 配信でモチベを強制的に維持 ● 誰も観てなくても、10分で辞めるみたいなことがしづらくなる ● せっかくなのでずんだもん画像を配置してみると急にそれっぽくなる ● 前述の解析スクリプトをリアルタイムに実行すれば喋れるのでは? ○ → ゲームそっちのけで開発へ…

Slide 11

Slide 11 text

全体像

Slide 12

Slide 12 text

プレイ動画分析くん( eapu2) ● 動画のフレームから以下のシーンを検出、情報抽出 ○ 選出画面 / 対戦中 / 結果画面 ○ ※ 素朴に OCR & 画像のテンプレートマッチング ■ OpenCV ■ Vision API (macOS)

Slide 13

Slide 13 text

技術: OBS Browser Source ● Chromium ベースのブラウザ画面 をソースとして取り込む ● ゲーム画面の上にHTMLを重ねるよ うなイメージ ● 描画を更新すれば反映される ● ページ上で再生した音声もいける ● つまりなんでもできる

Slide 14

Slide 14 text

ai-streamer ● ふつうのリアルタイムWebアプリケーションを書けばよい ● サーバ: 台詞生成(OpenAI)→ 音声生成(VOICEVOX) ○ POST /api/chat ● フロントエンド(OBS 内): ○ Server-Sent Events でリアルタイムにコマンドを受け取り… ○ 音声を再生 ○ 表情を変える ○ 字幕を表示

Slide 15

Slide 15 text

実況っぽくする工夫 ● レイテンシを下げるため Streaming response + 句読点で分割 ○ for await (chunk of responseStream) しつつ ○ 句読点がやってきたらすぐに音声生成へ ● n秒間発話がなかったら雑談 ○ 発話が終わったことはフロントエンド側でしかわからない ○ ので、フロント側から POST /api/idle する ● 過去の発話もプロンプトに含めて、一貫性を維持 ○ これがないと毎回新鮮な反応を返すbotになってしまう…

Slide 16

Slide 16 text

いい感じにプロンプトしてやる 40文字程度の短文を3つほどで、対戦相手のパーティー を吟味してください。 相手のポケモン: リザードン・グラードン・… <こちらのパーティー情報> 個別のポケモンの性能情報として、以下の情報も使って ください: ---- リザードンは「ほのお・ひこう」タイプで、特に「サン パワー」と晴れ状態を組み合わせることで超火力の炎技 が使える特殊アタッカー。… ----

Slide 17

Slide 17 text

🐱 🥄

Slide 18

Slide 18 text

Model Context Protocol

Slide 19

Slide 19 text

MCP経由で喋らせる ● ずんだもんによるライブコーディングにも対応 ● やります

Slide 20

Slide 20 text

prompt = """あなたは、VSCodeを使ってライブコーディング中のプログラマーです。 状況を伝えるので、視聴者にわかりやすく現在の状況を120文字程度で説明してください。 音声での発言を想定しているので、コードスニペットなどは使用しないでください。 語尾に『のだ』や『なのだ』をつけて話します。少しとぼけた雰囲気で、親しみやすく話してくだ さい。敬語は使わず、フレンドリーな口調を維持してください。 """ [[replace]] from = "AIStreamer" to = "エーアイストリーマー" [[replace]] from = "GitHub" to = "ギットハブ" [idle] timeout = 5000 prompt = "生活感のある雑談をしてください" 設定例

Slide 21

Slide 21 text

motemen/ai-streamer

Slide 22

Slide 22 text

Epilogue: ポケモン対戦、強くなったのか ● Nintendo Switch が壊れたので遊べてません 😅 ● Switch 2 も当選していない状態