AVPro Windows Media マニュアル飛ばし読み

UnityのWindows上で動画を再生するアセットとして（高いけど）定番のAVProWindowsMediaというのがあります。
https://www.assetstore.unity3d.com/jp/#!/content/2546

丁寧なマニュアルが有りますが、意外とまとまった日本語資料が無かったので書きました。
口語体で雑な日本語なので、気になったら原文を参照してください。

以下の記事が、素晴らしい導入です。

UnityとOculusで360度パノラマ全天周動画を見る方法2【Oculus Rift再生編】  
http://warapuri.com/post/120611106193/


AVPro Windows Media Unity Plugin version 2.80 2015/6/15版

#1. Introduction
"AVPro Windows Media"はUnity上でMicrosoft DirectShowがサポートする動画ファイルのスムーズな動画再生を行うためのプラグインです。

(Unityはquicktime準拠ですね)

このプラグインは動画再生を必要として、Unity標準のビデオ再生では満足できないハイエンドなユーザー向けです。

#2. System Requirements
- Unity Pro 4.1 ­ 4.6 (should also work with Unity 5.0 beta)
- Desktop Microsoft Windows platform (32­bit and 64­bit)
- Codecs for any video/audio you want to play

(codecをインストールする必要が有ることに注意、例えばH264だとLAV Filterとか)

##2.1 Platform not Supported
- デスクトップWindows以外のすべて

**Oculus Riftは公式にはサポートしません。しかし何人もの人が無事に使えていると言っています**

#3. Installation
1. unitypackageをインポート
2. DLL pluginを適切な場所に配置
3. **codecのインストールをしておいてください**

#4.Features
```
● Unity 4.1 ­ 5.0 supported.
● Both 32 and 64­bit friendly.
● Free watermarked trial version available.
● Years of professional use in the field.
● Fast native Direct3D9, Direct3D11 and OpenGL texture updates.
● Frame accurate seeking and scrubbing.
● Supports video transparency.
● Native Hap codec support (no plugin needed).
● Play videos from disk or from memory.
● Supports internal clips.
● 7.1 audio channel mixer.
● AV sync offset control.
● Unity 4.6 uGUI support.
● NGUI support.
```
** 4kサポートはしていません。(HapまたはH.263いわゆるDivXやXDivなどの一部コーデックを除く)(4kというセクションを専用に割いています)**

#5.Unity Components
このアセットは幾つものscriptを含んでいます。普通の使い方ならノンコーディングで大丈夫です。スクリプトを書くとすれば、これらのコンポーネントを更にコントロールするためのスクリプトくらいでしょうか。

##5.1 AVProWindowsMediaManager
動画を再生するシーン内に**「絶対に、たった1個、2個や0個じゃない1個」**だけ存在するようにしましょう。
そして、このスクリプトは最初に実行する必要があります。必要なら**Unity上のScript Execution Order Settingから、このアセットの他のスクリプトよりも先に実行するようにしてください**

(どのGameObjectにアタッチしていても良いので、空のGameObjectにぶら下げたりします)

##5.2 AVProWindowsMediaMovie
このコンポーネントは1:1で動画ファイルと対応します。もし再生したい動画が何個もあったら、その分だけ必要です。カラーフォーマットは内部的に処理するフォーマットで、クオリティとパフォーマンスに影響します。

-  “YCbCr_HD” (default): 高速で再生できます。 709YUVで作られた動画であれば。Hap 形式のビデオもこれ。
-  “YCbCr_SD”: 同じく高速で再生出来ます。Rec.601 YUV で作られたものであれば、普段は上のHDで良いと思います。
-  “RGBA32”: このモードは遅いですが、アルファチャンネル付きの動画に対応します。 Hap 形式のビデオはアルファチャンネル付きでも、これは選ばないでください。

カラーフォーマットは動画再生中に変更できません。

これらのフォーマット、何を選べばいいかはUnityEditor上で再生しながら切り替えたりしてfpsが一番出ている形式にしておけば大丈夫です。
また、このコンポーネントは内部的に動画を読んでいるだけなので、見て確認することが出来ません。見て確認するためのコンポーネント郡を以下で説明します。

