【Unity 2019.4〜】8K解像度の360度動画やVR180動画を実用的なパフォーマンスで再生する（HEVC使用）

# 概要
Unityで360度動画を再生するとき、4Kの解像度を境界として、動画コンテナに工夫が必要でした。

360度動画をUnity上で再生するための操作は、[公式ドキュメントに手順が掲載されています](https://docs.unity3d.com/ja/2019.4/Manual/VideoPanoramic.html)が、Unityにインポートするまでの工夫や、そうせざるを得ない背景事情を取り扱います。

2023年追記：
VR180フォーマットでも再生できたので、手順を追加。Apple Visionで取り上げられていたので、VR180の方が主流になる予感。
Vive Pro Eye程度だとそこまで解像感が良くないのですが、最近のHMDだと8Kぐらいの解像度は必要だと実感してます。HMDで片目4Kのパネルが主流になれば、12Kぐらい欲しくなる予感。H.266/VVCに期待。

2024年追記：
表「元ファイルの動画」の表記ミスを修正。180/360度動画と2D/3Dを混同を修正。
動画形式など、記事作成当時の誤った知識に基づく情報を修正。
表現の修正。

# 環境
### ソフトウェア
- Windows 10
- Unity 2019.4.x, 2022.3.34
- SteamVR
- HTC Vive, Vive Pro Eye

### ハードウェア 1 (2020年時点)
- Intel Core i7 10700
- NVIDIA RTX 2070 Super
- DDR4 32GB

### ハードウェア 2 (2023年追記)
- AMD Ryzen 9 7950X
- NVIDIA RTX 3090
- DDR5 64GB

### カメラ
- Insta360 Pro 2 (360度カメラ)
- EOS R5C + RF 5.2mm F2.8 (2023年追記, VR180対応)

# 背景
一般的にUnityに動画をインポートする際には、[H.264 (typically in a .mp4, .m4v, or .mov format)](https://docs.unity3d.com/ja/2019.4/Manual/VideoSources-FileCompatibility.html)を選択するが一般的です。[H.264](https://ja.wikipedia.org/wiki/H.264#プロファイルとレベル)は4K解像度までの対応が標準で、それを超える解像度はH.265を使用する必要があります。
一方で、H.264でもソフト（EOS VR Utilityなど）によっては、8K解像度で書き出せることもあり、VLCやMPCで再生できてしまいます。ですが、Unityでは正しく再生されません。本来、8KはH.264で想定されてないはずなので、H.265の動画を作成した方が望ましいです。

H.264の次世代規格である[H.265](https://www.jstage.jst.go.jp/article/itej/67/7/67_553/_pdf)は、8K解像度を標準で扱えます。Unityでも[Unity 2019.1](https://blogs.unity3d.com/jp/2019/04/16/introducing-unity-2019-1/#videosupport)からH.265をサポートしています。

# Unityにインポートするまで
1. H.265形式の動画ファイルを作成
2. [HEVC ビデオ拡張機能](https://www.microsoft.com/ja-jp/p/hevc-ビデオ拡張機能/9nmzlz57r3t7?activetab=pivot:overviewtab)の導入（120円）
3. Unityにインポート

## 1. H.265形式の動画ファイルを作成
お好みのエンコーダーや編集ソフト、各種ツールより、動画をH.265形式でエンコードして書き出します。H.265形式でのCPUエンコードは時間がかかるため、Intel QSVやNVIDIA NVENCやAMD VCEのような、GPUを活用したハードウェアエンコードあるいは、GPU支援を活用することで、高速化できます。
エンコードについては、私はいつも[こちらの方のブログ](https://rigaya34589.blog.fc2.com/blog-entry-1230.html)を参考にしています。

### 元ファイルの動画(Insta360 Pro 2撮って出しを付属ソフトでスティッチした直後の状態)

| 解像度・フレームレート | フォーマット | 2D, 3D | プロファイル | Chroma Subsampling | Bit depth | ビットレート(参考程度) |
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
| 8K30p(7680x3840, 29.97fps) | 360度 | 単眼視 | Main@L6.1@High | 4:2:0 | 8bit | 約150Mbps |
| 8K30p(7680x7680, 29.97fps) | 360度 | 両眼立体視 | Main@L6.2@High | 4:2:0 | 8bit | 約300Mbps |

### 元ファイルの動画(EOS R5C + RF 5.2mm F2.8の撮って出しをEOS VR Utilityで書き出した状態)

| 解像度・フレームレート | フォーマット | 2D, 3D | プロファイル | Chroma Subsampling | Bit depth | ビットレート(参考程度) |
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
| 8K30p(8192x4096, 29.97fps) | VR180 | 両眼立体視 | L6.1@High | 4:2:2 | 10bit | 約200Mbps |
| 8K30p(8192x4096, 29.97fps) | VR180 | 両眼立体視 | L6.1@High | 4:4:4 | 10bit | 約800Mbps |

### 動画ファイルの軽量化
上記の表について、Chroma Subsamplingが4:2:2や4:2:2、Bit depthが10bitで作成されている動画は、Microsoft Media FoundationやDXVAでのデコード処理に問題があるのか、一般的な動画再生ソフトや、後の行程でのUnityで、正しく再生できないことがあります。

この4:2:2や10bitは、プロダクションや編集のための、より高度なフォーマットです。これは、カメラでの撮影時に最大限データを確保し、編集耐性を持たせるために使用されるものです。

そのため、FFpmegやXMedia Recodeなどでエンコード、あるいは編集ソフトで編集や調整を終わらせ、再生に適したファイルへの書き出しを行います。VR180動画の場合、解像度やフレームレートはそのままに、Main@L6.1とし、QP18前後の設定で、4:2:0、8bitで書き出せば、Unity環境において、HMDで視聴しても正しく再生できるファイルとなります。

※ 8K動画はLevel 6以上推奨です。

## 2. HEVC ビデオ拡張機能の導入

現在、VR開発はWindowsの環境下で行われることが大半だと思われます。

Unityは、[Unity 2019.1](https://blogs.unity3d.com/jp/2019/04/16/introducing-unity-2019-1/#videosupport)から[H.265をサポート](https://docs.unity3d.com/ja/2019.4/Manual/VideoSources-FileCompatibility.html)しましたが、Windows上で動くUnity
では、動画のインポートと再生に[HEVC ビデオ拡張機能](https://www.microsoft.com/ja-jp/p/hevc-ビデオ拡張機能/9nmzlz57r3t7?activetab=pivot:overviewtab)を導入する必要があります。

これは、Unityが[Microsoft Media Foundation](https://docs.microsoft.com/en-us/windows/win32/medfound/h-265---hevc-video-decoder)を利用しているためです。

この拡張機能は[実質有償化しました](https://www.teradas.net/archives/35450/)が、OSレベルでH.265デコード機能が扱えるようになり、UnityでH.265が扱えるほか、エクスプローラのサムネイルでの表示やプレビューに対応します。


## 3. Unityにインポート
[公式ドキュメントに手順が掲載されています](https://docs.unity3d.com/ja/2019.4/Manual/VideoPanoramic.html)。2Dと3Dの双方の手順が記載されています。

2023年追記：以下の手順に示すスクリーンショットで、大体の流れを確認してみてください。

### 手順0

VR関係の導入。省略。
このプロジェクトは古いので、CameraRigを導入済みですが、最近であれば、XR Interaction ToolkitによるXROriginなどになってます。
また、Unity 2022.3環境のURPでも動作を確認しました。

### 手順1
RenderTextureは動画の解像度に設定します。
初期設定ではDepthBufferが設定されているので、Unityのリファレンスに従い、No depth bufferに設定します。

![ã­ã£ããã£2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421702/d914f61d-a5b8-470e-8d23-21bd47661120.png)

### 手順2
SkyBoxを変更するためのMaterialを作成します。
ShaderをSkybox/Panoramicとし、ImageTypeを動画の種類に合わせて設定します（180/360）。
3D Layoutは両眼立体視動画で必要で、動画に合わせて、上下配置(Over Under)と左右配置(Side by Side)の設定を行います。2Dの場合はNoneです。

対応するRenderTextureをこのMaterialのInspectorにD&Dして、設定します。

**VR180動画の場合**

![ã­ã£ããã£3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421702/1ec91607-6579-a747-5bb2-74b5a66e7db1.png)


**360度動画の場合**

![ã­ã£ããã£4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421702/4681edd9-6f09-c281-9cf7-0ae791d6747d.png)

### 手順3

Window -> Rendering -> Lighting Settingsから、Skybox Materialを設定します。
手順2で作成したMaterialに変更します。

この時、CameraのClear FlagsがSkyboxになっている必要があります。

### 手順4
VideoPlayerを配置し、URLやインポートした動画を指定します。
手順1で作成したレンダーテクスチャを、TargetTextureに指定します。
動画によってAspect Ratioを変更してください。

![ã­ã£ããã£.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421702/a19f262e-d5ac-a980-4930-c6c115fe36ad.png)

# 再生

これで大丈夫なはずです。動画やHMDの回転情報により、HMDの視野角外（正面でない）で再生される場合があります。その際は、空の親オブジェクトで調整するなどを行ってくださ。