Unityで動画を撮ってffmpegで差分比較する

Mayaから出力したカメラアニメーションがUnityでうまく再生されず、ちょっと加工して再出力を行いました。
結果なんかうまくいってる気がするけど、オリジナルとどの程度差分があるか比較したい…!
でも動画を2つ並べてもいまいちどの程度差があるか分かりづらいし、いちいち動画編集アプリで重ねる作業するのはめんどくさい…!

というわけでコマンド一発でできるようにしてみました。

動画を撮影する

UnityにはRecorderという最高の撮影ツールがあるので、とにもかくにもこいつを導入します。
Unity2019より前の場合はアセットストアで、それ以降はPackageManagerでインストールが可能です。

Unity Recorderをインストール

まずはWindow>Package Managerを起動します。
f:id:tm8r:20191226131036p:plain
次にPackage Managerの「Advanced」から「Show preview packages」にチェックを入れます。

f:id:tm8r:20191226131210p:plain
するとリストにUnity Recorderが表示されるので、こちらをインストールします。

Unity Recorderで動画を撮影する

f:id:tm8r:20191226131538p:plain
まずは動画撮影用の設定するため、「Add New Recorders」をクリックし、「Movie」を選択します。

f:id:tm8r:20191226132021p:plain
あとは出力先とファイル名を指定すれば最低限の設定は完了です。
もしGameViewの状態ではなく特定のカメラやRenderTextureを対象にしたい場合は「Capture」項目を変更する形になります。

「START RECORDING」をクリックすると撮影とシーン再生が開始し、同じボタンをクリックすると撮影が終了します。かんたん!
ちなみにExit PlayModeにチェックを入れておくと撮影終了時にシーンの再生も停止されるので便利です。

ffmpegで差分を比較する

ffmpegが入っていない場合は以下からダウンロードしてインストールします。
Download FFmpeg

次にターミナル(WindowsならコマンドプロンプトやPowerShell)を起動し、以下を実行してバージョンなどが表示さればおっけーです。

ffmpeg -version

以降は実際の結果をコマンドとあわせて紹介します。

動画を重ね合わせて比較する

前準備として動画があるパスにcdコマンドで移動しておきます。

cd C:\Users\tm8r\videos

まずは動画の上に透過した動画を重ねて比較をする方法です。

ffmpeg -i movie_before.mp4 -i movie_after.mp4 -filter_complex "[0:0]setpts=PTS-STARTPTS[a1];[1:0]setpts=PTS-STARTPTS[b1];[b1]format=yuva420p,colorchannelmixer=aa=0.5[alp];[a1][alp]overlay=shortest=1" -acodec copy -vcodec libx264 overlay_00.mkv

「movie_before.mp4」と「movie_after.mp4」が実際の動画ファイルになるので、ご自身の環境に合わせて変更してください。

このコマンドを実行すると同ディレクトリに「overlay_00.mkv」という名前で結果の動画が出力されます。
出力ファイルの拡張子は「mp4」などでも問題ありません。

「colorchannelmixer=aa=0.5」の「0.5」の部分がアルファの値になるので、こちらはお好みに合わせて調整してください。

f:id:tm8r:20191226133652p:plain
結果、このような画が得られます。

差分を抽出する

ffmpeg -i movie_before.mp4 -i movie_after.mp4 -filter_complex "[0:0]setpts=PTS-STARTPTS[a1];[1:0]setpts=PTS-STARTPTS[b1];[a1][b1]blend=all_mode=grainextract" -acodec copy -vcodec libx264 grainextract_00.mkv

次はブレンド機能のgrainextractというモードを使用してみます。

f:id:tm8r:20191226133703p:plain
結果はこの通り。

差がない部分はグレーになるので、完全に合致している場合は全領域がグレーになります。
透過で重ねる方法よりも差分の有無のチェックがしやすくてよいかんじです。

全部並べてみる

左上にオリジナル、右上に変更後、左下に透過して重ねたもの、右下に差分抽出したものを並べてみます。

ffmpeg -i movie_before.mp4 -i movie_after.mp4 -filter_complex "[0:0]setpts=PTS-STARTPTS,split=3[a1][a2][a3];[1:0]setpts=PTS-STARTPTS,split=3[b1][b2][b3];[b1]format=yuva420p,colorchannelmixer=aa=0.5[alp];[a1][alp]overlay=shortest=1[blend];[a2][b2]blend=all_mode=grainextract[blend2];[a3][b3][blend][blend2]xstack=4:0_0|w0_0|0_h0|w0_h0" -acodec copy -vcodec libx264 diff_split_00.mkv