（環境によっては、**YCbCr_HDとRGBA32で再生している動画の上下が反転するかもしれません。その場合は球ならy軸のscalingを負の値にしてください**）
（**もしかしたらAVProWindowsMediaMovieのignore flipsをオフにすれば解決するかも**）

##5.3 AVProWindowsMediaGUIDisplay
カメラに対してUI的に貼り付けるスクリプト。全画面再生とかで使います。
(使ったこと無いや…)
OnGUI()で描くやつです。

##5.4 AVProWIndowsMediaUGUIComponent
5.3のuGUI版、全画面再生したりするのに使います。

##5.5 AVProWindowsMediaApplyUITextureNGUI
5.3のNGUI版、全画面再生したりするのに使います。

##5.6 AVProWindowsMediaMeshApply
これはメッシュに直接割り当てます。（イマイチ使い道が分からない…5.7のMaterialApplyで代用できる上に、そちらのほうが応用しやすい）

##5.7 AVProWindowsMediaMaterialApply
これはマテリアルに動画を割り当てます。
**これが一番よく使われます**

大体の用途において、 5.2のAVProWindowsMediaMovieとセットで使うのでシーン内には同数が存在するはず。

#6. Use Case Note
お手軽な使い方ガイドです。このセクションを読んでおくと、実際お役立ちです。ありがちなユースケースと、それに対する作り方が書いてあります。

##6.1 Transparent Video
透過する動画を流したい、というのはあるあるです。
しかしアルファチャンネル付きの動画コーデックはそれほど多くありません。例えば

- 非圧縮RGBA
- Lagarith
- Hap Alpha 
とかでしょうか。現実的には後者2個になりそうです。

以下のコーデックはいけそうな気がしたけど、だめだった！
- VP8/VP9 WebM アルファ付きをサポートしてたけどDirectShow codecではダメだった
- VP6 フラッシュ用のコーデックでアルファをサポートしてたけどDirectShow codecが無さそうだった

##6.2 Video Clips
一個の長いビデオにパックして、サブクリップとしていくつもの動画がある。という使い方。
この方式は複数の動画を全部バラバラに読むよりもメモリ消費量が少なく、またハンドリングしやすいです。

AVProWindowsMediaもこの方式をサポートしています。Clipsというところで何秒から何秒がclip1で、何秒から何秒がclip2で…という風に長いビデオを区切って使えます。
この場合はPlayClip()という関数を使います。

##6.3 Video Scrubbing
動画の再生しながら早送りや巻き戻しをしたい場合。
実はこのAVProWindowsMediaは完璧とは言えないです。AVProQuickTimeの方は出来ます。しかしDirectShowの制限として1秒あたり15フレームに制限されています（ここは良く分からない）

スムーズな早送りや巻き戻しには、再生している動画ファイルがキーフレームをサポートしている必要があります。HapコーデックはMotionJpegのお化けなので毎フレームがキーフレームといえるので、安心ですね。

再生速度変更はAVProWindowsMediaはサポートしていますが、早送り相当は出来ても、高速な巻き戻し相当は出来ません。もしビデオを一時停止して、スクラビング（シーク）を手動でやることは出来ます。**しかしオーディオは一時停止中も流れたままです。**

##6.4 Super High Resolution 4K/8K Playback
高解像度動画の再生。
MP4video(H264)は普通、UHD(4k)の再生には適しません。なぜならAVProWindowsMediaはh264hardware decodingに対応していないので。
しかしまあ最近のメッチャ速いマシンだったら30FPSは大丈夫です。
もしもH264でなければいけないなら、H264codecのスムーズな再生のためのtipsをまとめた **H264**というセクションを見ておいてください。  
windowsデフォルトのDirectShowフィルタは1080pまでしかサポートしないので、3rd partyな H264デコーダーを追加する必要があります。また、その追加したH264デコーダーをOS既定のデコーダにちゃんと設定しましょう。(‘Codec Tweaker’ というソフトならGUIで指定できそう. **FAQセクションに書いてあります** )


コーデックとしてはHapが一番速いデコード出来るのでおすすめです。すごくファイルサイズが大きくなるので、速いSSDが欲しくなりますが…(**Hap codecセクションを見て！**)

