今更だけどYouTube LiveのメッセージをUnityで取得してみる

こんにちは、エンジニアの渡辺(@mochi_neko_7)です。

最近は趣味で専らLLM周辺の技術を触ったりプロトタイプを作ってみたりしていますが、今年のGWはずっと気になっていたAITuber*1を触っていました。

まとまってはいませんがAITuberの詳細が気になる方はこちらをご覧ください。

zenn.dev

以前作っていたChatGPT、VOICEVOX、VRMを組み合わせたAI Agentのプロトタイプでは、あくまでAgentのため人間が会話を入力する方式でしたが、AITuberの場合に大きく変わるのはYouTube Liveなどの視聴者のメッセージ(スパチャなども含む)とインタラクションする、という点です。

YouTube Liveの情報を拾うには公開されているWebAPIを叩けば良いのですが自分はこれまで触ったことがありませんでした。

.NET向けのクライアントライブラリも用意されていますがUnityにインポートする手間、使う機能がそこまで多くないこと、エラーハンドリングの自由度、実装の難易度がそこまで高くないことを踏まえ、結局自分でライブラリを書くことにしました。

github.com

本記事では、YouTube Data API v3を使ってYouTube Liveの視聴者のメッセージを取得するまでの流れと、このライブラリの利用方法について簡単に解説しようと思います。

環境

  • Unity 2021.3.0f1

基本的なワークフロー

基本的なワークフローはUnityでない場合と同様なため既に解説記事がたくさんあると思いますが、簡単に確認をしておきます。

YouTube Data API v3、およびYouTube Live Streaming APIを使用し下記の流れで準備をします。

  1. 認証をする(API Key or OAuth 2.0)
  2. VideoIDを使ってYouTube Data API / Videos APIを叩いて、LiveChatIDを取得する
  3. LiveChatIDを使ってYouTube Live Streaming API / Live Chat Messages APIを叩いて、 LiveChatMessagesを取得する

公式のドキュメントはこちらです。

developers.google.com

developers.google.com

まず認証ですが、API Keyを使う方式と、OAuth 2.0で認証をする方式の2つから選ぶことができます。

API Keyの方が実装が楽、かつAITuberのようなユースケースでは十分のため今回はこちらを採用しています。

アプリなどを配布する場合にはクライアント側(Unity側)でAPI Keyを持つのはKeyを抜かれるリスクがあるため、そのようなユースケースではOAuthの認証を使用することになると思います。

次に、VideoID(YouTube動画のURL https://www.youtube.com/watch?v=*********** のQuery Parameter *********** の部分の文字列)を使って、(YouTube Live Streaming APIではなく)YouTube Data API / Videos APIを叩いてLiveChatIDを取得します。

どういう理由なのか分かりませんが、YouTube Data APIをサッと見てもLiveChatIDの取得方法がリファレンスには書いていないので注意が必要です。

Videos  |  YouTube Data API  |  Google Developers

part のQuery Parameterに liveStreamingDetails を入れると、items の要素に次の形式のオブジェクトが含まれるようになるため、ここから"activeLiveChatId"を取り出すことができます。

"liveStreamingDetails": {
    "actualStartTime": "2023-05-07T10:33:17Z",
    "scheduledStartTime": "2023-05-07T11:00:00Z",
    "concurrentViewers": "206",
    "activeLiveChatId": "***********************************************************"
}

LiveChatIDが手に入ったら、YouTube Live Streaming API / Live Chat Messages APIを叩いてメッセージのリストを取得します。

developers.google.com

少し注意が必要なのは、リストがPagingされているためにPage Tokenを取り回さないと差分が取得できないという点です。

Responseには "nextPageToken" という要素が含まれているのでこれをキャッシュしておき、次のリクエストでPage TokenをQuery Parameterに載せる必要があります。

メッセージには snippet.type の要素で種類が分かりますが、テキストのみのコメント以外にもスーパーチャット(スパチャ)なども含まれていることも気をつけておきます。

LiveChatMessages  |  YouTube Live Streaming API  |  Google Developers

自分の作成したライブラリではこれらのAPIをパッと叩けるようにする実装を用意しています。

APIの叩き方はテストコードを見ると分かるとは思いますが、エラーハンドリングを自前のライブラリで行っていて少し複雑に見える点に注意してください。

github.com

Pollingしてメッセージを更新する仕組み

配信中に随時追加されるコメントを拾うためにはLive Chat Messagesの差分を取っていく必要がありますが、そのためにはPollingしつつPage Tokenを更新していく仕組みが必要です。

また機能を利用する視点では、Pullして差分を取りに行くよりはPushのイベントで差分が来たら配ってもらう方が取り回しが良いでしょう。

ですので一定間隔でPollingしつつ、UniRxのイベントで差分を取得できる拡張機能を用意しています。

github.com

MonoBehaviourからこれを利用するサンプルも用意してあるので、使い方はこちらを参照していただければと思います。

github.com

UniRxを活かしたフィルタリングの例

UniRxでイベントが拾えると嬉しいのは、フィルタリングなどの加工がしやすい点です。

例えばLive Chat Messagesにはスパチャなども含まれていますが、 スパチャに反応して特別なギミックを動かしたい場合には次のようなStreamを作れば良いです。

    collector
        .OnMessageCollected
        .Where(message => message.Snippet.Type is LiveChatMessageType.superChatEvent)
        .Subscribe(OnSuperChatMessageCollected)
        .AddTo(this);

他にも時間方向のイベント処理などもできますので、ユースケース次第で柔軟にStreamを用意できると思います。

おわりに

リアルタイムの配信限定ではありますが、YouTube Liveの視聴者のメッセージを取得する流れとそのUnityライブラリを簡単に紹介しました。

必要最小限に絞ると独自実装でもそれほど複雑にはなりませんが、YouTubeのAPIの仕様の理解が必要なのでサクッと利用したい方はライブラリを触ってみていただければと思います。

YouTubeのAPIを触るだけなら別にUnityを使用する必要はないですし、LangChainを触る場合はPythonで書いた方が早いかもしれません。

ただAITuberの用途を考えた時にVRM ↔︎ Live2Dなどのアバターの取り回しや、3D空間や物理エンジンの利用、XRへの拡張などを考えると、Unityで実装するモチベーションもあるかと思います。

自分の場合は他に必要な機能を既にUnityのライブラリとして作っていたためUnityで作った方が早い、というのも大きいですが。

UnityベースでAITuberのような仕組みを作りたい方などの参考になれば幸いです。

参考

*1:VTuberの中身をAI、LLMベースのChatGPTなどに置き換えたもの、というイメージ