ちょっとコマンドが長くなってますが、上記2つを利用しつつ並べてるだけです。

f:id:tm8r:20191226134357p:plain
結果。最高。

おわり

差分比較動画つくるとか、並べて一つの動画にするとか、動画編集アプリで人間がやる作業ではない。つらい。
ffmpegは神。どんどん自動化していきましょう🤗

細かい解説とかは気が…向いたら…(向かないやつ)

使用したモデルはユニティちゃんのお友達の茅野まりえちゃんです。
© UTJ/UCL

【Unity】FBXをアニメーションクリップ化せずにカスタムプロパティを差し替える

  • はじめに
  • OnPostprocessGameObjectWithAnimatedUserPropertiesを使う
  • OnPostprocessAnimationを使う
  • まとめ

はじめに

先日こんな記事を書きました。
tm8r.hateblo.jp

こちらではFBXからアニメーションクリップを取り出してカスタムプロパティをAnimatorControllerのプロパティから別のプロパティに差し替える、ということをしていました。
が、アニメーションクリップを取り出さずにFBXのままやりたい!ということもあると思うので、改めて調査してみました。

尚、利用環境はUnity2018.1.4f1です。

続きを読む

【Unity】【Maya】FBXのカスタムプロパティのアニメーションをUnityで使う

はじめに

Unity2017.2からは各種DCCツールで設定したカスタムプロパティをFBXからImport出来るようになりました。

Animated Custom Properties

Various DCCs (e.g. Maya and 3DSMax) support adding custom properties (or attributes) to objects:
These will appear in the Animation Window as Animator properties, just like additional curves created from imported clips:
You can then use a MonoBehaviour to drive other Component properties, or use an AssetPostprocessor to bind your curves directly to any Component.
https://blogs.unity3d.com/2017/10/12/unity-2017-2-is-now-available/

尚、この記事における利用環境などは以下の通り。

  • Unity: 2017.3.0p3
  • 使用モデル: ユニティちゃんトゥーンシェーダー2.0同梱のSDユニティちゃん
  • Maya: 2018sp2

Mayaでカスタムプロパティにキーを打ってエクスポートする

というわけで早速やっていきます。
まずはMayaで適当なカスタムプロパティ(Extra Attributes)にキーを打っていきましょう。

今回は特定のマテリアルのアトリビュートを書き換えるようなものを考えます。
具体的にはユニティちゃんのこのパーツのハイライトのアトリビュートを変えてみようと思います。
f:id:tm8r:20180228155746j:plain


こんな感じのコードを用意してスクリプトエディタなどで実行します。
引数は要件に応じて書き換えてください。

今回は変化が分かりやすいようにMaterialのcolorに割り当てたファイルノード(file2)のAlphaGainにキーを打っておいて、これをRoot_sphereノードにcustom_highcolor_powerという名前でコピーしています。
これをFBXエクスポートして準備完了です。

UnityでFBXをインポートする

上のFBXをUnityでインポートしたのち、ImportSettingで「Animated Custom Properties」にチェックを入れて「Apply」を実行します。
f:id:tm8r:20180228160610p:plain

これをAnimationウィンドウで見てみるとこのようになっています。
f:id:tm8r:20180228160721p:plain

どうやらちゃんとインポートされているようです。やったぜ。

値を反映する

さて、これを果たしてどうやって反映すればいいのか…!

Unityのブログには以下のように書いてあります。

MonoBehaviourを使って他のコンポーネントプロパティを制御することができますし、どのコンポーネントにも直接カーブをバインドするのにAssetPostprocessorを使うこともできます。
https://blogs.unity3d.com/jp/2017/10/12/unity-2017-2-is-now-available/

お、おう。

Animationウィンドウをよく見てみるとAnimator.〜と書いてあります。
というわけで、正解はこう。
f:id:tm8r:20180228161124p:plain
AnimatorControllerを作成、Stateを追加してMotionにインポートしたAnimationClipを指定したのち、Mayaで作ったアトリビュートと同じ名前、同じ型のパラメーターを追加してやればおっけーです。
深刻なドキュメント不足。