他には XvidやDivXのコーデックもUHD再生に耐えられることを発見しました。HapよりはCPU負荷あるけど、H264をヒーコラとCPUデコードするよりはマシです。そしてHapよりはビデオサイズが縮みます。（これらは、H263と言う言い方もしますね）

##6.5 Low CPU Usage
CPU使用率が低いことは重要な場面もあります。例えば複数の動画を同時に再生するときや、GPU温度を上げたくないなどです。

そういう用途にはHap codecを使いましょう。
(執拗なHap推しですね…)

##6.6 Multiple Audio Speakers
動画を再生しながら音が出るスピーカー(AudioSource)の位置を動的に変更したい場合があります。
例えば長い壁があり、壁沿いに複数のスピーカーがあって、Audio Listenerを付けたMainCamera(プレーヤー)が壁沿いに歩く。一番近いAudioSourceのみから音が出てくる、という場合です。
このプラグインは7.1chのオーディオミキサーをサポートしています。なので8個のスピーカーの音量(Volume Level)をそれぞれ個別にfloatの値で制御できます。(1f,0,0,0,0,0)→(0,0,1f,0,0)みたいに。

##6.7 Oculus Rift Virtual Reality
3DVideo(パノラマの立体視動画)をVR環境で流すというのは、よくある使用例です。このプラグインは**こういった用途を直接はサポートしません。**しかし、何人もの人がこの用途で実際に使っています。

基本的なアプローチは、Side by Sideで左と右にそれぞれ左右の目に合わせた動画をまとめた動画ファイルを作ります。
左目分のUVを指定した平面と、右目分のUVを指定した平面を作って、tagやlayerでそれぞれの目だけに見えるようにCulling指定することで実現可能です。

この用途へのサポートやサンプルも将来追加したいです。
（当然、球へのマッピングでも有効です）

#7. Playback Performance
##7.1 Hardware
まずはハードウェアが快適化をチェックします。普通に対象のPCで対象の動画ファイルを再生して、カクついたりしない事を確認しましょう。
タスクマネージャやリソースモニタでチェックしましょう。

もし動画ファイルのビットレートが大きかったり、フレームレートが高かったりすると、CPU負荷以前にディスクアクセス速度が足りなくて再生がカクつく可能性があります。CPUの再生負荷が軽い代わりにビットレートが高くなりがちなHap codecを使ったりするときは、特にSSDを推奨します。

また、SLIやCrossFire環境だと、動画再生が不定期にカクつくという場合もあります。もし該当環境であれば、シングルGPUでも試してみてください。
このプラグインは、シングルGPU推奨です。

##7.2 Video Format
使用用途にあわせた動画フォーマットを選びましょう。
動画コーデックによって、圧縮率を重視していたり、再生負荷が低いことを重視していたりします。

動画ファイルサイズが大きくなることを気にしないのであれば、**Hap video codecはおそらくベストな選択です。**Hap形式の動画は、CPUのデコード負荷が最小で、GPUへの転送もしやすい圧縮形式だからです。
(そうは言ってもHapのエンコーダは大変だったりしますけどね)

H264形式は、非常にCPUデコード負荷の高いコーデックのひとつです。 H264形式は非常に高い圧縮率を誇りますが、再生負荷も非常に高いです。
H264エンコードには様々なエンコードオプションがあります。これらのオプションは重要で、もっとも適したオプションにして再生をスムーズにしましょう。
例えばffmpegでは、こういったオプションを指定します。

```
ffmpeg -­i input.mp4 ­-c:v libx264 ­-pix_fmt yuv420p ­-preset veryslow -­tune fastdecode ­-profile:v main -­coder 0 -­g 6 -­crf 20 output.mp4
```

(一応各オプションを解説します。日本語では以下のサイトが詳しい)

-  http://tech.ckme.co.jp/ffmpeg.shtml 
- http://mobilehackerz.jp/archive/wiki/index.php?%BA%C7%BF%B7ffmpeg%2F%B9%E2%C5%D9%A4%CA%A5%AA%A5%D7%A5%B7%A5%E7%A5%F3

