YouTube Data API を使ってUEでコメントを取得する



Youtube LiveのコメントをUEから取得してみます。

<iframe width="560" height="385" src="https://www.youtube.com/embed/wQvqLTYvP-k" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

サンプルプロジェクトがあります。

https://github.com/yeczrtu/youtube_data_api__ue_sample

## 全体の流れ
1. UEとGoogle Cloud ConsoleでAPIが使えるようにセットアップ
1. APIリファレンスを参考にUEでリクエストを送信
1. レスポンスのJsonの処理
1. 取得したコメントを使用してリアクションを作成

# Unreal Engine側の準備

今回使用したUEのバージョンはUE5.1です。UEの導入や基本的な使い方は省略します。

UEでWeb APIを使用するためにプラグインのVaRestを入れます。RestAPIが手軽に扱えるようになる神プラグインです。

https://www.unrealengine.com/marketplace/en-US/product/varest-plugin



# Youtube Data API Keyの取得

Youtube Data APIを使用してYoutube Liveのコメントを取得します。
以下の記事を参考にYoutube Data API v3の有効化とAPI Keyの取得を行います。

https://qiita.com/koki_develop/items/4cd7de3898dae2c33f20

Youtube Data API v3の有効化とAPI Keyの取得が出来たら、Data APIが使用できる状態になります。



# コメント取得に必要なIDについて


コメントを取得するために必要になる3つのIDを調べていきます。

- ```channelId```：```videoId```を取得するために必要
- ```videoId```　：```livechatId```を取得するために必要
- ```livechatId```：配信のコメント等の情報を取得するために必要


はじめにAPIリファレンスを参考に必要なリクエストを書き、次にUEのVaRestでどのように実装するかを書いていきます。

Live Streaming APIのリファレンス

https://developers.google.com/youtube/v3/live/docs


## ```channelId```の取得

自分の```channelId```は以下のページの通りに調べることが出来ます。

https://support.google.com/youtube/answer/3250431?hl=ja

自分以外の```channelId```が知りたい場合は以下の記事が参考になると思います。
しかし、他人の配信の情報を取得したい場合は、後述する配信のURLから```videoId```を取得する方法の方が楽に出来ます。

https://diy-programming.site/youtube/custom-url-channel-id/


## ```videoId```の取得

次に```channelId```から現在行われているライブ配信の```videoId```を調べます。


リクエストURLは次のようになります。```********```のところに```channelId```とAPI Keyを入れます。

```
https://www.googleapis.com/youtube/v3/search?eventType=live&part=id&channelId=********&type=video&key=********
```
このURLをGETメソッド、application/jsonでリクエストを送信します。


レスポンスのJsonは次のような形式で帰ってきます。

```json:
{
  "kind": "youtube#searchListResponse",
  "etag": etag,
  "nextPageToken": string,
  "prevPageToken": string,
  "pageInfo": {
    "totalResults": integer,
    "resultsPerPage": integer
  },
  "items": [
    検索リソース
  ]
}
```
参考ページ https://developers.google.com/youtube/v3/docs/search/list?hl=ja

上記Jsonのitemsの配列にリクエストした内容が入っており、videoIdは```items[0].id.videoId```で取得できます。


BPで書くとこのようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558809/4b5572d2-cd03-df2d-3aba-6e6a4025cdea.png)
#### 配信URLから```videoId```の取得
また、限定公開のLiveだと取得できない？ようなので、その場合はライブ配信ページのURLの最後の部分をコピーします。

```https://www.youtube.com/watch?v=*********```
上のURLの```*********```の部分が```videoId```になります。

この方法では```channelId```が不要です。

## ```livechatId```の取得

次に```videoId```から```liveChatId```を調べます。

リクエストURLは次のようになります。

```
https://www.googleapis.com/youtube/v3/videos?part=liveStreamingDetails&id=**********&key=************
```

先ほどと同じように帰ってきたJsonのitemsにリクエストした内容が入っています。
```livechatId```は```items[0].liveStreamingDetails.activeLiveChatId```で取得できます。

BPで書くとこのようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558809/b3911fa3-7c5f-e718-88fa-4602116e3d4f.png)

## 配信のチャット情報

ようやく```liveChatId```がわかったのでこれでコメントの取得が出来ます。

コメント取得のリクエストURLは次のようになります。

```
https://youtube.googleapis.com/youtube/v3/liveChat/messages?liveChatId=*******&part=snippet,authorDetails&key=**********
```

Jsonのitemsから```snippet.textMessageDetails.messageText```でコメントが取得できます。

BPで書くとこのようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558809/69107c24-8f3c-f015-204f-01e5225e8a2e.png)
また、コメント以外にも様々な情報を取得することが出来ます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558809/5701d354-fead-ae14-af47-0abde49ae2d9.png)
コメントをしたユーザー名を取得
```authorDetails.displayName```

ユーザーがメンバーシップか判定
```snippet.newSponsorDetails.memberLevelName```

スーパーチャットの判定
```snippet.type```

スパチャ額
```snippet.superChatDetails.amountDisplayString```


など色々情報が取得できるので、スパチャ額や、特定のユーザー、メンバーシップの有無によってリアクションを変えることも可能です。

詳細についてはAPIのリファレンスを確認してください。

https://developers.google.com/youtube/v3/live/docs/liveChatMessages/list


