見出し画像

[Ae]人数と尺に合わせて自動で動くエンドロールの作り方

人数可変・尺固定(つまり人数が多いほど速い)、役職名は別スタイルのエンドロールを、CSVの差し替えだけで更新できる仕組みをAfter Effectsでエクスプレッションを使って作る方法を記事としてまとめます!
元ネタはこちらの記事です。

今回作るのは下図のようなエンドロールです。
ポケモン赤緑の道路をいくつかピックアップして、そこに登場するトレーナー名を使わせていただきました。(ポケモン 赤 緑 青 ピカチュウ 攻略 wiki

エンドロール_3

方針としてはCSVの内容を連結して一つのテキストレイヤーに流し込んで、それの高さを取得して時間内でスクロールし終わるように動かし、役職名のスタイルはテキストアニメーターとエクスプレッションセレクターで調整する、という感じです。

CSVの準備・読み込み

Googleスプレッドシートでこのようなシートを作り、CSVとしてダウンロードして読み込ませます。

スクリーンショット 2021-10-21 0.57.42

コンポジション内にCSVを入れ、ソーステキストに下記のエクスプレッションを設定します。(ファイル名は適宜調整)

var endText = "";
for (var i=0;i<thisComp.layer("data.csv")("データ")("行数");i++){
	if (footage("data.csv").dataValue([0, i])) endText += '\r\n' + footage("data.csv").dataValue([0, i]) + '\r\n';
	endText += footage("data.csv").dataValue([1, i]) + '\r\n';
}
endText;

テキストレイヤーのフォントや文字サイズを調整すると、こんな感じになります。

スクリーンショット 2021-10-21 1.30.36

このエクスプレッションは、改行('\r\n')を挟んで名前を連結して、「遭遇場所」にテキストが入っているときは改行+遭遇場所+改行を追加するものなので、このような見た目になります。

スタイルを調整する

1つのテキストレイヤーの一部分だけ調整したいので、テキストアニメーターを使います。
よくある使い方は範囲セレクターを動かして1文字ずつ出現させるアニメーションを作ったりなのですが、もちろん止めたままにもできますし、エクスプレッションセレクターを使うことで、JavaScriptで複雑な指定をすることもできます。

パターン1:遭遇場所(役職名)を少し小さくする

まず範囲の前に先に大きさを指定します。
アニメーターの隣りの▶を押してスケールを選び、少し小さくします。

スクリーンショット 2021-10-21 1.43.27

すると文字の間隔が空いてしまうので、先程追加された「アニメーター1」の隣りの▶を押してプロパティ→字送りを追加して狭くします。

スクリーンショット 2021-10-21 1.45.00

全ての文字が小さくなっているので、これからエクスプレッションセレクターを追加して特定の文字だけを対象にします。
先程の▶を押し、セレクター→エクスプレッションを選びます。

スクリーンショット 2021-10-21 1.46.38

遭遇場所(役職名)の部分だけ適用したいので、基準を「行」に変更し、下記のエクスプレッションを入力します。

var target = [];
for (var i=0;i<thisComp.layer("data.csv")("データ")("行数");i++){
	if (footage("data.csv").dataValue([0, i])) target.push(footage("data.csv").dataValue([0, i]));
}

var endRow = [];
for (var i=0;i<thisComp.layer("data.csv")("データ")("行数");i++){
	if (footage("data.csv").dataValue([0, i])) endRow.push("", footage("data.csv").dataValue([0, i]));
	endRow.push(footage("data.csv").dataValue([1, i]));
}

var out = 0;
for (var i=0;i<target.length;i++) {
	if (target[i] == endRow[textIndex-1]) {
		out = 100;
		break;
	} else {
		out = 0;
	}
}
out;

思ったより複雑なコードになってしまいましたが、無事小さくすることができました!

スクリーンショット 2021-10-21 4.23.39

スクリーンショット 2021-10-21 4.25.52

パターン2:名前を少し大きく太字にする

パターン1のコードのif文の中の「out = 」のあとの100と0を入れ替えれば、アニメーターの設定が逆に名前の方に反映されるようになるので、それに変えてスケールと字送りを少し大きくします。
太字は簡易的にはなりますが、アニメーターで線幅を設定することができるので、テキストレイヤーのスタイルを「線の色あり、幅0px」にしておいて、アニメーターで調整します。

スクリーンショット 2021-10-21 4.39.03

するとこんな感じになります。

スクリーンショット 2021-10-21 4.35.50

スクリーンショット 2021-10-21 4.41.19

アンカーポイントにエクスプレッションを設定して動かす

テキストを画面外すぐ下に隠し、下記のエクスプレッションをアンカーポイントに設定することで、高さに合わせた速さで動かすことができます。

スクリーンショット 2021-10-26 3.57.43

var n = thisLayer.sourceRectAtTime();
[n.width/2+n.left, (n.height+thisComp.height+100)*time/20];

+100はテキストが1行のときの大体の高さ、time/20の20は何秒でスクロールさせ終わるかの秒数です。
今回のものは20秒でテキストが画面を通り過ぎます。

別デザインVer

例えばこういうタイプなら、2つのテキストレイヤーを用意してそれぞれにスタイルを当てることで、エクスプレッションセレクターでの複雑な指定なく作ることができます。

エンドロール_4

スクリーンショット 2021-10-26 4.25.15

スクリーンショット 2021-10-26 4.25.28

役職名ソーステキスト用エクスプレッション

var endText = "";
for (var i=0;i<thisComp.layer("data.csv")("データ")("行数");i++){
	if (footage("data.csv").dataValue([0, i])) endText += '\r\n' + footage("data.csv").dataValue([0, i]);
	endText += '\r\n';
}
endText;

名前ソーステキスト用エクスプレッション

var endText = "";
for (var i=0;i<thisComp.layer("data.csv")("データ")("行数");i++){
	if (footage("data.csv").dataValue([0, i])) endText += '\r\n';
	endText += footage("data.csv").dataValue([1, i]) + '\r\n';
}
endText;

アンカーポイント用エクスプレッションは前パターンと同様です。

まとめ

After Effectsで更新の多いエンドロールを作るならこんな感じかと思います!
After Effectsでの長文もしくは大量のテキストの追加や削除はしんどいので、やはりCSVを使うのがやりやすいかな〜と思います。
Premiereならロールを設定することで、動かす部分のエクスプレッションは書かずに済みますが、結局テキストの調整が大変なのは同じなので、何度も調整する予定があるなら、今回のやり方の方が分があるかなと思います。
Adobe XDのようなキャンバス外も見えるツールで縦長の画像を作成して読み込ませて、エクスプレッションでスクロールさせる方法も一考の余地ありですね…!

追記 2021/10/28 めちゃ重いらしい!!

データ量が多いとめちゃくちゃ重くなってレンダリング時間が70時間超えとかになるみたいです!どひゃー!!!
原因は、AEのエクスプレッションは変数を保持できなくて、イチから毎フレ計算し直すせいですね…

対策としては重いエクスプレッションの計算を何とか一度だけにする、あるいはもう長い画像で書き出してしまうか、かと思います…!
一旦前者の方法を書きますが、これがベストなフローかというと何とも言えないところですね…

① テキストレイヤーをプリコンポーズして「フレームを固定」する

まず、アンカーポイントに設定したスクロールするエクスプレッションを外して、テキストをプリコンポーズします。
CSVが同階層になくエラーになるかと思うので、新しく作ったコンポ内にもCSVがある状態にします。

そうしたら親階層へ戻って、今作ったテキストのコンポを右クリックで「時間」→「フレームを固定」します。

スクリーンショット 2021-10-28 5.20.57

これで一旦CSVの表示とスタイルの設定は1フレだけの計算になるかと思います。
ただ、これだとはみ出た部分が切り取られてしまっているので、コラップストランスフォームをオンにします。

スクリーンショット 2021-10-28 5.24.27

スクリーンショット 2021-10-28 5.24.56

次は高さを取得してスクロールさせたいのですが、この高さをsourceRectAtTimeを呼んでいるところから引っ張ってくると、毎フレまた重い計算が走ってしまうみたいなので、非常に残念ですが手打ちします…!

② 高さを手打ちしてスクロールさせる

テキストのコンポの中へ入って、テキストレイヤーのすぐ下に表示用のテキストレイヤーをガイドレイヤーにして作成します。

スクリーンショット 2021-10-28 5.47.04

ソーステキストのエクスプレッションに下記を設定して、フォントサイズや色を見やすいものにします。(Math.roundは四捨五入です)

var n = thisComp.layer(1).sourceRectAtTime();
Math.round(n.height);

スクリーンショット 2021-10-28 5.46.10

今回のデータだと高さは2867pxほどのようです。
親階層に戻ってテキストのコンポのアンカーポイントに下記のエクスプレッションを数字を変えて設定します。

[thisComp.width/2, (2867+thisComp.height+100)*time/20+thisComp.height/2];

これでだいぶサクサク動くようになったのではないでしょうか…!

更新する人がAEに不慣れな場合は、エフェクトの「スライダー制御」を設定して参照するようにしておいて、そちらに値を入れてもらうようにすると、エクスプレッションを壊される心配はないですが、英語版AEやバージョンの違いなどでエラーが出ないようにするにはちょいひと手間要ります。

スクリーンショット 2021-10-28 5.54.38

[thisComp.width/2, (effect("スライダー制御")("スライダー")+thisComp.height+100)*time/20+thisComp.height/2];

調整すると下記になります。

[thisComp.width/2, (effect("ADBE Slider Control")(1)+thisComp.height+100)*time/20+thisComp.height/2];

大きなデータでのレンダリング検証はできていませんが、明らかにプレビューの速度が違うので、効果はあるかと…!

最後まで読んでくれてありがとうございます! 良ければサポートしてもらえると嬉しいです!