[AfterEffects Script]コンポジションマーカーの情報を取得

最近は仕事の片手間に(というか仕事で使うためにも)ofxAEという、AfterEffectsで作ったアニメーションをopenFrameworksで動かすためのライブラリを作っています。
(Contributor超募集してます!)

作ってる目的の一つにはデザイナとプログラマの分業がよりうまくいくようにするというものがあるので、
そのためにデザイナが書ける簡易スクリプトみたいなものを実装したい。
例えばあるフレームから別のフレームにジャンプしたり、ループ範囲を指定したり、ある条件でテクスチャを変更したり、など。

時間軸上に配置できる、長さを持つ、文字が入力できる、といった点からコンポジションマーカーがまさにうってつけなんだけど・・・

なんとAfterEffectsのスクリプトではコンポジションマーカーにはアクセス出来ないらしい。なんてこった。
After Effects Script Reference - MarkerValue Object

結論から言うと、できました。
もちろん素直な方法ではないですが、そんなに行儀の悪い方法でもないと思います。

  • スクリプトからレイヤーマーカーにはアクセスできる。
  • コンポジションを選択した状態で「ファイル」->「複数アイテムから新規コンポジション」を使うとマーカーの情報を保ったままレイヤーとして新規コンポジションに配置される。
    (CompItem.add(CompItem)ではマーカーの情報が落ちてしまう)
  • よって、対象のコンポジションを選択状態にして「複数アイテムから新規コンポジション」を実行し、そこに配置されたレイヤーからマーカーを取得すればよい。

というわけでできたコードがこちらです。

/*
AfterEffectsでコンポジションマーカーを取得するスクリプト
2013.10.31 by nariakiiwatani
MIT License - http://sourceforge.jp/projects/opensource/wiki/licenses%2FMIT_license
*/

// マーカーの情報を取得したいコンポジションを渡す
function getCompMarker(comp) {

// プロジェクトに含まれるコンポジションのリストを取得
function getCompAll(proj) {
	var ret = [];
	for(var i = 1; i <= proj.numItems; ++i) {
		if(proj.item(i) instanceof CompItem) {
			ret.push(proj.item(i));
		}
	}
	return ret;
}
// 配列の差分を取得
function getArrayDiff(a, b) {
	var ret = [];
	for(var _a in a) {
		var found = false;
		for(var _b in b) {
			if(a[_a] === b[_b]) {
				found = true;
				break;
			}
		}
		if(!found) {
			ret.push(a[_a]);
		}
	}
	var tmp = a;
	a = b;
	b = tmp;
	for(var _a in a) {
		var found = false;
		for(var _b in b) {
			if(a[_a] === b[_b]) {
				found = true;
				break;
			}
		}
		if(!found) {
			ret.push(a[_a]);
		}
	}
	return ret;
}

// プロジェクトウィンドウの選択情報を操作するので、操作前の状態を保存しておく
var selected = app.project.selection;
var selection = [];
for(var i = 0; i < selected.length; ++i) {
	selection.push(selected[i].selected);
	selected[i].selected = false;
}

// ここから処理の本体
comp.selected = true;	// 書き出し対象のコンポジションを選択状態にする
// 「複数アイテムから新規コンポジション」はプロジェクトウィンドウにフォーカスしていないと使えないので強制的にアクティブにする
app.project.showWindow(false);
app.project.showWindow(true);

var allComps = getCompAll(app.project);	// コマンド実行前のコンポジションのリスト
app.executeCommand(2796);	// 「複数アイテムから新規コンポジション」を実行
var added = getArrayDiff(getCompAll(app.project), allComps)[0];	// コマンド実行によって追加されたコンポジションを探す
var marker = added.layer(1).marker;	// これが欲しかったマーカー!

// ここから後片付け
added.remove();	// 増やしたコンポジションを削除
comp.selected = false;	// 選択状態を解除
for(var i = 0; i < selected.length; ++i) {	// スクリプト実行前の選択状態に戻す
	selected[i].selected = selection[i];
}
// マーカー情報を返す
return marker;
}

getCompMarkerに取得したいCompItemを渡してやればマーカーのPropertyObjectが返ってきます。

これで俄然ofxAEの開発が楽しくなってきました。

参考サイト。ありがとうございます!

AEP Project – CommandID
After Effects Script Reference