## 最新コメントのみを取得する

上記のやり方では毎回コメントの履歴がたくさん(デフォルトだと最大500件)読み込まれてしまいます。
そのため古いコメントは無視するような処理を追加します。
コメントが打たれた時間はitemsの```snippet.publishedAt```で [ISO 8601](https://www.w3.org/TR/NOTE-datetime)の形式で取得できます。
取得したこの時間と最後に打たれたコメントの時間を比較して、新しいものだけ取得するようにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558809/1b0d84a8-e31c-774d-26f7-5c058bfecee7.png)



## コメントに遅延をつける
コメントの更新と更新の間に追加されたコメントは同じタイミングで取得されてしまうので、前の更新からコメントが追加された時間分遅らせます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558809/59dedbf0-7a27-9200-ff7f-def5262d39c1.png)
更新したタイミングの時間とコメントが打たれた時間の差分だけ遅延させるようにします。
![youtube_api.drawio (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558809/3502868a-5476-97b0-f1e7-d1a518dbc193.png)
差分の計算ですが、UEのバグでDate timeの引き算ができないようなので、Timespanに変換して行いました。

https://forums.unrealengine.com/t/having-troubles-with-datetime-in-ue5/502649

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558809/5297707e-42ba-306b-86f9-ef56b8ecc6f7.png)
## コメントを降らせる
降らせなくても良いです。
あくまでも取得したコメントを使用して、なにかリアクションできるという一例なのであまり丁寧に説明はしません。

コメントを更新したタイミングで、アクターを生成して、文字列と遅延させる秒数の情報を渡しています。
生成時に適当なエフェクトを出して、適当なスタティックメッシュのsimulate physicsを有効にして、文字表示するwidget componentをアタッチしています。

適当なスタティックメッシュのVisibleはFalseです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558809/b067ba2b-b898-d80b-176f-9ca47e3b1cd6.png)


詳細は[サンプルプロジェクト](https://github.com/yeczrtu/youtube_data_api__ue_sample)を見てください。

## Queries per day
このYouTube Data APIは無制限に使えるわけでななく、１日に使える上限が決まっています。

使用できる上限は[Cloud console](https://code.google.com/apis/console?hl=ja)の [Quotas] ペインで確認できます。
デフォルトでは10,000が上限です。


更新頻度が高いほどすぐなくなり、上記の処理を1秒ごとに更新していると1時間もかからずなくなってしまします。
長時間使用するのであれば、上限を増やすか、更新頻度を下げるかしましょう。

## おまけ UEからコメントを追加
最初に貼った動画中にUEからコメントを追加しています。

これをするためにはOAuth 2.0 認証でアクセスが必須になります。

Youtube Data APIの認証方式は以下の２つがあり、これまではAPI Keyでアクセスしていました。

- API Keyでアクセス
- OAuth 2.0 認証でアクセス

API Keyでアクセスする場合、配信にAPIを使用してコメントを追加する場合などの一部の機能が使用できません。
OAuth 2.0 認証に必要なアクセストークンの取得には、かなり面倒な手順を踏まないと出来ないのでやり方は割愛します。([参考](https://dev.classmethod.jp/articles/oauth2-youtube-data-api/))

アクセストークンが必要なこと以外はこれまでと同じです。
コメント追加のリクエストURLです。
```
curl --request POST \
  'https://youtube.googleapis.com/youtube/v3/liveChat/messages?part=snippet&key=[YOUR_API_KEY]' \
  --header 'Authorization: Bearer [YOUR_ACCESS_TOKEN]' \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --data '{"snippet":{"liveChatId":"YOUR_LIVE_CHAT_ID","type":"textMessageEvent","textMessageDetails":{"messageText":"Your cool text message goes here!"}}}' \
  --compressed

```
APIリファレンス https://developers.google.com/youtube/v3/live/docs/liveChatMessages/insert?apix=true

次のようにBPでheaderを追加することが出来ます。また、GETではなくPOSTメソッドであることにも注意してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558809/dcbd1152-071c-406b-05bc-aff1013a6453.png)
上の画像の続きです。POSTなのでリクエストの中身（この場合はコメントする文字列）を作る必要があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558809/f57df8a0-2c44-8fe5-f622-796b686d2910.png)
BPでJsonを扱うとかなり煩雑になってしまうので、FastAPIなどでプロキシサーバーを作りたくなります。

UIからの入力など詳細については[サンプルプロジェクト](https://github.com/yeczrtu/youtube_data_api__ue_sample)を参考にしてもらえたらと思います。

# 参考サイト

コメント取得のリクエストURL

https://gist.github.com/yuta0801/2e3cd3581f078d4a0f68ff3e3953c513

１日に使えるAPIの上限について

https://masaki-blog.net/youtube-data-api-quotas#:~:text=%E3%81%A8%E6%80%9D%E3%81%84%E3%81%BE%E3%81%99%E3%80%82-,1%E6%97%A5%E3%81%AB%E4%BD%BF%E3%81%88%E3%82%8B%E3%82%AF%E3%82%A9%E3%83%BC%E3%82%BF%E3%81%AE%E9%87%8F%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6,%E3%81%AF10%2C000%E3%81%AB%E3%81%AA%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82

Youtube Data API のOAuth 2.0 認証

https://dev.classmethod.jp/articles/oauth2-youtube-data-api/