NTTドコモR&Dの技術ブログです。

Unreal Engineで始めるリッチなストリーマ活動

この記事で達成すること

  • Unreal EngineでYoutube ライブ配信のコメントをリアルタイムに取得できること
  • Unreal EngineでWindowsのアプリケーションをキャプチャ・表示できること

コメントの取得とログ表示

検証環境

  • Windows 11(64bit,i9-10980HK,メモリ64GB,RTX 3080 Laptop)
  • Unreal Engine 5.0.3(以下、UE)
  • Python 3.9

事前準備

1. Youtubeのライブ配信権限の申請とAPIキーの準備

以下のページを参考に実施してください ※最大24時間かかります、24時間後にまた来てください support.google.com

APIキーの取得はこちらが詳しいです qiita.com

2. Unreal Engineのインストール(5.0.3)

Unreal Engine(今回は5.0.3)をインストールしてください。(詳細は下記を参照)

docs.unrealengine.com

3. 配信ソフトのインストール(Streamlabs Desktop)

配信にはOBSやSteamlabs Desktopを使います。既にインストール済みの方や、とりあえず後でもいいや、という方は読み飛ばしても大丈夫です。

なお、Streamlabs Desktop自体にもコメント取得機能がありますが、今回は使いません。

vip-jikkyo.net

コメント取得から配信するまでの流れ

今回は以下の流れでキャプチャ→コメント取得→配信まで進めていきます。

  1. UEで配信したいアプリケーションウィンドウをキャプチャして3D空間に描画
  2. Pythonでライブ配信へのコメント取得
  3. PythonからUEへコメントを送信・描画
  4. UEアプリをStreamlabs(やOBS)でキャプチャ、Youtubeへ配信

実装

0.UEでプロジェクト作成

まずはEpic Launcherの上部ライブラリからインストールしたUE5.0.3を起動し、プロジェクトブラウザからサードパーソンプロジェクトを作成します。

UE5.0.3を起動する
左ペインでゲームを選択、サードパーソンを選び、名前を決めて作成

以下のような画面が表示されれば準備完了です。これ以降、UE側はこのプロジェクトを使用します。

作成されたサードパーソンプロジェクト

1.UEでウィンドウキャプチャ・描画

キャプチャ用UEプラグイン導入

ゲームなどのアプリケーションの画面をキャプチャするために、WindowCapture2DというUE用プラグインを使います。マーケットにもこのプラグインはありますが、UE5.0以降に非対応*1でインストールができません。そのため、GitHubから直接プラグインをダウンロードして利用します。以下にアクセス後、後に示す手順にてPluginを直接プロジェクトへコピーしてください。

github.com

  1. 上記ページのCode>Download ZIPからデータをダウンロード、解凍
  2. UEプロジェクトのルートフォルダをエクスプローラで開き、「Plugins」フォルダを作成
  3. GitHubからダウンロードしたデータ内のPluginフォルダの中身の「WindowCapture2D」フォルダを、さっき作成した「Plugins」フォルダ内へ移動
  4. プラグインのリビルドを促すダイアログが出るので、はいを選択(出ない場合はUEプロジェクトを起動してみたり、こちらを参考にVisual Studioをインストールして再度試してください)
  5. プロジェクトの編集>プラグインでプラグインブラウザを開き、インストール済みのプラグインにWindowCapture2Dが有りチェックされていればOK

CodeからDownload ZIP
All>コンテンツフォルダにPluginsフォルダを新規作成
Pluginsフォルダをエクスプローラで開く
ダウンロードしたプラグインのWindowCapture2DをUEプロジェクトのPluginsフォルダへコピー
Rebuildを促すダイアログが出るので「はい」を選択する。(出ない時はVSをインストール)
変更が検出されるので、インポートする
プラグインブラウザからWindowCapture2Dを探して、チェックがついてたらOK
以上でキャプチャ用プラグインの導入ができました。

ウィンドウキャプチャ用アクタの使い方および設定方法

ここからはWindowCapture2Dプラグインの使い方となるので、下記の開発者のクイックスタートを見てください。

WindowCapture2D quick start - YouTube

設定が完了して動作させると以下のような表示になります。 今回はMetaMe*2のウェブページを表示したEdgeをキャプチャしてみました。

Edgeをキャプチャして表示

UEが非アクティブでも処理落ちしないように設定

このままだとゲームをするためのウィンドウをアクティブ化した際にUE側が処理落ちしてしまい、配信・ゲームどころではありません。

これを回避する設定は簡単で、エディタの環境設定から「CPU」と検索して出てくる「エディタのパフォーマンス」設定のチェックを外すのみです。

非アクティブ時に処理を低減させない設定

2. Unreal Engine上でYoutubeライブのコメントを表示する