```
-c:v libx264 …H264形式でエンコード  
-pix_fmt yuv420p …ピクセルのフォーマット指定。一番負荷が低い  
-preset veryslow …エンコードは遅い代わりに出来上がる動画サイズが小さくなる  
-tune fastdecode …CABACおよびin-loop deblockingを無効にし、デコードの際の負荷を減らす。(画質は少し落ちる)
-profile:v main …Mainプロファイルを使う(Highプロファイルよりも再生負荷が低い）
-coder 0 …符号化方式の種類を指定。x264 では -coder vlc (-coder 0) で CABAC なし、-coder ac (-coder 1) で CABAC あり。
-g 0 …GOP(Group Of Picture)のサイズをフレーム数で指定する。
-crf 20 …品質、小さいほど高品質でファイルサイズが大きくなる。6ごとにビットレートが倍くらいになる。20はかなり高画質。
```

もっと極端に再生負荷を下げるなら
```
ffmpeg ­-i input.mp4 ­-c:v libx264 -­pix_fmt yuv420p -­preset veryslow -­tune fastdecode -­profile:v main -­crf 20 -­refs 1 -­coder 0 -­g 30 -­x264opts no­-deblock ­-x264opts bframes=0 output.mp4
```
という設定もできます。追加で参照フレームや、GOPの増加、deblockオプションなどを入れています。

**H263互換の XVidまたはDivXコーデックは再生負荷がH264よりは明確に低く、ファイルサイズがHapより縮むので良いバランスのコーデックです。**

##7.3 Codec Tuning
幾つかのコーデックは再生をなめらかにするための固有オプションがあります。例えばLagarithコーデックは、再生時にマルチスレッドでデコード出来るオプションがあります。こういった設定はVirtualdubなどのソフトのコーデック設定をよく調べてみてください。

##7.4 Video Resolution
これはあまり知られていない事ですが、正しく指定された動画解像度はGPU上のTextureへのメモリーアライメントが最適化されて、再生負荷への影響が十分にあります。
上から順にCPUやGPUに優しい解像度設定です。
1. 縦横解像度共に2のべき乗
2. 横解像度は2のべき乗（縦解像度は何でも良い）
3. 縦横解像度共に16の倍数
4. 横解像度は16の倍数（縦解像度は何でも良い）
5. 縦横解像度共に4の倍数
6. 横解像度は4の倍数（縦解像度は何でも良い）
7. それ以外の解像度

例えば1920x1080の場合は4.に当たりますね。

##7.5 Multi-Threading
もしUnityEditor上では動画がスムーズに再生されているのに、ビルドするとガクガクする場合は、Unityのマルチスレッドレンダリングを無効化する事で改善するかもしれません。PlayerSettings→Inspectorをdebugにして MTRenderingのチェックを外してオフにします。

##7.6 Display Frame-Rate Sync
再生する動画のフレームレートは、再生するディスプレイのフレームレートの整数倍である必要があります。例えば30fpsの動画を60hzのモニターで再生するなど。しかし24fpsの動画を60hzのモニターで再生するとスムーズに見えません。

（OculusRift DK2は75Hzモニターなので、この問題が大きいです。　先人の知恵： http://d.hatena.ne.jp/fai_fx+OculusRift/20140814 ）

AVProWindowsMediaMovieコンポーネントは、**'Display Sync'オプションがあります。**これをチェックしておくと内部的にフレームを先読みしてバッファリングすることで、こういった状況でもスムーズな再生ができるようになります。ただしこのオプションを入れると再生開始時や動画のシーク時に一瞬バッファリングのために止まります。
このオプションは、Unityのexeがフルスクリーン起動していて、なおかつビルドオプションでVSyncがonになっている時しか正常に動作しません。

(これは、結構知られていないオプションですね)

##7.7 Machine Setup
バックグラウンドで動いてるアプリが多いと良くない。

##7.8 Garbage Collection
Garbage Collectionが走ると動画再生中にフレームドロップが起きます。Unityでコンテンツを作るときに無駄なGCまかせのリソースを撒き散らさないように気をつけて作りましょう。

##7.9 latest Version
このプラグインは常に最新のものを使ってください。

#8. Codec Guide

ここは長々と各種ビデオコーデックのおすすめが書いてあります。  
おすすめ順は
Hap>>XVid /DivX>>(CPU負荷高いのでおすすめしない壁)>>>H264>>>(H265)  
とのことです。  

特に1080pを超える動画解像度だと、3rd partyのcodec を探す必要があったりして、大変です。