ただこれだけだとパラメーターが受け取れただけでUnityちゃんの頭のアレには何も起きないので、Materialに値を渡してやりましょう。

_rendererにはinspectorでMesh_SD_unitychan以下の_headを指定しています。
f:id:tm8r:20180228162234p:plain

いざ実行…!

f:id:tm8r:20180228161906g:plain
ヤッター。反映できたよー。

PlayableAPIを使用する場合を考える

AnimatorControllerを使える環境ならこれでよいですが、PlayableAPIで制御する場合はパラメーターが使えない(自信ない)気がするので、これだと困ってしまいます。
となると、AnimationClipのカーブを書き換えたいなーとなるわけです。

まずはUnity2017.2の新機能を眺めてみましょう。

Asset Import: Added AssetPostprocessor.OnPostprocessGameObjectWithAnimatedUserProperties(GameObject go, EditorCurveBinding[] bindings) and void AssetPostprocessor.OnPostprocessAnimation(GameObject root,AnimationClip clip).
https://unity3d.com/jp/unity/whats-new/unity-2017.2.0

AssetPostprocessorにOnPostprocessGameObjectWithAnimatedUserPropertiesとOnPostprocessAnimationが追加されているようです。

今回はOnPostprocessAnimationを使ってみます。

もともとあったメソッドだとAnimationClipを取得するのがなかなかダルかったのですが、OnPostprocessAnimationは第二引数にAnimationClipが入ってくるのがよいですね。

まずはOnPostprocessGameObjectWithUserPropertiesでユーザー定義のアトリビュートのあるものをフックできるので、これで名前が一致するものをフィルタリングしてアセットパスをtargetsフィールドに格納しておきます。
次にOnPostprocessAnimationでこのtargetsに含まれるものがきたら対象のカーブのEditorCurveBindingを書き換え、AnimationClipとして保存しているような感じです。

curveBinding.path = "Mesh_SD_unitychan/_head";
curveBinding.type = typeof(SkinnedMeshRenderer);
curveBinding.propertyName = "material._HighColor_Power";

pathはルートからの相対パス、typeは対象のクラス、propertyNameはそのまま格納するプロパティの名前を指定します。

目的のオブジェクトに対してそれぞれ何を指定したらいいか分からない場合、そのオブジェクトに対して新規でAnimationClipを作成して実際にAdd Propertyしてキーを打ってみて、生成された.animファイルをテキストとして開いてみるとよいです。

あとはこのAnimationClipをPlayableAPIを使って再生してやればおっけーです。

シンプル。

ただ、これだと割と構造が厳格に決まってないと厳しいのと、使い回しがきかなさそうな感じがします。

PlayableAPIを使ってもうちょっと柔軟に反映する方法を考える

CurveBindingのtypeは何もビルトインされているクラスじゃないと駄目なわけではないので、自前で値を保持するクラスを作ってそいつを指定する、というのも可能です。
具体的には以下のようにします。

あとはこれに合わせてModelImporterのcurveBindingまわりの処理を以下のように変えてやります。

curveBinding.path = "";
curveBinding.type = typeof(CustomProperties);
curveBinding.propertyName = "_highcolor_power";

Inspectorはこんな感じ。
f:id:tm8r:20180228162118p:plain

これでCurveBindingのpathは空文字でよく、さらに値の反映先も自由に決められるので、AnimatorControllerで制御するときと大きく変わらない感じで管理できそうです。やったぜ。

おわり

OnPostprocessGameObjectWithAnimatedUserPropertiesは2回目のインポートのタイミングで確かにカスタムプロパティのEditorCurveBindingが処理に入ってくるんですけど、いまいち何に使えばよいか分からず。
事例が色々出てくることに期待しつつ、気が向いたらもうちょっと追ってみたいところ。

カスタムプロパティがサポートされたのは大変喜ばしいんですけど国内も国外も資料なさすぎてつらみがすごい…。

f:id:tm8r:20170906162925p:plain
この作品はユニティちゃんライセンス条項の元に提供されています

【Unity】【AR】Unity2017.3+Vuforia7で水平面検知する

