こうしす!通信

こんな映像コンポジットソフトがあったら良いなという話

2014/12/01 01:00 投稿

コメント:2

  • タグ:
  • コラム
  • 夢物語
夢物語担当のButameronです。こんにちは!

世の中には優れたコンポジットソフトがいくつもあります。
まず、OPAP-JPで使用しているのはAfter Effectsです。これは、「レイヤーベースのコンポジットシステム」と呼ばれる物で、アニメ業界でも標準的な立ち位置にあるようです。一方、日本ではマイナーですが、「ノードベースのコンポジットシステム」と呼ばれるものがあり、代表例としてはNukeが挙げられます。こちらは、構造上、タイムライン機能がレイヤーベースに比べると貧弱(複雑)になるため、アニメの撮影作業にはあまり向いていないといえるかもしれません。

Nukeは使ったことがないので評価しようがありません。
しかし、After Effectsについては、手に馴染まないなあとずっと思っています。(理由はこの記事の最後に独り言として書いておきます)

やはり初恋の人は忘れられないのか、元AviSynthユーザーとしては悶々としております。

実は、筆者が一番最初に本格的に使ったビデオ編集ソフトは、AviSynthです。このソフトの発想はノードベースのコンポジットシステムに近いのですが、一番の特徴は「スクリプトでビデオを編集する」ということでしょう。(厳密には動画編集ソフトというよりもフレームサーバーという種類のソフトです)


たとえば、「音声無しの映像test1.aviとtest2.aviを結合して、さらに音声test.wavを乗せる」という編集をするのであれば、以下のような書き方になります。
audio = DirectShowSource("test.wav")
video = DirectShowSource("test1.avi") + DirectShowSource("test2.avi")
video = video.AudioDub(audio)
return video


これを「xxxx.avs」というファイル名でテキストファイルとして保存して、「xxxx.avs」をMedia Player Classic等のAviSynth対応ソフトにD&Dすることで、編集結果を再生することができます。


このソフトの優れた点は、プラグインでエフェクト等の関数を増やせるだけでなく、自分で関数を作ることができるという点です。しかも外部ファイルを相対パスで指定してインクルードする機能もあります。したがって、共通エフェクトを「Common.avs」に入れておいて、各シーンや各カットのavsから呼び出すということが可能です。

取っつきにくいですが、定型的なエフェクトを掛けるだけであれば、結果的に作業の手間を省くことができます。


ただ、AviSynthには割と問題があります。

  • After EffectsのようにリッチなGUIがない。
  • GUIではないのでタイムラインという概念が特にない。
  • Layer機能は単なるエフェクトのひとつ。
  • 3Dレイヤ的なものについてはサードパーティのプラグインを含めて壊滅的。
  • 上記の理由で、モーショングラフィックスを実現するのは非常に困難。
  • 大量の動画を読み込ませると再生が始まるまでかなり待たされる上にメモリを食う。(32bitの壁はすぐ突破する)
  • AVIを大量に読み込ませるとDLLコールの最大数を突破するためかエラーになる。
  • 解像度を落としてプレビューする機能がない(自分でスクリプトとして実装する必要がある)
  • 特殊な言語で習得に手間がかかる上、for文がないなど機能が制約されている。(ただし、AviSynth+では改善されている)
  • ラムダ式のような流行の機能が使えない
  • Windowsでしか使えない


例えば、AEやNiVEのようなGUIを作って、スクリプトを自動生成するような方法を考えた場合、モーショングラフィックスを実現するためには、フレーム毎に1行のスクリプトを出力しなければならないなどの残念な仕様となります。つまり言語仕様が不足しているわけです。

AEでいうところのエクスプレッション的なラムダ式をエフェクト関数の引数に渡すということは必須であると考えられ、やはり、ぶっちゃけ.NET Framework上で似たような事ができたら便利じゃないかなあと思うわけです。


