この記事は、前回書いた「自動運転AIチャレンジで、車載カメラ映像をVLMに実況させてみたメモ」の続きです。
前回は、自動運転AIチャレンジ2026の走行中に、車載カメラ画像と車両状態を見ながらローカルVLM/LLMで実況文を作るところまで試しました。
前回記事:
今回は、その実況文をAITuberKitへ接続して、ブラウザ上のアバターに喋らせるところまでやってみました。
完成したシステムというより、まだ実験メモです。
ただ、前回は「音声ファイルを作って動画にあとから合成する」構成だったのに対して、今回は実際にAITuberKitの画面でキャラクターが発話するところまで進みました。
何をやりたいのか
やりたいことは、走行中の車両に「助手席AI」が乗っているような体験を作ることです。
カメラ画像や車両状態を見ながら短くコメントしてくれるキャラクターがいると、楽しく自動運転できるはずです。たぶん。
最終的には、次のような方向にもつなげたいです。
- 自動運転の挙動を説明してくれる助手席AI
- 走行ログを見返すための実況・解説生成
- チーム内で走行結果を共有するための動画化
- 将来的には、マルチモーダルAIを制御判断の補助に使えるかの検討
ただし、今回の記事では制御まではやりません。
今回は「VLM実況文をAITuberKitへ流し、アバターが喋るローカル構成を作る」ところまでです。
AITuberKitとは何か
AITuberKitは、AIキャラクターと会話したり、AITuber的な配信画面を作ったりするためのWebアプリケーションです。
AITuberという名前から「YouTube配信用のツール」という印象を持つかもしれません。
実際、YouTube Liveのコメントを取得して、AIキャラクターがコメントに返答する用途も想定されています。
ただ、AITuberKitの中身を今回の用途から見ると、もう少し広く「AIキャラクターの入出力UI」と捉えるのが分かりやすいです。
主に次のような部品をまとめて扱えます。
| 役割 | AITuberKitでできること |
|---|---|
| キャラクター表示 | VRM / Live2D / PNGTuberなどのキャラクターを画面に表示する |
| 会話入力 | テキスト入力、音声入力、配信コメント、外部連携メッセージなどを受け取る |
| 応答生成 | LLM APIなどを使ってキャラクターの返答を作る |
| 音声合成 | VOICEVOX、Google Text-to-Speech、ElevenLabsなどで発話音声を作る |
| 発話演出 | 音声に合わせた口パク、会話ログ表示、配信用の画面構成を担う |
| 外部連携 | WebSocket経由で別アプリケーションと接続する |
普通に使う場合は、ユーザーのコメントや配信コメントをAITuberKitへ入れて、AITuberKit側でLLM応答、音声合成、アバター発話までまとめて行う構成になります。
今回は、ここでAITuberKitに「走行状態を理解して実況文を考える」ところまでは任せていない点です。
自動運転AIチャレンジの走行実況では、入力がふつうのチャットではありません。
車載カメラ画像、速度、操舵、加速度、直近の走行履歴のようなROS側の情報を使います。
そのため、今回の構成ではAITuberKitを次のように使いました。
- 実況文を考える: ROS 2側のVLM実況ノード
- 実況文を受け取る: AITuberKitの外部連携モード
- 声に出す: AITuberKit側のVOICEVOX
- キャラクターとして見せる: AITuberKitのアバターUI
つまり今回のAITuberKitは、「頭脳そのもの」というより、生成済みの実況文をキャラクターの発話体験に変換する部分です。
この分け方にすると、走行状態を読むロジックはROS側で改善できます。
一方で、声、キャラクター、口パク、配信用画面はAITuberKit側の機能をそのまま使えます。
前回から変えたところ
前回の構成では、VLM実況ノード側でVOICEVOX音声を生成し、その音声を走行動画へ合成していました。
今回は、VLM実況ノードはテキストだけを出します。
そのテキストをbridgeでAITuberKitへ送り、AITuberKit側で音声合成、アバター発話、口パク、画面表示を担当します。
ざっくり比較するとこうです。
| 項目 | 前回 | 今回 |
|---|---|---|
| 出力 | 実況音声つき走行動画 | AITuberKitのアバター発話 |
| TTS | VLM実況ノード側のVOICEVOX | AITuberKit側のVOICEVOX |
| 画面 | 後処理で音声合成 | 実ブラウザ画面を録画 |
| キュー制御 | ノード側で古い音声を捨てる | bridgeでlatest-only送信 |
| 目的 | 低遅延実況生成の成立 | 喋るアバターUIの成立 |
今回の全体構成
今回も、外部APIには寄せず、1台のPC上で完結させています。
使った主な要素は次の通りです。
| 役割 | ツール |
|---|---|
| シミュレータ / 自動運転 | AWSIM / Autoware |
| 車載カメラ画像・車両状態の取得 | ROS 2 |
| VLM | moondream |
| Text LLM | qwen2.5:1.5b |
| LLM実行 | Ollama |
| アバターUI | AITuberKit |
| AITuberKit連携 | aituber-server |
| 音声合成 | AITuberKit側のVOICEVOX |
| 録画 | x11grab + PulseAudio monitor |
構成図にすると、だいたいこうです。
ポイントは、AITuberKitにLLM判断まで全部任せているわけではないことです。
走行状態を見て実況文を作る部分は、前回作ったVLM実況ノードのままです。
AITuberKitは、生成済みの短い実況文を受け取り、キャラクターとして喋るUI側を担当します。
AITuberKitへどう渡したか
VLM実況ノードは、実況文を realtime_commentary.jsonl に1行ずつ書き出します。
そのJSONLをtailするbridgeを作り、新しいコメントが出たら aituber-server へ送ります。
AITuberKitは外部連携モードで aituber-server と接続しているので、serverへ送られたメッセージがAITuberKit側に流れます。
今回のbridgeでは、古いコメントを全部順番に読ませるのではなく、基本的に最新のコメントだけを送るようにしました。
これは前回記事でも同じ考え方です。
リアルタイム実況では、古いコメントが溜まって順番待ちになると、映像と音声の対応がすぐ崩れます。
そのため、多少コメントを捨てても、いまの映像に近いコメントを優先した方が体験としては自然でした。
記事版の低遅延VLM実況ロジックをそのまま使う
今回の記事では、前回からの続きとして、次の構成にしました。
- VLM:
moondream - Text LLM:
qwen2.5:1.5b - 画像前処理:
full_320x180 - 前回フレームと現在フレームの比較
- 速度・操舵・加速度などの車両履歴
- 短い日本語実況文
- AITuberKit側のVOICEVOXで発話
設定のイメージはこうです。
REALTIME_COMMENTARY_MODE=llm
REALTIME_TEMPLATE_STYLE=normal
REALTIME_COMMENTARY_TRIGGER=interval
REALTIME_INTERVAL_SEC=4.0
REALTIME_MIN_SPEAK_INTERVAL_SEC=4.0
REALTIME_PREPROCESS=full_320x180
REALTIME_VISION_MODEL=moondream
REALTIME_TEXT_MODEL=qwen2.5:1.5b
REALTIME_VOICEVOX_URL=
REALTIME_VOICEVOX_URL は空にしました。
これは、VLM実況ノード側で音声を作らず、音声生成をAITuberKit側に寄せるためです。
最初はbridge側で 助手席AI: というprefixを付けていましたが、毎回それが読み上げられて邪魔でした。
最終的にはprefixを空にして、発話本文だけをAITuberKitへ送るようにしました。
なお、一度、もっと速いテンプレート実況もAITuberKitへつなぎました。
これはかなり速く、JSONLからbridge送信まではほぼミリ秒級でした。
ただし、前回Qiitaで書いた「VLMが画像を見て、Text LLMが車両状態と合わせて実況する」構成とは別物です。
今後、速さを重視するならテンプレート実況の組み合わせも選択肢になるかもしれません。
実際に喋った
今回、音声はAITuberKit/Chromeから出ているものだけを録音するようにしました。
その後、以下の流れで確認しました。
- AITuberKitを外部連携モードで起動
-
aituber-serverとWebSocket接続 - VLM実況ノードが
realtime_commentary.jsonlを生成 - bridgeがAITuberKitへ最新コメントを送信
- AITuberKit側VOICEVOXで発話
- Chromeの実音声をPulseAudio monitorで録音
- デスクトップ画面と音声を同じmp4に録画
最終的に、AITuberKitの実画面と実ブラウザ音声を含むデモ動画を作れました。
代表runの結果
このrunでは、左側にMPC Camera + AWSIM、右側にAITuberKitを置きました。
まだ完全に整った画面ではありませんが、少なくともAITuberKitのアバターは隠れず、実音声も同じmp4に入りました。
結果は次の通りです。
| 項目 | 結果 |
|---|---|
| comments | 8 |
| bridge sent | 8 |
| dropped | 0 |
| total latency min / median / max | 1.767 / 1.941 / 4.493 sec |
| vision latency min / median / max | 0.740 / 0.835 / 2.676 sec |
| text latency min / median / max | 0.959 / 1.060 / 1.811 sec |
| audio mean / max | -30.5 / -7.1 dB |
| 冒頭無音 | 約27.7 sec |
| NG語検出 | 0 |
| 完全重複 | 0 |
VLM + Text LLMの生成だけを見ると、中央値で約1.9秒でした。
別runでAITuberKit側の実音声開始も計測したところ、AITuberKitへPOSTしたあと、実際の音声開始までの追加遅延は中央値で約0.9秒でした。
つまり、正常にGPUが効いている状態なら、画像取得からアバターの実発話開始まで、おおむね2〜3秒台で収まる感触です。
もちろん、これはまだかなり荒い評価です。
コメント文の長さ、AITuberKit側の発話キュー、GPUの状態、録画開始タイミングで体感は変わります。
遅延の内訳
今回の遅延は、大きく分けると次の3つです。
- VLMが画像を見る時間
- Text LLMが実況文を作る時間
- AITuberKit側でTTSして実際に音が出るまでの時間
代表値としては、次のようなイメージです。
AITuberKitへのbridge送信そのものはかなり軽く、POSTは数十ミリ秒程度でした。
そのため、ボトルネックはbridgeではなく、VLM/LLM生成とAITuberKit側TTS/発話キューです。
(一度、Ollamaコンテナ内でGPUが効かなくなった状態もありましたが、そのときは同じ構成でも生成中央値が十数秒まで悪化しました。GPU必須です。)
ローカルLLM/VLMを使う場合、モデル選定だけでなく、実行時に本当にGPUに乗っているかを確認するのはかなり大事です。
視聴体験としてはまだ課題が多い
AITuberKitに接続して喋らせるところまではできました。
ただ、助手席AIとして気持ちよく見られるかというと、まだまだ課題があります。
特に気になったのは次の点です。
| 課題 | 状態 |
|---|---|
| 冒頭無音 | 録画開始から約28秒喋らない |
| 現在状況との同期感 | 発話がどの場面に対するものか分かりにくい |
| 風景への言及 | まだ弱い |
| レース実況らしさ | これから設計 |
| 画面レイアウト | デバッグ窓が残っている |
冒頭無音は、単純なVLM/LLM生成遅延とは別で、録画開始、AWSIM/ROS起動、最初のカメラ画像待ち、最初のコメント生成、AITuberKit発話開始までの待ちが合わさって、視聴上はかなり長い無音になりました。
AITuberKit接続で分かったこと
今回、AITuberKitを「生成済みコメントをキャラクターとして見せるUI」に特化させて使っています。
AITuberKitは頭脳を持たず、ただただ受肉させるためだけに使います。
自動運転AIチャレンジの走行実況では、カメラ画像だけではなく、速度、操舵、加速度、目標速度との差、直近の履歴が重要です。
そのため、走行文脈を読む部分はROS側の実況ノードで持ち、AITuberKitには短い発話文を渡す構成にした方が扱いやすいです。
一方で、AITuberKit側へ寄せると良い部分もあります。
- アバター表示
- TTS
- 口パク
- キャラクターとしての見た目
- 配信・デモ向けの画面
つまり、役割分担としてはこうです。
| 役割 | 担当 |
|---|---|
| 走行状態の理解 | ROS / VLM実況ノード |
| 画像から見えるものの抽出 | VLM |
| 車両履歴を踏まえた短文生成 | Text LLM / template |
| 発話とアバター表示 | AITuberKit |
この分け方にすると、VLM実況ノード側の改善と、アバター演出側の改善を分けて進められます。
ここから改善したいこと(雑案)
- キャラ付けをする
- 冒頭無音をなくす
- 発話がどの場面に対応しているかを見える化する
生成遅延が2〜3秒あると、発話がどのフレームに対するコメントなのか分かりません。 - 即時実況とVLM解説を分ける
- City Circuit Tokyo Bay らしさを入れる
- 人間と対話できるようにする
- 運転してもらう
まとめ
前回作ったVLM実況を、AITuberKitへ接続して、助手席アバターに喋らせるところまで試しました。
今回できたことは次の通りです。
- VLM実況ノードの出力をJSONLで受ける
- bridgeでAITuberKitへ最新コメントを送る
- AITuberKit側VOICEVOXで発話する
- AITuberKit/Chromeの実音声を録音する
- デスクトップ画面と音声を一発録画する
- 代表runでは生成中央値約1.9秒で動かす
一方で、助手席AIとして見て楽しいかというと、まだまだです。
AITuberKit接続そのものは成立したので、次は「喋る」から「見ていて面白い実況」に寄せていきたいです。
参考
- 前回記事: 自動運転AIチャレンジで、車載カメラ映像をVLMに実況させてみたメモ
- AITuberKit: https://github.com/tegnike/aituber-kit
- AITuberKit docs: https://docs.aituberkit.com/