#9. Video Tools & Software
##9.1 Virtualdub
おすすめ、DirectShow向きなAVIファイルを作れます。 

##9.2 Adobe AfterEffects /Premiere
言うまでもないです。ただ、デフォルトのエンコード設定は、動画再生負荷が高かったりするので注意。

##9.3 FFmpeg
めっちゃ便利な、なんでもエンコーダ

##9.4 LAV Filters
codec/filterパック系は、おすすめしません。なぜなら変なコーデックが入ったり、古いフィルターが入ったりして再生パフォーマンスが落ちたりするからです。
（K-lite codec packとか…よくないですね）
そんな中で、一つだけおすすめするとすれば、LAV Filtersです。このフィルターはFFmpegと同じコードベースから作られていて信頼性があります。
LAV filtersは(MainプロファイルだけじゃなくHighプロファイルも再生可能な、そして1080P以上の解像度も再生可能な)H264デコーダも含んでいます。

#10. Support
省略

#11. About RenderHeads Ltd
省略（この会社、儲かってそうだなあ…）

#12. Credit
省略

#FAQ
気になることだけ訳します。

##Frame seeking doesn’t seem to be working properly?
シークするにはPositionFrameプロパティを設定しなければいけません。

##What codecs are needed to play MP4/MKV files?
Install Haali Media Splitter (h ttp://haali.su/mkv/) 
or
Install GDCL Mpeg­4 filter ( http://www.gdcl.co.uk/mpeg4/) 

##How do I get transparent videos to play correctly?
まずはその動画コーデックがアルファチャンネル付きで作れるかを確認する。そしてAVProWindowsMediaMovieのColor FormatをRGBA32にする (**Hap Alphaなら YCbCrHDのままで良い**) 
最後にUnity上のマテリアルがアルファチャンネルを含むか確認する。

## I’m trying to play a very high quality H.264 video and I only get a blank screen with audio playing, how can I fix it?
Windows7やWindows8はデフォルトでH264をデコード出来ますが、SimpleプロファイルやMainプロファイルまでです。Highプロファイルや1080pより高解像度のH264動画を再生したければ

1) Install L AV f ilters
2) Install C odec Tweaker
3) Run Codec Tweaker, go to “Preferred decoders” and change “H.264” from “Microsoft” to “LAV Video”.

##Which of your Unity video­playback plugin is more suitable for me: AVPro Windows Media or AVPro QuickTime?
もしWindowsとMacのクロスプラットフォームで作るならAVPro QuickTime一択です。
Windows上での高パフォーマンスで動画を再生するなら、 AVPro Windows Mediaです。なぜならWindowsのQuickTime はマルチスレッド対応が貧弱なので。

事前に無料のデモ版で、再生パフォーマンスは検証してから買ってください。

##動画の再生、ポーズではなく停止がしたい
public GameObject MovieGameObject;がAVProWindowsMediaMovieを追加しているGameObjectだとすると

```
AVProWindowsMediaMovie Movie = MovieGameObject.GetComponent<AVProWindowsMediaMovie>();
Movie.Pause();
Movie.MovieInstance.PositionSeconds=0f;
AVProWindowsMediaPlugin.Stop(currentMovie.MovieInstance.Handle);
```


##毎回動画を再生して確認するのがしんどいので、サムネイルテクスチャを生成したい
Windowsなら、こんな感じのスクリプトを作ってffmpegを作ってフレーム切り出しをしておくと、便利。
**AVProWindowsMediaMaterialApply**コンポーネントのDefault Textureに割り当てておくとか。

CreateThumbnail.ps1

```
# フォルダ内のaviファイルの1秒後のサムネイルをpngで全部吐くスクリプトです
# ffmpeg.exeが起動フォルダに存在することを前提にしています。
# 入力は、aviファイルを対象にしています。また、出力はPNGファイルです。
# 適宜読み替えて使ってください
$Env:Path += ";.\"

Get-ChildItem .\ -include *.avi  -Exclude *.meta -Recurse | foreach-object { 
$newname = $_.Basename + ".jpeg";
#切り出しタイミングは hh:mi:ss.SSS のフォーマットで指定すればOK
ffmpeg -ss 00:00:00.300  -t 1 -i "$_" -f mjpeg  $newname 

}
```