C#で実装してmonoでマルチプラットフォームに対応することは恐らく可能です。デコーダーとしてffmpegとかを使う必要はあるかもしれません。これで、Windowsでしか使えないという部分もギリギリ解決できます。ついこの間.NET Frameworkのリファレンスコードが公開されたこともあって、monoの互換性向上にも期待されます。

また、マネージドコードを使うことで懸念されるパフォーマンス低下ですが、SIMD命令が使えるらしい次世代のJITコンパイラRyuJITや、unsafeコードや、最悪P/Invokeで何とか出来たら良いなあ。あとは、OpenCLとか.NETから呼び出せるんでしょうか。まぁプラットフォーム依存になってしまいますから、要検討というところもあるでしょうね。

少なくともインターフェース部分だけでも.NET Framework上で実装することの利点は、C# だけでなく、VB.NETや、C++/CLI、(Iron)Ruby、(Iron)Python、(マネージ)JScript 、PowerShellなどに対応できると考えられることです。したがって、言語習得のためのハードルも下がります。(まぁそれぞれの言語の表現能力の差とかで使える機能と使えない機能が出てきそうですが)


実装としては、AviSynthのような感じを踏襲し、それを実現するために、LINQのような遅延評価を参考にしたり、演算子オーバーロードを使用するという感じでしょう。今頭の中でイメージしている使い方は以下のような感じです。
public static class Program
{
    public static IVideoContext Scene01Cut01()
    {
         IVideoContext video1 = VideoSource.AviSource("test1.avi");
         IVideoContext video2 = VideoSource.AviSource("test2.avi");
         IVideoContext audio = VideoSource.WavSource("test.wav");

         // 時間ごとにブラーが大きくなる+フェードインエフェクト
         // このように時間的に変化するパラメーターはラムダ式で実装する
         video1 = video1.Blur((t, vc)=> t * 2.5).FadeIn(10);

         // ブラーは固定値+フェードアウトエフェクト
         // 固定値の場合はオーバーロードで実装することを規約で決めて対応
         video2 = video2.Blur(5).FadeOut(10);

         // 演算子オーバーロードされた+演算子で動画を結合することもできる
         IVideoContext result = (video1 + video2);

         // 音声を追加することもできる。このあたりはAviSynthと同じ。
         result = result.AudioDub(audio);

         return result; // この時点ではまだレンダリングは実行されない
    }

    public static int Main()
    {
         //実際はこの部分は別のプログラム※で実装される
         //※ エンジンを組み込んだGUIやフレームサーバー用の別プログラム

         RenderEngine re = new RenderEngine();
         using (var fs = new FileStream(…)) 
         {
             //ここでIVideoContextに蓄積された編集情報を元に
             //レンダリングが実行される
             re.RenderAll(Scene01Cut01(), new RenderOption(), fs);

             //指定フレームのプレビューの場合は以下のようになる
             var frameNum = 200;
             re.RenderPreview(Scene01Cut01(), new RenderOption(), frameNum, fs);

             //reがCloseかDisposeされるまでメモリが破棄されず何度でも
             //フレーム単位のレンダリングができるとなお良い

         }
         return 0;
    }

}


実際には、Main関数の部分は実装せず、.NET アセンブリとしてScene01Cut01関数の部分がDLLにコンパイルされる形になるはずです。

C#はスクリプト言語ではないため、スクリプトの気楽さが幾分か減少してしまう上、リンクとかが大変そうですが、そのあたりはもっと検討が必要だと思われます。ただ、レンダリングするタイミングでバックグラウンドでコンパイルを走らせることそのものは、AviSynthユーザーにとってはそんなに違和感はないと思います。

また、AE風のGUIでレイヤーベースのタイムラインで色々入力すると、自動的にソースコードが生成されるという形になれば便利なはずです。これは、Visual StudioのWindows Formsのデザイナと同じような感じですね。

