Pixel Streamingを利用して外部から自宅PCのUEエディターにアクセスしよう

この記事は、PixelStreamingのプラグインを使用して、自宅PCを活用しつつ、Editorに外部からアクセスできるようにしてみようという記事です。

まず大前提として、単にUEエディターを外出先からアクセスするなら[Chromeリモートデスクトップ](https://remotedesktop.google.com/?hl=ja)等を活用、エディターを誰かと共同で触るのであれば[マルチユーザー編集](https://dev.epicgames.com/documentation/ja-jp/unreal-engine/getting-started-with-multi-user-editing-in-unreal-engine)を利用すれば良さそうなのかなと考えています。

そのため、この記事ではUEが入っていないPCなどを持った方に、自分のChromeの認証情報などは伝えずに自分のエディタを見てもらい、実際に触ってもらいたいなど何らかの理由で上記技術が使用できないときに活用できるかも...？といったぐらい気軽な気持ちで見ていただければと思います。
一応、今回の方法を使用すれば、自宅PCからUE製アプリケーションをPixelStreamingで配信することも可能になるかと思います。

## 検証環境
- OS: Windows 10 Home
- UEバージョン: 5.4

## 注意事項
ネットワーク環境などが原因で動かない可能性がありますのでご了承ください。

## PixelStreamingとは
UnrealEngine製のアプリケーションをWebブラウザ上で体験できるようにするための技術です。
これにより、ユーザーは高スペックなデバイスが無くても、インストール不要で高品質なコンテンツを体験することができます。
PixelStreamingを触ったことがある方はお気づきだと思いますが、プラグインの機能にエディタをstreamingする機能が備え付けられています。
今回は、その機能を利用してエディタをWebブラウザ上で体験してみようと思います。
※ PixelStreamingのもっと詳しい内容については、[こちらのドキュメント](https://dev.epicgames.com/documentation/ja-jp/unreal-engine/pixel-streaming-in-unreal-engine)を参照してください。

## まずは自分のPC内だけで試してみよう
前述の通り、PixelStreamingのプラグインには、エディタをstreamingする機能が備え付けられているため、最初にそれを使って、自分のPC内で完結する状態でどのような感じになるか試してみましょう！
まずは、適当なプロジェクトを作成しPixelStreamingを導入してみます。
Edit > Plugins > Pixel Streamingをオンにし、再起動してください。
![スクリーンショット 2024-12-22 233412.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581290/ffaf609d-ee95-7e82-e0da-cb1f9003a064.png)

次に、エディタ上部にあるPixel Streamingから「Launch Signalling Server」と「Stream Full Editor」をオンにしてください。
![スクリーンショット 2024-12-22 233512.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581290/3d7a448b-1107-547a-a7dc-097e0a8a24b6.png)

すると以下のような状態になると思います。
![スクリーンショット 2024-12-22 233529.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581290/c5b6c786-6489-d6ee-583a-d0731456437e.png)

この状態のままWebブラウザのURL欄に「 127.0.0.1:80 」と記述し、アクセスすると「CLICK TO START」という表示がなされるため、クリックしていただくと実際にブラウザ上でエディタを触ることができます。

<img width=100%><img width=100% src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581290/5486519f-459f-9b70-b03a-ea67a989da53.gif">

無事動作確認出来ましたら、「Stop Signalling Server」と「Stop Streaming」を押し、Streamingをストップします。
URLに打ち込んだ127.0.0.1とは、ローカルループバックアドレスと呼ばれ、自分自身を表す特別なアドレスとなっています。
このため、現時点では外出先など同一ネットワーク外からではアクセスできないことから、これをアクセス可能にしていきます。

## 外出先からアクセス可能にするために必要なこと
このPixel Streamingですが、Webブラウザへの映像データや操作内容を送受信するための仕組みとしてWebRTC技術が用いられています。

WebRTCとは、P2P方式を用いて端末同士がデータのやり取りをリアルタイムで行うことができる通信技術のことです。
人同士がやり取りを行うためにお互い住所などの情報が必要などと同じように、端末同士が直接通信するためにもお互いの情報を知る必要があります。

そして、WebRTCでは、シグナリングサーバーと呼ばれるサーバーを介してお互いの情報をやり取りしています。
PC内で完結させたときに「Launch Signalling Server」というボタンをクリックしていただきましたが、Pixel Streamingのプラグインには、あらかじめプラグインの中に用意されたシグナリングサーバーを起動させていたわけですね。

このことから、今回のパターンでいえば、あらかじめ用意されているシグナリングサーバーを外部からアクセスできる状態にすれば、うまくいくような気がしてきました。

ただ、もう一つ困ったことがあります。
「127.0.0.1:80」とアクセスした際にWebページが表示されましたが、現時点ではこのページにも外部からアクセスできません。
そのため、シグナリングサーバーに加えてWebページ自体も公開する必要があるということですね。

※ WebRTCにおいて、必要となるサーバーは実は他にもあります。この記事では直接関係していないため、詳しい説明は省きますが、気になる方は[こちらの入門サイトなど](https://jp.vcube.com/sdk/blog/webrtc-general-server-configuration-signaling-turn-sfu.html)を見ていただければと思います。

## Cloudflare & ドメイン設定
今回、自宅PCに外出先からWebブラウザ経由でアクセスする際に[Cloudflare](https://www.cloudflare.com/ja-jp/)というサービスを利用したいと思います。
Cloudflareとは、セキュリティやWebページのパフォーマンスを強化などしてくれるような機能を提供しているクラウドサービスになります。
今回、このサービスのうち、[Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/)というサービスを使用していきます。

### Cloudflare Tunnelとは
自宅のWebサーバー（自宅のPC）に外からアクセスできるようにするサービスです。
このサービス、実は使用するだけなら無料で使用ができるため、レンタルサーバーを用意しなくても手軽にWebページを公開したりできるものとなっています。

### Cloudflareへの登録
まずは、Cloudflareに登録していきましょう。
https://www.cloudflare.com/ja-jp/

普通のサービスと同じように登録する形になりますが、こちらの [Cloudflareアカウント作成してみる！](https://zenn.dev/east_takumi/articles/240121-get_started_with_cloudflare)という記事がわかりやすいのではないでしょうか。

登録が済みましたら、以下の画面になっているかと思います。
![スクリーンショット 2024-12-19 050317.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581290/a2def255-0c2e-ec80-2645-ca4492962697.png)

### ドメインの取得
表示されたCloudflareのページをよく見るとドメインというものが必要なようです。
ドメインとは、インターネット上の住所みたいなものなのですが、これを自分で取得する必要があります。
様々なサービスがありますが、今回私は[お名前.com](https://www.onamae.com/campaign/lp/customize-domain/011/?utm_source=Google&utm_medium=paidsearch&banner_id=726_kwt_domain_bigdomain-main_rsa_009&waad=crG9EdJV)を利用してドメインを取得しました。

お名前.comの例ですが、トップページにある検索欄へ好きな文字列を入力し検索するか、.comや.netのボタンをクリックした後に表示されるページで、同じように検索することで取得できるドメインが表示されます。
その後は、ページに従い契約することでドメインを取得することができます！
なお、場合によっては少し時間がかかる場合があります。

![スクリーンショット 2024-12-23 031728.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581290/27d0d727-725e-0baa-3865-15041bbae3dd.png)

※ 2024/12/22現在では、.comや.netドメインは初期費用無料ですので、検証としてやってみたい方はこちらを選ばれるのが良いのではないでしょうか？


※ 注意事項として、初年度費用は0円のものがありますが、**次年度以降更新料がかかる場合があります**。また、サーバー初月無料特典が付いてくる場合もありますが、こちらも2ヶ月目以降は費用が掛かってしまうため注意が必要です。サーバーに関しては、特に不要であれば**契約しなくても今回問題ありません**。

### Cloudflareにドメインを登録
さて、無事ドメインを取得することができましたらCLoudflareに登録していきます。
1. 「既存ドメインを入力」の欄に先ほど取得したドメインを入力
2. DNSレコードのクイックスキャンを選択（デフォルトのはずです）
3. 続行

![スクリーンショット 2024-12-19 050317.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581290/910a63f2-f783-a44c-12c4-a2c0aeb7182a.png)

続いてプラン選択画面になりますので、Freeプランが選択されていることを確認し、続行してください。

![スクリーンショット 2024-12-19 050918.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581290/df203d19-f3e3-3d0d-86f9-eabaf27f72f9.png)

続いてDNSレコードを確認する画面になりますが、基本的にはこのままで問題ないと思われますので、画面下部の「次へ」ボタンをクリックしてください。

![スクリーンショット 2024-12-19 051734.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581290/424846ba-ae45-30ae-1736-46292d92c2a9.png)

この後、以下のような画面になると思います。
2つコピーをするボタンが表示されていますが、こちらをそれぞれ契約したサービスに登録する必要がありますので、一度登録したドメイン取得サービスに戻ってください。
![スクリーンショット 2024-12-19 123527.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581290/c0b2dd8f-9fb4-38ef-0a90-edde9c572a0e.png)

お名前.comの場合は、ログイン後 「ネームサーバー設定 > ネームサーバーの変更」ドメインを選択し、「その他のサービス」欄にある入力欄へコピーしたものをそれぞれペーストして保存してください。
![スクリーンショット 2024-12-23 035003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581290/afaf0710-70f1-aba3-fff6-b94cd450ed52.png)

Cloudflareへ戻った後、一度サイドバーからアカウントホームへ戻っていただき、ステータスが「アクティブ」
になっているかどうかを確認してください。
なお、ちょっと時間がかかるかもしれません。
私の場合は、少し時間をおいてからリロードをすることでアクティブと表示されるようになりました。
![スクリーンショット 2024-12-19 124227.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581290/e986d23a-0e1f-669b-e673-0731e534b6f3.png)


### Cloudflare Tunnelの作成
さて、ようやく本題のCloudflare Tunnelの設定をしていきます。
サイドバーのZero Trustをクリックし、ネットワーク > Tunnelsをクリックすることで以下のTunnel作成画面へ遷移してください。
なお、この時「Go Home」というようなエラーが表示された場合、リロードすることが私は解決できました。
また、もしかしたらZero Trustへの登録が必要のような画面へ遷移する場合もあるかもしれません。
その場合は、Freeプランに相当するものを選択し、登録してください。
このタイミングでは登録しませんでしたが、不意にページを離れてしまい再度ログインした際、Zero Trustへの登録を促されましたのでどこかのタイミングで登録が必要になるかと思います。

![スクリーンショット 2024-12-19 135834.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581290/6f3623bc-acaa-4d26-5ab8-820f680be506.png)

トンネルの追加ボタンから遷移した先では、Cloudflareを選択してください。

![スクリーンショット 2024-12-19 143223.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581290/d70c34a5-2d94-b7c2-21fd-0d741292b6f0.png)

Cloudflare選択後、Tunnel名を入力する画面が表示されるため、Tunnel名を入力してください。

その後、Cloudflareと自宅PCを繋ぐための設定をどうするか聞かれる画面へ遷移します。
どのような方法でも良いのですが、今回私はWindowsを選択しました。
その場合、画面にも表示されていますが
1. CLoudflareとの接続をするためのアプリケーションをダウンロード
2. 1. を起動
3. コマンドプロンプトを「管理者権限」で起動
4. ページに記載されているコマンドをコピー

![スクリーンショット 2024-12-19 151402.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581290/c5e763d0-7d4d-4079-324c-006e858f33f4.png)

※ 作業時はあまり気にならなかったのですが、日本語と英語のスクショが入り乱れてますね...（スミマセン

これらがうまくいくと画面下部に「Connected」が表示されるはずです。

![スクリーンショット 2024-12-19 151921.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581290/9cbb40c8-f083-3a6d-174b-4d5745e9613c.png)


### Tunnelのルーティング作成
Connectedが表示された画面の下部にある「次へ」ボタンをクリックしてください。
誤って別のページへ遷移してしまった場合は、Zero Trustのネットワーク > TunnelsからTunnel一覧画面へ遷移し、該当のTunnelの設定ページへ遷移し、パブリックホスト名のタブ > 「パブリックホスト名を追加する」ボタンをクリックしてください。

![スクリーンショット 2024-12-23 042800.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581290/11682ed6-9d83-6a9a-a2ae-a86b91527a2d.png)

私は誤って別ページへ遷移してしまったため、「次へ」ボタンをクリックした方と画面が少し違うかもしれませんが、入力内容はほぼ同じだと思います。

![スクリーンショット 2024-12-23 043630.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581290/75c05877-6196-a26c-b220-21217febc472.png)

ここでは、Signalling ServerのものとWebページ表示用の以下の2つ分追加することとなります。
- Signalling Server用
    - サブドメイン: signalling（基本的には何でも良いですが、わかりやすいと後々楽です）
    - ドメイン: 今回契約したドメイン
    - タイプ: tcp
    - URL: localhost:8888
- Webページ表示用
    - サブドメイン: frontend（基本的には何でも良いですが、わかりやすいと後々楽です）
    - ドメイン: 今回契約したドメイン
    - タイプ: http
    - URL: localhost

![スクリーンショット 2024-12-23 044012.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581290/eae1d746-fbea-028c-7711-5145dae58313.png)

追加後は、Tunnel一覧画面から遷移した設定画面のページですが、上記のようになっているかと思います。


## サーバー・Webページ公開準備
さて、Cloudflareでの設定が終了したため後は
1. PC上でサーバーの起動
2. エディタのstream開始

を行います。

### サーバー起動
最初のPC内での動作確認時は、Editorからサーバーを立ち上げました。
ただ、これだとログの確認が少し面倒なため以下の手順でサーバーを起動させることとします。

1. 使用しているエンジンが格納されているフォルダからEngine > Plugins > Media > PixelStreaming > Resources内に格納されているWebServersをデスクトップなどへコピー
    - もし存在しない場合、[PixelStreaing Infrastructure](https://github.com/EpicGamesExt/PixelStreamingInfrastructure)からコードをダウンロードする必要があるかもしれません。こちらに関しては後日追記予定です。
2. コピーしたWebServers > SignallingWebServer > cirrus.jsをエディタで開く
3. 以下を変更
    ```js
    // defaultConfigの内容修正
    const defaultConfig = {
      UseFrontend: false,
      UseMatchmaker: false,
      UseHTTPS: true, // falseからtrueへ変更
      ～
      PublicIp: 'signalling.${契約したドメイン}', // localhostから変更。SignallingサーバーとしてCLoudflareに設定したドメインを設定
      ～
    }
    
    // clientConfigの修正
    var clientConfig = { type: 'config', peerConnectionOptions: {} };
    // 以下を追加
    clientConfig.peerConnectionOptions = {
      iceServers: [
        // P2Pに必要なサーバーの明示的な設定
        { urls: 'stun:stun.l.google.com:19302' },
        { urls: 'stun:stun1.l.google.com:19302' },
        { urls: 'stun:stun2.l.google.com:19302' },
        { urls: 'stun:stun3.l.google.com:19302' },
      ],
    };
    ```
4. 変更を保存し、```SignallingWebServer > platform_scripts > cmd > setup.bat```を実行
    - これはwindowsの場合です。Linuxやmacの場合は、bashフォルダにあるsetup.shを実行してください
5. 実行完了後、同じフォルダにある```run_local.bat```を実行してください
    - 同じくLinuxやmacの場合は、bashフォルダにあるrun_local.shを実行してください
6. コマンドプロンプトが立ち上がりっぱなしになり、ログが出ていれば立ち上げ成功です

### UEの配信設定
最後にUE側の配信設定を行います。
「Use Remote Signalling Server」にチェックを入れ、Remote Signalling Server URlには、wss://signalling.${契約したドメイン} を入力してください。
その後、「Stream Full Editor」をクリックし、streamを開始してください。
![スクリーンショット 2024-12-23 051444.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581290/a46e4160-c21d-64b1-a590-fbdcc8a238ea.png)

### 動作確認
ここまでの設定がうまくいっていた場合、同一ネットワーク以外からhttps://frontend.${契約したドメイン} へアクセスすれば、確認できるようになっているはずです！
私の場合は、スマホ（WiFiオフ）や別PCをスマホのテザリングを利用してアクセスするなど行いました。
とりあえず動作確認が成功しましたら、コマンドプロンプトを閉じ、「Stop Streaming」をしましょう。

## 後始末
不意に作業内容がネット上に流れてしまうことを防ぐために、私は以下のような後始末をしておきました。
1. 今回作成したCloudflare Tunnelを削除
2. しばらく使わないので、windowsの設定 > アプリ > cloudflared からアンインストールを選択
  - ファイルの置き場がすぐわかる方は、[こちらのトピック](https://community.cloudflare.com/t/delete-cloudflared/298625/4)にある方法でも良いかもしれません


## 最低限のセキュリティについて
今回、URLを知っていればだれでもアクセスできるため、本当に簡易的ですが最低限のセキュリティとしてBasic認証というものを導入してみます。
cirrus.jsをエディタなどで開き、以下を追加してください。
```js
// 今回は動作確認程度ですので、わかりやすいように先のコード修正でも出てきたdefaultConfigの直前に記述

const BASIC_USER_NAME = "好きなユーザー名を記述"
const BASIC_PASSWORD = "好きなパスワードを記述"
const basicAuthMiddleware = (config) => {
    return (req, res, next) => {
        // 認証ヘッダーの取得
        const authHeader = req.headers.authorization;
        
        if (!authHeader) {
            // 認証ヘッダーがない場合は認証を要求
            res.setHeader('WWW-Authenticate', 'Basic realm="Pixel Streaming"');
            res.statusCode = 401;
            res.end('Unauthorized');
            return;
        }

        // Basic認証のデコード
        try {
            const base64Credentials = authHeader.split(' ')[1];
            const credentials = Buffer.from(base64Credentials, 'base64').toString('utf8');
            const [username, password] = credentials.split(':');

            if (username === BASIC_USER_NAME && 
                password === BASIC_PASSWORD) {
                return next();
            }
        } catch (e) {
            console.error('Basic auth decode error:', e);
        }

        // 認証失敗
        res.setHeader('WWW-Authenticate', 'Basic realm="Pixel Streaming"');
        res.statusCode = 401;
        res.end('Unauthorized');
    };
};
app.use(basicAuthMiddleware());

const defaultConfig = {
~
}

```

これを記述後、再度run_local.batやrun_local.shを実行しアクセスすると以下のように認証を求められるはずです。
![スクリーンショット 2024-12-23 5.40.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581290/3e11bdde-b77c-75bc-5ffe-278e6a8365af.png)

---
参考記事:
[Cloudflare Tunnel を使って自宅をデータセンターみたいにする](https://zenn.dev/takajun/articles/fbd783e459c722)
[Windows における Cloudflared トラブルシューティング](https://qiita.com/khayama/items/84ab5685ab8462222034)