【UE4】俺、AIになる

# はじめに

こんにちは。
突然ですが、
### VTuber
になりたいんですよね。

![vtuberイラスト.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/873426/a4d938a4-502c-1c67-c445-2f4c5cb33e67.png)

VTuberになって、あわよくば**にじさんじ**に入って、YouTube収入とか**スパチャ**とかで稼ぎつつ、**承認欲求**を満たしたい・・・。

けど、VTuberって
- モデルの用意
- かっこかわいいボイス
- なんかモデル動かす
- カメラキャプチャ？？
- 歌が歌える
- 配信とか時間かかる
- etc....

特にめちゃくちゃ調べたわけじゃないですけど、とても大変そうですよね。
ハードやソフトを揃えるだけじゃなくて本人のスキルも磨かなければなりません。
本当にVTuberの皆様ってすごいんだなと痛感します。

そもそも本職をおろそかにできないので、特にスキルを磨く時間がないんですよね。

となると、やはり
### 全てAIにやらせよう（錯乱）
と思うわけです。

なので、今回は**自分がAIになる記事**になります。

最後には**VTuber第一歩となる動画**も用意しておりますので、よければご覧ください。

#### 共同開発者
@kdr250 
@ko27 
@39yatabis 
@hrkmed 

# 目次
- [はじめに](#はじめに)
- [概要](#概要)
- [AIになる](#aiになる)
    - [構成図](#構成図)
    - [UE4](#ue4)
        - [VaRest](#varest)
        - [Runtime Audio Importer](#runtime-audio-importer)
        - [OVR LipSync](#ovr-lipsync)
        - [META HUMAN](#meta-human)
    - [Azure Text to Speech](#azure-text-to-speech)
- [結果](#結果)
- [おわりに](#おわりに)
- [参考文献](#参考文献)

# 概要
今回も時間がないので、既存のサービスを作っていきます。
使用するサービスは目次にも挙げていますが、下記の通りです。

- **UE4**
- **Azure Text to Speech**
- **OVR LipSync**
- **META HUMAN**

それぞれ細かい説明は後に記述いたします。

**VTuber**第一歩として、今回は
#### 自分が3Dモデルになって、言語を発する
ところを目標としております。

では、早速やっていきましょう。

# AIになる

## 構成図

ざっと使用するサービスの構成図は下記の通りです。

![俺AIになる構成図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/873426/2e98d44c-7b17-354e-5995-b19c4b20456c.png)


ざっくりと流れとしましては下記の通りです

1. **適当なテキストを用意**
1. **APIを用意してテキスト・性別をXML形式に変換**
1. **Text to Speechで音声化**
1. **APIでmp3からBase64エンコードしたwav形式に変換**
1. **音声からOVR Lipsyncを用いて口の動きを再現**
1. **META HUMANで用意した3Dモデル(俺)に読み込ませて、喋らせる**

## UE4
![unrealengine.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/873426/5894e304-cd1e-a801-d9c7-1d796d7b258a.png)

[UE4 公式](https://docs.unrealengine.com/4.27/ja/)

本企画の要です。
3D制作プラットフォームです。主にゲームエンジンとして利用されますが、最近ではノンゲーム分野でも注目を集めています。
今回はこのエンジン上でテキスト入力を検知して、APIにデータを渡したり、METAHUMANにLipSyncを読み込ませたりすることで、俺モデルを作成していきます。

### VaRest
UEでAPIを叩くプラグインです。
今回はバックエンドAPIを叩いて音声を取得するのに使用しています。
テキスト入力を受け取り、バックエンドAPIにリクエストしています。
実際に動かしているBlue Printが下記の通りです。

※**Blue Print**・・・UnrealEngine内でプログラムを作るためのツールみたいなもので、ビジュアルスクリプティングシステムと言う仕組みを採用したツールです。ビジュアルスクリプティングシステムとは、その名の通り視覚的にプログラムを作成する仕組みのことです。
https://tech.pjin.jp/blog/2019/10/23/ue4_blueprint_01/

![スクリーンショット 2022-10-17 12.56.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/873426/3551613c-5051-7587-7f86-76255d2ade8c.png)


### Runtime Audio Importer
アプリ起動中に動的に音声処理するプラグインです。
今回はバックエンドAPIより取得した音声を処理するために使用しています。
実際に動かしている部分のBlue Printが下記の通りです。

![スクリーンショット 2022-10-17 12.55.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/873426/9129bb0b-0ebd-2ef7-acdd-3298c7015f26.png)


### OVR LipSync

[OVR LipSync](https://developer.oculus.com/documentation/unreal/audio-ovrlipsync-unreal/?locale=ja_JP)

Oculusのリップシンク用プラグインです。
今回はMetaHumanをリップシンクさせるために使用しています。
俺モデルの口を動かして、**あたかもそこに俺がいるかのような錯覚を生み出します。**
プラグイン適用させているBlue Printが下記の通りです。

![スクリーンショット 2022-10-17 12.55.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/873426/df9fe480-01cf-b9fd-cc1c-afc7a30c0ed5.png)



### META HUMAN

META HUMANはUEのフレームワークで、フォトリアルな人間キャラクターの3Dモデルを作ることができます。 

つまり**俺の生みの親**であるわけです。 
生成したモデルをUEにインポートすることも可能です。  

MetaHumanにより作られた3Dモデルがこちらです。

![スクリーンショット 2022-10-17 18.36.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/873426/53dc59a3-45b2-b6b6-fabd-baad6f2081b5.png)

のちに掲載する動画にはPCへの負荷の都合上、左下のおじさんを使用しています。
![スクリーンショット 2022-10-17 19.04.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/873426/71187dc0-462c-93f5-5a56-ec004ff7b1fc.png)


## Azure Text to Speech

[Text to Speech REST APIドキュメント](https://learn.microsoft.com/ja-jp/azure/cognitive-services/speech-service/rest-text-to-speech?tabs=streaming)

テキストから音声データへの変換は Microsoft Azure の **Text to Speech API** を利用しました。
アカウント登録し、トークンを発行して以下のようなリクエストを送ると、**レスポンスで音声データ**を返してくれます。
テキストや声の種類などを**独自の SSML という形式**で指定することができます。
 ```zsh
curl --location --request POST "https://${SPEECH_REGION}.tts.speech.microsoft.com/cognitiveservices/v1" \
--header "Ocp-Apim-Subscription-Key: ${SPEECH_KEY}" \
--header 'Content-Type: application/ssml+xml' \
--header 'X-Microsoft-OutputFormat: audio-16khz-128kbitrate-mono-mp3' \
--header 'User-Agent: curl' \
--data-raw '<speak version='\''1.0'\'' xml:lang='\''ja-JP'\''>
    <voice xml:lang='\''ja-JP'\'' xml:gender='\''Female'\'' name='\''ja-JP-NanamiNeural'\''>
        日本語の音声を話すテストです。
    </voice>
</speak>'
```

今回はこれを UE から呼び出さないといけなかったため、中継サーバーを立てて UE 側の処理の負担を減らすようにしました。
**UE の VaRest は API のレスポンスを String でしか受け取れないため、Text to Speech API のレスポンスを中継サーバーで base64 エンコード**して返しています。
中継サーバーは適当に **Pytho**n で書きました。

参考までに以下

```python
from base64 import b64encode
import os
from fastapi import FastAPI, Response
import requests
​
URL = os.getenv(“URL”)  # Azure のリクエストURL
SPEECH_KEY = os.getenv(“SPEECH_KEY”)  # Azure のトークン
​
app = FastAPI()

@app.get("/tts")
def main(response: Response, gender: str, text: str):
    headers = {
        "Ocp-Apim-Subscription-Key": SPEECH_KEY,
        "Content-Type": "application/ssml+xml",
        "X-Microsoft-OutputFormat": "riff-16khz-16bit-mono-pcm"
    }
    payload = f"<speak version='1.0' xml:lang='ja-JP'>\
    <voice xml:lang='ja-JP' xml:gender='{gender}' name='{'ja-JP-KeitaNeural' if gender == 'Male' else 'ja-JP-NanamiNeural'}'>\
        {text}\
    </voice>\
</speak>"
    r = requests.post(URL, headers=headers, data=payload.encode("utf-8"))
    response.headers["Content-Type"] = "text/plain"
    return b64encode(r.content)
```

# 結果

ここまでで、テキストを入力しその言葉を発する俺モデルが完成しました。
実際に動いている動画も作成致しましたのでご覧ください。

https://twitter.com/miyaengineer/status/1581958448950177792?s=20&t=b_PZVAZZ5HjebXZG22cT1Q

# おわりに

#### VTuberへの道は長い

# 参考文献
- UEについて
    - [UE公式](https://www.unrealengine.com/ja/)
    - [UE4公式ドキュメント](https://docs.unrealengine.com/4.27/ja/)
    - [Epic Developer Community](https://dev.epicgames.com/community/?application=unreal_engine)
    - [VaRest -　GitHub](https://github.com/ufna/VaRest)
    - [Runtime Audio Importer - GitHub](https://github.com/gtreshchev/RuntimeAudioImporter)

- Azure Text to Speechについて
    - [Text to Speech](https://learn.microsoft.com/ja-jp/azure/cognitive-services/speech-service/rest-text-to-speech?tabs=streaming)

- META HUMANについて
    - [META HUMAN公式](https://www.unrealengine.com/ja/metahuman)

- OVR Lipsyncについて
    - [OVR Lipsync公式](https://developer.oculus.com/documentation/unreal/audio-ovrlipsync-unreal/?locale=ja_JP)
    - [Oculus社のリップシンクライブラリ「Oculus LipSync ( OVRLipSync )」をUE4で使う方法について その1 (サンプル解説編)](https://pafuhana1213.hatenablog.com/entry/2018/11/17/002935)
    - [Tutorial Part 2: Lip sync, text to speech and Unreal Engine | Prototype | OVR Oculus & Replica |](https://www.youtube.com/watch?v=SBMzammddHw)
    - [UE4OVRLipSyncCookFrameSequence - GitHub](https://github.com/IlgarLunin/UE4OVRLipSyncCookFrameSequence)