確かに見た目取っつきにくいですが、一般ユーザーはGUIと仲良くしていれば普通にビデオ編集ができ、高度なユーザー(笑)は、自分でコンポジションやユーザー定義エフェクトをゴリゴリプログラムして効率的な編集作業が実現できるため、みんなが幸せになれそうです。バックエンドがプログラミング言語のフレームワークであれば、こういう利点があるわけですね。

こういう拡張性というか柔軟性の高さは、実現できればAEにない強力な利点になると思います。



というわけで、こんなビデオ編集フレームワークがあったらいいなーとずっと思っています。
まぁ自分で作ればいいんですが、いかんせん暇も気力も根気もないので、単なる夢物語なんですけどね。でも、作ってやるぜというすごい技術者がおられたら、ぜひお願いします。あと、できればライセンスはMITか、最悪でもLGPLがいいです。お手伝いぐらいならできますで。





補足というか独り言

After Effectsの課題点

After Effectsは便利です。
とても便利です。サードパーティのエフェクトもそれなりに揃っていることから、実質的に唯一の選択肢です。

しかし、泥臭い作業を甘受しなければならないというのが生理的にアカン感じです。使えば使うほど嫌いになっていく、それがAfter Effectsです。

ここからdisりまくりますので、disるのが嫌いな方、Adobe信者の方は読み飛ばして下さい。

1. 外部ファイルを参照できない

一番不便な点は、他のAEPをダイナミックリンクなり何なりで取り込まずに参照するということができないという点です。Premiere Proはaepをダイナミックリンクで参照することができますが、肝心のAfter Effects自身は別aepを参照することができず、取り込むことしかできません。

After Effectsがビデオ編集ソフトではないというのは百も承知なのですが、たとえば共通的に使うコンポなどは、あるaepのコンポの内容を弄れば、それを参照するaepにも反映されるという機能があれば、すごく便利だと思うのです。

たとえば、全シーンで登場するポスターの内容を一括して変更できたら便利ですよね?

ところが、現在のAEでは、ファイルを跨いだ場合、ひとつひとつ手で置き換えていく必要があります。設計からして、ファイルを跨がないことが前提となっているようですが、ここが一番大嫌いなポイントです。

(そもそもダイナミックリンクの機能が不安定だったりパフォーマンスがアレという不満もありますが)

2. 既存のエフェクトを組み合わせて新たなエフェクトを作るような「ユーザー定義エフェクト機能」がない


1にも少し被る点ですが。

ご承知の通り、同じようなエフェクトの組み合わせを繰り返し使う場面は多いと思います。
こうしす!第2話でいえば、線画に対して微妙に色を被せる(いわゆる色トレス)作業や、軽いDFフィルタをかけるという作業は定型的に行われる物です。

もし後から調整したくなったとき、全てのコンポに対してパラメータを調整していく必要があります。
例えば、こうしす!の場合カット数は80〜170程度ありますが、手作業で80〜170回同じ作業を繰り返さなければならないということになります。

もし、よく使うエフェクトの組み合わせをまとめて「ユーザー定義エフェクト(仮)」として登録する機能があり、なおかつ、そのユーザー定義エフェクトを弄っただけで、それを使用している全てのコンポの調整が完了するとすれば、作業がすごく楽になると思いませんか?

ところが、After Effectsにはそのような機能はありません。アニメーションプリセットはあるものの、本質的に、ここで言う「ユーザー定義エフェクト(仮)」とは異なる物です。

(注:エフェクトのパラメータだけであれば、一括して変更することは出来なくもありません。それは、エクスプレッションを使う方法です。各エクスプレッション内で、絶対パス指定でスクリプトを読み込んで、evalして、その中の何かの変数や関数を呼んでreturnすれば良いのです。しかし、aepからの相対パス指定はできないというのが残念なところです)

3. 痒いところに手が届かないスクリプトやエクスプレッション


たとえば、レイヤーを読み込んだPSDの一括差し換え。
スクリプトでフッテージの置き換えを行うと、残念ながら望み通りの動作にはなりません。
差し換えがうまくいかないのはともかく、これではファイル名の変更もまともにできません。

