BMS, Movie, Illustrations, Programming

マーカーとエクスプレッションを活用したカット切り替え(ホワイトイン・ホワイトアウト)【After Effects】

よくあるやつをやっただけですが、せっかくコードを書いたので晒しておきます。

使い方

ホワイト平面の不透明度に後述のエクスプレッションを指定すると、レイヤーマーカーを配置するだけで不透明度がなめらかに変化し、簡単にホワイトイン・ホワイトアウトが実現できます。ブラック平面を使用すると、ブラックイン・ブラックアウトになります。

マーカーはテンキーの * (アスタリスク) のショートカットキーで簡単に追加することができます。

また、マーカーのコメントに < と記載すると、不透明度の上昇(ホワイト平面の場合はホワイトアウト)のみが有効になります。
(クレッシェンドのイメージ)

マーカーのコメントに > と記載すると、不透明度の減少(ホワイト平面の場合はホワイトイン)のみが有効になります。
(デクレッシェンドのイメージ)

実装方法

レイヤーに指定されたマーカーの時刻とマーカーのコメントを取得し、それによって処理を行っています。

マーカーの情報の取得は以下のようなコードで実現できます。

function getAllMarkerLabels(layer) {
  const markers = layer.marker;

  for (let i = 0; i < markers.numKeys; i++) {
    const markerKey = markers.key(i + 1);
    const markerComment = markerKey.comment;
    const markerTime = markerKey.time;
  }
}

getAllMarkerLabels(thisLayer);

他にも marker.nearestKey(t) を使用する方法などもあります。

https://helpx.adobe.com/jp/after-effects/using/expression-language-reference.html

また、他の「MarkerKey の属性」及び「Key オブジェクトの属性」も利用できます。

  • markerKey.index
  • markerKey.time
  • markerKey.comment
  • markerKey.duration

これを応用すれば色々なエクスプレッションを書くことができます。

利用イメージ

コード

このコードを不透明度のエクスプレッションに貼り付けてください。

const TRANSITION_IN_SPEED_EXPONENT = 2.5;
const TRANSITION_OUT_SPEED_EXPONENT = 3.5;
// const 半減期 = Math.log(2) / TRANSITION_SPEED_EXPONENT
//             ≒ 0.693 / TRANSITION_SPEED_EXPONENT 【秒】
const MAX_OPACITY = transform.opacity;

// 全てのレイヤーマーカーの情報を配列にして返す
function getAllMarkerLabels(layer) {
  const markers = layer.marker;
  const markerInfos = [];

  // Loop through all markers
  for (let i = 0; i < markers.numKeys; i++) {
    const marker = markers.key(i + 1);
    markerInfos.push({
      comment: marker.comment || "", // Use empty string if comment is null/undefined
      time: marker.time,
      index: i,
    });
  }

  return markerInfos;
}

// 不透明度を計算して number を返す
function calculateTransitionOpacity(markerInfos, currentTime) {
  let transparency = 100;

  for (let i = 0; i < markerInfos.length; i++) {
    const m = markerInfos[i];
    const distance = Math.abs(currentTime - m.time);

    const isIn = m.comment.includes("<");
    const isOut = m.comment.includes(">");

    if (currentTime < m.time) {
      if (isIn || (!isIn && !isOut)) {
        transparency *= 1 - Math.exp(-TRANSITION_IN_SPEED_EXPONENT * clamp(distance, 0, 10));
      }
    } else {
      // Including the case where currentTime === m.time
      if (isOut || (!isIn && !isOut)) {
        transparency *= 1 - Math.exp(-TRANSITION_OUT_SPEED_EXPONENT * clamp(distance, 0, 10));
      }
    }
  }

  return MAX_OPACITY * 0.01 * (100 - transparency);
}

// 不透明度を計算する
calculateTransitionOpacity(getAllMarkerLabels(thisLayer), time);

関連リンク

[エクスプレッション]マーカーを使って不透明度をフェードインさせる_maker | EverydaySkillShare

[Ae]レイヤーマーカーでテキストを管理する|寿司の妖精

以下のリンクでは expo ではなく自由にキーフレームを指定してアニメーションを作成できるようです。

マーカーでリズムを刻むエクスプレッションアイディア | SHADECO