UE4 PixelStreamingの手引き（ホスティング編）

※この記事は以下の記事の続きです。良ければ合わせてご覧ください
- [UE4 PixelStreamingの手引き（導入編）](https://qiita.com/T_Sumisaki/items/d526d1fd43041856114c)
- [UE4 PixelStreamingの手引き（UIカスタマイズ編）](https://qiita.com/T_Sumisaki/items/68d37587890f379f0b8e)

※記事作成時点ではEarlyAccessです

この記事を読んでいる方はおそらくすでにローカルネットワーク内でのPixelStreamingに成功しているだろう、と思います
そうなれば次は、インターネット上…つまりクラウド上のサーバに配置したくなりますね

ただ、インターネットを通じてPixelStreamingを行う際には、ある問題が発生します
いわゆる`NAT越え問題`です

ネットワークに関わっている方なら「なるほどね～」と思うことだろうと思います
知らない人は…後で調べてください


# 検証環境
下記記事と同じ
- [UE4 PixelStreamingの手引き（導入編）](https://qiita.com/T_Sumisaki/items/d526d1fd43041856114c)
- [UE4 PixelStreamingの手引き（UIカスタマイズ編）](https://qiita.com/T_Sumisaki/items/68d37587890f379f0b8e)

# 参考リンク
https://docs.unrealengine.com/en-US/Platforms/PixelStreaming/Hosting

# 準備するもの
- AWSアカウント


## サーバー構成
今回はPixelStreaming用とSTUN/TURN用の2つのインスタンスを使用しています
![Untitled.png](https://qiita-image-store.s3.amazonaws.com/0/117589/70675aaa-0a4f-f01e-a0d4-af51b985160c.png)

※セキュリティグループの簡素化のため、互いのインスタンスと操作用のPCの間のトラフィックはすべてAllowにしました
※ご自身のセキュリティポリシーに従って設定してください


## 環境構築（PixelStreaming用）
PixelStreaming用サーバの設定は[導入編](https://qiita.com/T_Sumisaki/items/d526d1fd43041856114c)と同様にしてください

ただし、NVIDIAのドライバが入っていないとUE4のアプリが起動しませんので、下記ドキュメントを参考にしてドライバをインストールする必要があります
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/WindowsGuide/install-nvidia-driver-windows.html


## 環境構築（STUN/TURN用）
STUN/TURNサーバ用のアプリには[coTurn](https://github.com/coturn/coturn)を使用します
設定手順については下記記事が参考になるでしょう

[coTurnでEC2上にTURNサーバを作ってみた](https://qiita.com/okyk/items/2d7db6b148a43bc3b405)

STUN/TURNとしての特別な設定は不要です

## 環境構築（設定ファイル）
SignallingWebServerにSTUN/TURNを使用する旨の設定が必要です

config.jsonを以下のように書き換えてください

```json:config.json
{
	"UseFrontend": false,
	"UseMatchmaker": false,
	"UseHTTPS": false,
	"UseAuthentication": false,
	"LogToFile": true,
	"HomepageFile": "player.htm",
	"AdditionalRoutes": {},
	"peerConnectionOptions": "{\"iceServers\": [{\"urls\": [\"stun:<STUNのPublicIP>:3478\",\"turn:<TURNのPublicIP>:3478\"],\"username\": \"hakobuneworks\",\"credential\": \"********\"}]}"
}
```

peerConnectionOptionsのValueをエスケープしている理由ですが、
Cirrus.jsのプログラム側に少々不具合があるようで、内部でParseしているため`JSON文字列`でないと受け付けない状態になっています
普通にJsonで書きたい方はプログラム側を修正することをおすすめします

```js:cirrus.js
// 120行目付近
	if(typeof config.peerConnectionOptions != 'undefined'){
		// clientConfig.peerConnectionOptions = JSON.parse(config.peerConnectionOptions);
		clientConfig.peerConnectionOptions = config.peerConnectionOptions;
		console.log(`peerConnectionOptions = ${JSON.stringify(clientConfig.peerConnectionOptions)}`);
	}
```

## 実行
後は[導入編](https://qiita.com/T_Sumisaki/items/d526d1fd43041856114c)と同じ手順で実行してください
coTurnの起動も忘れないように

ただ、WebRTCProxyの起動だけは、同梱されている`Start_AWS_WebRTCProxy.bat`を使用するほうが良いかと思います
明確に比較できてはいませんが、通常のStartではうまくつながらない可能性がありそうです

ネットワーク状況によってレイテンシと画質に問題が出ますが、今回の構成ではTURNサーバがボトルネックになると思われるので、その部分をスケールアップすれば改善すると思います

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">AWSのGPUインスタンス上でPixelStreamingが動いた！TURNサーバの性能が低いからレイテンシと画質の劣化がヤバいけど、もっと性能のいいサーバを用意できるなら問題なくなるはず <a href="https://twitter.com/hashtag/UE4?src=hash&amp;ref_src=twsrc%5Etfw">#UE4</a> <a href="https://twitter.com/hashtag/UE4Study?src=hash&amp;ref_src=twsrc%5Etfw">#UE4Study</a> <a href="https://t.co/cANW7FliYo">pic.twitter.com/cANW7FliYo</a></p>&mdash; 墨崎達哉 (@T_Sumisaki) <a href="https://twitter.com/T_Sumisaki/status/1060735754362441728?ref_src=twsrc%5Etfw">2018年11月9日</a></blockquote>


# 考察
ここまで実行できている方であれば、SignallingWebServerに同梱されているbatファイルに、AWSの名前がつくバッチファイルがあることに気がついているかと思います
中身を見てみると、その先はPowerShellスクリプトにつながっており、その内部で先程config.jsonに書いたpeerConnectionOptionsを生成して当てはめるような書き方になっています
STUNのアドレスには、自分のPublicIPを指定しています

これはおそらくこのスクリプト作成時には、PixelStreamingサーバとSTUN/TURNサーバは同一のインスタンスに立ててしまう設定になっていたと考えられます
そうすると、今回僕が作成したような構成で問題になったSTUN/TURNサーバによるボトルネックもある程度合理的に解消できるのでは？と思います

このあたり、サーバの構築に詳しい方であれば解決できるかと思います


# 追記

<blockquote class="twitter-tweet" data-partner="tweetdeck"><p lang="ja" dir="ltr">ちょっと試すだけであれば、STUNとTURNのサーバは <br>Engine/Source/ThirdParty/WebRTC/rev.23789/programs/Win64/VS2017/<br>のものを使うとお手軽そうです<br>自分はWebRTCProxy, SignallingWebServer,STUN,TURN,UE4アプリを全部Windowsサーバに同居させる構成で試して、うまくいってました</p>&mdash; neguse (@neguse) <a href="https://twitter.com/neguse/status/1060837730643402752?ref_src=twsrc%5Etfw">November 9, 2018</a></blockquote>