以下のような構成にしたいと思います

  1. Youtubeのライブ配信のコメントを取得するPythonサーバを立てる
  2. UEアプリで特定のキーを押すと、Pythonサーバからコメントを受け取りログ出力する

まず、1のPythonプログラムは以下のようなものを準備します。APIキーは自分のものを記述します。video_idはライブ配信時に都度書き換えます。

import datetime 
import urllib.request
import json
from pytz import timezone 
from websocket_server import WebsocketServer


APIKEY = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' #事前準備にて取得したAPIキーを貼り付け
video_id = 'xxxxxxxxxxxx'  # 配信開始後に設定されるwatch?v=xxxxxxxxのx部分をコピペ

param = {
    'part': 'liveStreamingDetails',
    'id': video_id,
    'key': APIKEY
}

target_url = 'https://www.googleapis.com/youtube/v3/videos?' + (urllib.parse.urlencode(param))
req = urllib.request.Request(target_url)
update_time = datetime.datetime.now(timezone('Asia/Tokyo'))


def new_client(client, server):
    global APIKEY, target_url, req, param, update_time
    print("New client connected and was given id %d" % client['id'])
    server.send_message_to_all("Hey all, a new client has joined us")
    with urllib.request.urlopen(req) as json_ress:
        ress = json.load(json_ress)
        param = {
            'part': 'id,snippet,authorDetails',
            'liveChatId': ress['items'][0]['liveStreamingDetails']['activeLiveChatId'],
            'key': APIKEY
        }
        target_url = 'https://www.googleapis.com/youtube/v3/liveChat/messages?' + (urllib.parse.urlencode(param))
        req = urllib.request.Request(target_url)


def client_left(client, server):
    print("Client(%d) disconnected" % client['id'])


def message_received(client, server, message):
    if message == "get":
        global APIKEY, target_url, req, param, update_time
        server.send_message_to_all("GetComment")

        with urllib.request.urlopen(req) as json_ress:
            ress = json.load(json_ress)
            for res in ress['items']:
                comment_time_str = res['snippet']['publishedAt']
                while len(comment_time_str) < 32:
                    index = comment_time_str.find("+")
                    comment_time_str = comment_time_str[:index] + '0' + comment_time_str[index:]
                comment_time = datetime.datetime.fromisoformat(comment_time_str)
                comment_time = comment_time.astimezone(timezone('Asia/Tokyo'))
                comment = res['authorDetails']['displayName'] + 'さん ' + res['snippet']['displayMessage']
                if update_time > comment_time:  # 取得済みコメントはスキップ
                    continue
                else:
                    update_time = comment_time + datetime.timedelta(microseconds=1)
                send_str = comment_time.strftime('%H:%M') + " " + comment
                print(send_str)
                server.send_message_to_all(send_str)


PORT = 9001
server = WebsocketServer(port=PORT)
server.set_fn_new_client(new_client)
server.set_fn_client_left(client_left)
server.set_fn_message_received(message_received)
server.run_forever()

次に、2のUnrealEngine側の準備をします。

まずはWebSocketのプラグインをインストールします。

BlueprintWebsockectsにチェックを付ける

次にレベルブループリントを下図の様に開き、続いて後述する画像の様にノードを配置します。

レベルブループリントの開き方

レベルブループリントの中身
ブループリントの書き方に関しては詳細は省きますが、チュートリアルや公式ドキュメントを参考にしてください。

ノードを配置する | Unreal Engine ドキュメント

[UE4] Input入門|株式会社ヒストリア

これらUEアプリとPythonサーバの動作としては、ZキーでPythonサーバに接続、Cキーでgetメッセージを送りPythonサーバから最新のコメントを受信してログ出力、Xキーで接続を閉じるという簡単なものになっています。

3. 動作確認

動作確認をしてみましょう。 確認手順は以下のようになります。

  1. Youtubeライブ配信を開始する
  2. VideoID(配信URLのwatch?v=xxxxxxxxのx部分)をコピペし、Pythonサーバを起動する
  3. Unreal Engineのプロジェクトを緑のプレイボタンから実行し、Zキーでサーバに接続する
  4. ライブ配信の方へコメントを書き込み、Cキーで取得してみる
  5. ログにコメントが出力されたらOK
    コメントの取得とログ表示
    あとはこのUEのプレビューをStreamlabs Desktopで配信すれば、Vtuber風の配信ができそうです。 お疲れ様でした。

備考

  • キャプチャ画面の色合いがおかしい場合、UEアプリのアクタのマテリアルを調節してみてください。

参考

*1:この記事を書いたのは実は1年前なのですが、2023年12月19日時点でマーケット版もUE5.0に対応しているようです。そちらも試してみてください。

*2:MetaMeについてはこちら https://note.metame.ne.jp/