ES2015とExtendScriptを使ってAfterEffectsのコンポジションをjsonで文字列保存する話

この記事はアドベントカレンダー23日目の記事です。
昨日の記事は@kareobanaさんの「[変換、逆変換で遊ぶ。](http://qiita.com/kareobana/items/9d50ce3a13137904eac8)」でした。

---

最近Web系のサービスを書いたり動画的なことをしたりする機会があるのですが、所用でAfterEffectsのコンポジションを文字列として書き出して再利用したいという需要がそこはかとなく湧いてきました。今回の記事では、普段余り使うかわからない保存形式の話や文字列書き出しの事例などの話とかをまとめつつ、作成した成果物の紹介します。

---

# AfterEffectsの情報を保存する諸々のファイル

### アニメーションプリセット(. ffx)
エフェクトをプリセットとして保存できる。FX Consoleと組み合わせて利用したりもできる。複数人での作業時にエフェクトを揃えたり作業効率化とかに。

### テンプレートプロジェクト(.aet)
開くと名称未設定の新規プロジェクトとして開かれるテンプレートファイル。複数人での作業時に制作の型を強制するときや作業効率化とかに。
作成するにはテンプレートにしたいファイルの拡張子を `.aep` から `.aet` に変更すれば良い。aetを変更したい場合はaepに戻せばいい。

### XML プロジェクトファイル(. aepx)
aepをバイナリではなくXML文字列として保存できる。可読性は低く人間が見て理解できるようなものではなさそう。

> 注意：XML プロジェクトファイル形式をメインのファイル形式として使用しないでください。After Effects の主要なプロジェクトファイル形式はバイナリプロジェクトファイル (.aep) 形式です。XML プロジェクトファイル形式は、プロジェクトのコピーの保存用、また自動化ワークフローの中間の形式として使用してください。

https://helpx.adobe.com/jp/after-effects/using/projects.html

### プロジェクトファイル(.aep)
プロジェクトをバイナリ保存する。バイナリ保存といいつつ結構読める(中身のエクスプレッションやレンダーキューのXML情報など)ので、aepの外部公開には気をつけよう。


文字列保存という意味では `.aepx` が良さげですが、可読性が低いのと重いのとで微妙そう。

---

# 文字列書き出しの事例
AfterEffectsの保存形式以外の選択肢として、ae-to-jsonなどがあります。

### ae-to-json
https://www.npmjs.com/package/ae-to-json

これはNode.jsで作成されたスクリプトで、AfterEffectsのすべてのデータをjsonに書き出してくれるというものです。素晴らしい。

ただ、[サンプルで公開されているjson](https://raw.githubusercontent.com/Jam3/ae-to-json/master/example/example.json)を見る限り、
- 情報が多すぎて見づらい
- すべてのコンポジションが参照されてしまい、コンポジションだけを出そうとすると一つのプロジェクトファイルに一つのコンポジションのような形にしなければいけない
という問題があり、今回の使用方法としては微妙でした。
~~そもそも試してみたけど僕の環境では動かなかった~~

---


# 【本題】コンポジションを文字列として出力する話
本題です。
今回やりたいことは特定コンポジションのjson化でしたので、CompItemオブジェクトが持つ子要素の情報を含む全部の情報を取得するようなスクリプトを書いてみました。

https://github.com/matsurai25/composition2json/releases/tag/v1.0
ここからjsxbinをダウンロードできます。拙いですがソースコードも公開してます。

![check.gif](https://qiita-image-store.s3.amazonaws.com/0/85281/e247e624-8b4f-390d-91db-1e83e94a02a0.gif)

このgifを例にしまして、

<img width="1440" alt="スクリーンショット 2016-12-23 0.33.05.png" src="https://qiita-image-store.s3.amazonaws.com/0/85281/6e097491-db56-fdcb-1e00-568932ba84f3.png">

こちらがレイヤーをいじった箇所、

|<img width="387" alt="スクリーンショット 2016-12-23 2.16.36.png" src="https://qiita-image-store.s3.amazonaws.com/0/85281/74a6dfde-3717-0fbd-c606-aaee3df9c4de.png">|<img width="376" alt="スクリーンショット 2016-12-23 2.16.56.png" src="https://qiita-image-store.s3.amazonaws.com/0/85281/7c7ef327-18a4-915d-394d-285dfbf8d634.png">|<img width="477" alt="スクリーンショット 2016-12-23 2.17.23.png" src="https://qiita-image-store.s3.amazonaws.com/0/85281/5724f121-b050-0220-94d3-ddf6155915d9.png">|
|---|---|---|

こちらが出力されたjsonになります。(全文は長いので[こちら](https://github.com/matsurai25/composition2json/blob/master/src/sample.json))


# スクリプトの中身
[先日の記事]()でExtendScriptでES2015やJSONオブジェクトを使用する話などをしたかと思いますので、それを利用します。

### クラスオブジェクトの再現
普通にJSON.stringify等オブジェクトの全値を参照しようとすると、

- ライトレイヤーでないのにライトレイヤー周りのkeyが呼ばれてエラー
- 子レイヤーが配列的に取得できずに.layer(1)のようにメソッドを通さなければいけない
- 子レイヤーのオブジェクトが親コンポジションの完全なオブジェクトを持ってしまっているので無限ループする

等色々問題が会って面倒だったので、ES2015のclassやextendsを使用して再現することにしました。C2J.getObject(obj)でobjを判定してそれをラップして使いやすくしたオブジェクトを返します。
なお、クラス構造などに関しては[Hiroshi Saitoさん](@https://twitter.com/hiroshisaito)の[AEスクリプトリファレンス](http://aejsx.hiroshisaito.net/)を参考にしています。

### デフォルトのプロパティを削除
今回欲しいのは「どこをどう変更したか」という情報だったので、デフォルト値から動きのない値はgetObject後に残さないようにしました。これによりかなりの容量削減、可読性向上ができます。
幸いにしてそれぞれをクラスとして書いていましたので、それぞれのクラスのconstructorで判定します。

https://github.com/matsurai25/composition2json
詳しい構造とかはこちらをご参照ください　

# jsonで出せて何が嬉しいのか
コンポジションをjsonで出せると何ができるか。

- 変更点を明示しやすい(gitのような差分管理が使える)
- 文字列から逆にコンポジションへ再現するような処理が書けるようになる
- 何を行っているかという行為を表しているので、モーションのAE以外への移植が行いやすくなる。

とかでしょうか。

<img width="471" alt="スクリーンショット 2016-12-23 2.38.11.png" src="https://qiita-image-store.s3.amazonaws.com/0/85281/92b2d5f6-26a0-21eb-cde8-0b6ab1e8f59a.png">

以前作成した[TalkOnAE](https://twitter.com/matsurai25/status/670243599548706819)~~(今はもう寂れてしまった趣がある)~~で行ったAE上でWEBのAPIとつなぎこんで色々するというのが個人的にすごく大好きなので、超強化版としてAE上から使えるフリーコンポジションマネージャー+SNSのようなものを作成しようとしています。ご協力いただける方はぜひ@matsurai25まで。


# 宣伝
こんな感じのを僕がコラムで書いてるEverydayOneMotionメイキングブックというものがありますので、よろしければお手にとって見て下さい。スクリプトとか色管理の効率化(+α)とかをやると思います。
http://motions.work/c91/

明日のAfterEffectsアドベントカレンダーは、@Misaki_Akatsukiさんで「大事な予定を忘れない為に今すぐ覚えたいスクリプトのテクニック」です。