実況 AI が一歩遅れるので語るのをやめて相槌にした
カメラの前でゲストが手元の対象を次々と切り替えていく様子を、音声 AI が実況します(映像の渡し方は OpenAI Realtime API に映像を流せないので 1fps の静止画で代用した)。最初の設計では対象が変わるたびに AI が語っていましたが、この設計では実況が構造的に追いつきません。語り終える前に次の対象が来るので実況は常に一つ遅れ、ゲストの手が速いほど遅れが積み上がります。
生成を速くしても打ち切りを入れても遅れは消えませんでした。一つの対象に語る時間が対象の切り替わる間隔より長い限り、どう並べても追いつかないからです。
転回: 実際の MC は解説し続けない
テレビの実況の MC は、目の前のものを一つずつ解説してはいません。主役はゲストで、MC は基本的に相槌を打ち、語るのはゲストが何かを掲げた・手を止めた・声を上げたときだけです。場面が変わったら前の話は無条件で捨てます。
AI の設計も、この MC のやり方に合わせて次のように変えました。
- 基本の出力は相槌(「うん」「ほぉ」「おっ」)。一つの対象につき一言以下
- 語るのは、ゲストが掲げた・止めた・声を上げたのいずれかが起きたときだけ
- 場面が変わったら、前の話題は言い切っていなくても捨てる
うまくいったこと: 高速な切り替え中の相槌は体験として成立した
ゲストが速いペースで対象を切り替えている間は AI が相槌だけを打ち、私が見ている限りでは体験として成立しました。一つ遅れの解説を聞かされるより、テンポに合った相槌の方が「見てもらっている」感覚が残ります。
「反応しない勇気」を設計に入れたと言えます。全イベントに語る AI より、語らないことを選べる AI の方が速く見えます。
抜けたこと: 止めて掲げた 20 秒間を見逃した
ゲストが対象を手に取り、動きを止めてカメラに掲げた場面は語るべき場面でしたが、AI はこの 20 秒間何も言いませんでした。
原因は、映像の検出器が「動きの山」だけを出来事とみなしていたことです。掲げて静止している間のフレーム差分は 4〜8 で動きの閾値を下回り、検出器から見れば「何も起きていない」状態が続いていました。語るべき瞬間は動きの山ではなく動きの谷にありました。
その後: 静止イベントを足したら二重発火した
静止も出来事として検出するようにしたところ、既存の「動きの山」トリガーと静止トリガーが近い時刻に両方発火し、後から発火したトリガーが先の応答を打ち切る自己キャンセルの連鎖が起きました。一方のトリガーの応答が語り始めた瞬間にもう一方のトリガーが打ち切るので、結局どちらの応答も語りません(出力を切る仕組みが音声を消した別の例: LLM は喋っているのに音声が出ない原因は進行装置のフラッシュ)。
対処として、トリガーを一本の直列キューに通しました。どのトリガーが発火しても、キューの先頭が処理中なら後続は待つか捨て、並列には発火させません。
体験の評価は主観で、静止の検出とキューにも制約が残る
- 「体験として成立した」は私自身の主観で、第三者の評価は取っていません
- 静止の検出は「差分 4〜8 が続く」という閾値で、掲げずにただ手を止めただけの静止と区別できていないため、語らない場面で語ることがあります(誤検知の扱い方は 検出器の精度ではなく誤検知時の体験で仕様を書く)
- 直列キューにしたことで近い時刻に起きた 2 つの出来事のうち片方は必ず捨てられ、両方に反応する設計は諦めました
語る場面を絞り、トリガーの排他を先に決める
- 全イベントに語る AI はどれだけ速くしても遅れるので、「反応しない勇気」を設計に入れる
- 止めた・掲げたのように、語るべき瞬間は動きの谷にもある
- 後から足したトリガーは既存のトリガーと二重発火するので、イベント検出を足すときは既存トリガーとの排他を先に決める
喋らない AI 実況者の方が、喋り続ける AI 実況者より速く見えました。喋るべき瞬間を見逃した原因は、「動いたときだけ見る」検出器を書いた私にありました。