さらに、失望するのが、スクリプトから叩ける機能の少なさです。
たとえば、After Effects CCからCS6形式に保存する操作を、スクリプトからボタン一発でできるようにできれば便利なのですが、残念ながらそれは不可能なようです。

エクセルマクロのレベルを期待すると絶望します。
失望ではありません、絶望です。


エクスプレッションについては、2にも触れたとおりです。さらに、プロジェクト単位のグローバル関数を用意することもできません。たとえば、同じような挙動をするエクスプレッションは共通関数を使えると便利なのですが、そういう使い方は想定されていないようです。なんとかテキストレイヤを使ってそれっぽいことをすることは可能ですが、なんと回りくどいことか。

正直、Flashを作っているのと同じ会社が作っているとは思えません。
(いや、まあ、あれは元々作っていた会社が違いますが)


4. プロジェクトファイルがバージョン間で互換性がない


これですよ、これ。
こうしす!の制作では、After Effects CS6が標準の制作環境になっています。
しかし、筆者の環境は、After Effects CC(2014)です。ですので、まず、After Effects CC(2014)からCC形式に書き出し、After Effects CCを立ち上げてCC形式からCS6形式に書き出す、というアホみたいなことをしなければなりません。

「制作環境を合わせれば良いじゃん、CC契約でもCS6が使えるんだし」というご意見はごもっともです。

でも考えて下さい。
完璧ではないにしても、PhotoshopならCCで保存したpsdがCS4で開けます。
Excelなら2003でも互換パックを入れれば2013で保存したxlsxが開けますし、2013でも2003のxls形式で保存できます。

AE CS6からCC(2014)で根本的な機能が変わっているわけではないのですから、せめてCCの各バージョン内とCS6だけでも後方互換性・前方互換性を持たせたらどうなんだろうと思ったりするわけです。
(特にCS6とCCの間でビジネスモデルを大きく転換したわけですから、少なくともCCの各世代からCS6への互換性を持たせるのは当然ですよね。)

あともう一つ気に入らないのが、XML形式のaep(aepx)です。いや、方向性はGOODなんです。
とても良いと思います。ですが、中途半端です。

XMLといいながら、バイナリーデータ(の16進数)が残りすぎていて、しかもその仕様が殆ど開示されていないため、ほとんど有用性がありません。そして、常用が非推奨だというのも残念です。まぁPSDのファイル名の置換のために、テキストエディタで編集できるのは助かるのですが……。

もちろんすべてをXMLで記述するのが難しいのは分かります。
けれども他社製のソフトで仕様通りにaepxを書き出すことができれば、定型処理的なものは非常に簡単に自動化できるのではないでしょうか。これまでdisってきたことも、すべて別のソフトを作ることで解決してしまうのですが、残念ながらこれも実現が難しいのです。

コメント

スクリプト型コンポジットソフトのタイムラインの概念は別のGUIソフトで経時変化パラメータつけてcsvとかで吐き出してスクリプトでパースすればいけそうなんだよなあ。

No.1 121ヶ月前
OPAP-JP OPAP-JP
(著者)

たぶん、それは可能ですね。
AviSynthでCSVのパースをさせるのは大変そうなので、わざわざCSVにする必要はなくて、GUI側で普通にスクリプトを自動生成すればいだけです。(そういうタイプのソフトもあった気がします)

ちなみに、AviSynthにはフレーム単位でエフェクトのパラメータを変化させるAnimate関数というものがあります。
あと確かeval的な物も使えたはずなので、動的にスクリプトを生成して云々の処理も可能なはずです。(さらにいえば、JavaScriptを組み込めるプラグインもあります)



No.2 121ヶ月前
コメントを書き込むにはログインしてください。

いまブロマガで人気の記事

こうしす!ch

こうしす!ch

このチャンネルの詳細