Unity2017.3が正式にリリースされまして、Vuforia7が搭載されました。
というわけで早速使ってみたので、実機で実行するまでを解説します。

  • Vuforia7の何がいいの?
  • 導入
  • シーンのセットアップ
  • エディタで実行してみる
  • タップでオブジェクト表示するようにする
  • ビルドしてみる
  • おわり
続きを読む

【Unity】ARKitのFaceTrackingでユニティちゃんに変身する


UnityのARKitプラグインでFaceTrackingがサポートされたので、ブレンドシェイプが設定されているユニティちゃんでためしてみます。

まずはサンプルを読んでみる

最新のARKit導入すると、UnityARKitPlugin>Example>FaceTrackingディレクトリの中にFaceBlendshapeSceneというシーンがあるので、これを参考に進めます。
FaceBlendshapeSceneはFaceTrackingのデモでよく見るスケキヨみたいなパックが顔に張り付くアレです。

このシーンにおける、ARFaceMeshManagerのUnityARFaceMeshManager.csとBlendshapeOutputのBlendShapePrinter.csがヒントになります。
ざっくり言うと、それぞれの役割は以下の通りです。

  • UnityARFaceMeshManager.cs:メッシュの生成と制御
  • BlendShapePrinter.cs:取得したブレンドシェイプの名前とウェイトを画面に表示する

サンプルを参考に実装してみる

というわけで作ってみたのがこちら。

ARKitから取得したanchorDataをもとにモデル自体の位置の調整、頭の骨の回転値の調整、ブレンドシェイプの適用、といったことを行っています。

シーンはこんな感じになってます。
f:id:tm8r:20171204134319p:plain

unitychan_dynamicはAnimatorやFaceUpdateなど色んなコンポーネントがついてますが、SpringManager以外は全て非アクティブにしておきます。
f:id:tm8r:20171204134751p:plain
この状態だともちろん体が動かないので若干寂しい感じがありますが、デフォルトで入ってるアニメーションデータだと頭の骨にキーが打たれていて、スクリプトでやっている骨の回転値の調整などで都合が悪いのでオフにしている感じです。

これを実行すると以下のようなユニティちゃんに変身できる闇のアプリのできあがりです。

ブレンドシェイプまわりの補足

取得できるブレンドシェイプの値とその詳細は以下をご参照ください。
https://developer.apple.com/documentation/arkit/arfaceanchor.blendshapelocation

anchorData.blendShapesからはキーをブレンドシェイプの名前、値を0〜1のウェイトとするDictionaryが取得できます。
Unityで使用するブレンドシェイプの範囲は0〜100なので、こちらは取得した値を加工して使います。

また、EyeBlinkLeftを取ってRightは取ってないのは、単純に今回使用したモデルのブレンドシェイプにそれぞれを閉じるようなものがなかったためです。
ARKitに合ったブレンドシェイプターゲットを持つモデルを用意できればもうちょっと同期してる感が得られそうですね!

f:id:tm8r:20170906162925p:plain
この作品はユニティちゃんライセンス条項の元に提供されています

【Unity】ARKitでセッション情報を破棄する

UnityでARKitを使用する際、特に凝ったことをしないのであればHelpersにあるUnityARCameraManager.csによってセッションの管理をする形になるかと思います。
ただ、このコンポーネントを使用すると、たとえばシーン遷移によって再度トラッキングをし直したいというとき、前のセッションの情報が残ってしまいます。

というわけで、これの解決法を調べてみます。

続きを読む

【Unity】FBX ExporterでMayaと連携してみる

Unity2017.2がリリースされ、あわせてねんがん(?)のFBX Exporterがリリースされました。βですけど。

ざっくり言うと、Unityで適当な仮オブジェクトを作成して作業したのち、Mayaと連携してUnityのシーンで特に作業をすることなく、仮オブジェクトを別のモデルに差し替えることができるようなアセットです。

詳細は以下。
blogs.unity3d.com
www.youtube.com

というわけで早速いじってみます。

  • FBX Exporter(beta)を導入する
  • UnityでExportしてみる
  • MayaでExportしてみる
  • Unityに戻って確認してみる
  • シーンとFBXを関連付ける方法
  • 個人的につらいと思ったところ
  • FBXの書き出し設定を変える方法
  • 感想
  • おまけ
    • Mayaで自前のスクリプトからFBX Exporterのコマンドを呼ぶ
    • Install Unity Integrationがやってることを調べる
続きを読む

スポンサーリンク