aftereffects-declarative
After Effects を宣言型 JSON で構築する標準スキル。
新規構築・再実行性の高い編集でこのスキルを優先し、既存シーンの外科的な部分修正は命令型スキルを優先する。
目的
- 1ファイルの scene JSON で comp 構成を一括適用
- 再実行時は
layers[].idで upsert 再利用 - 人手編集後も再適用しやすい運用に寄せる
使い分け(重要)
- 宣言型を使う:
- 新規 comp / 新規レイヤー群を組み上げる
- 同種変更を複数箇所へ展開する
- scene JSON を成果物として残し、再実行可能にしたい
- 命令型(
aftereffects-cli)を使う:- 人間が作った既存シーン(scene JSON 未管理)へ部分修正を入れる
- 複雑な既存レイヤーに expression をピンポイント適用する
- comp 全体の再宣言を避け、局所的に安全修正したい
- 併用方針:
- まず命令型で調査・局所修正し、安定して繰り返す段階で宣言型へ移行する
基本フロー
ae-cli healthで疎通と、開いている.aepの絶対パスを確認~/ae-agent-skills/scene.schema.jsonと~/ae-agent-skills/references/scene.example.jsonを確認(フッテージ編集はfootage-edit.example.json、プリコンポ配置はcomp-assembly.example.jsonも確認)- 対象
.aepと同じ案件ディレクトリに scene JSON と案件固有の生成スクリプトを作成/更新(サブディレクトリ名は_edl/を推奨するが強制しない) --expect-project <対象.aep>を付けて--validate-onlyで検証- 同じ
--expect-projectを付けて実適用 - apply失敗時はCLIの
Rollback診断を読み、succeededでもcomp / ProjectItem / layerを確認する。rollback後は内容が戻ってもdirtyがtrueになり得る - compを直接指定した
layers/properties --include-keyframes/bounds/expression-errorsで数値確認 snapshotで見た目をPNG確認- scene JSON は
.aepと一緒に案件側の履歴管理・同期へ含める。作業中/完了版を別ディレクトリへコピーして二重管理しない
参照ファイル(固定)
- schema:
~/ae-agent-skills/scene.schema.json - サンプル:
~/ae-agent-skills/references/scene.example.json - フッテージ編集サンプル:
~/ae-agent-skills/references/footage-edit.example.json - プリコンポ配置サンプル:
~/ae-agent-skills/references/comp-assembly.example.json - CLIリファレンス(日本語):
~/ae-agent-skills/references/cli.ja.md - CLIリファレンス(英語):
~/ae-agent-skills/references/cli.md
ファイル運用ルール(重要)
- 横断再利用するエンジン、schema、referenceは
~/ae-agent-skills/に置く - 案件固有の scene JSON、EDL、生成スクリプトは対象
.aepと同じ案件ディレクトリに置く - 案件ディレクトリ直下を散らかさない場合は
_edl/を推奨のサブディレクトリ名として使う。既存の案件構成へは強制しない work//done/へのコピー運用は行わない。履歴は案件側のGit、同期ストレージ、バックアップへ一本化する- 例:
ae-cli apply-scene --scene-file /path/to/project/_edl/main.scene.json --expect-project /path/to/project/main.aep --validate-onlyae-cli apply-scene --scene-file /path/to/project/_edl/main.scene.json --expect-project /path/to/project/main.aep
コマンド
ae-cli health
ae-cli list-footage
ae-cli apply-scene --scene-file <scene.json> --expect-project <project.aep> --validate-only
ae-cli apply-scene --scene-file <scene.json> --expect-project <project.aep>
ae-cli apply-scene --scene-file <scene.json> --expect-project <project.aep> --mode replace-managed
ae-cli apply-scene --scene-file <scene.json> --expect-project <project.aep> --mode clear-all
ae-cli layers --comp-name <comp>
ae-cli properties --layer-name <layer> --comp-name <comp> --include-group <group> --include-group-children --include-keyframes [--filter <regex>] [--include-expression] [--include-disabled]
ae-cli properties --layer-name <layer> --comp-name <comp> --property-path <matchName.path>
ae-cli bounds --layer-name <layer> --comp-name <comp> --time <sec>
ae-cli expression-errors --comp-name <comp>
ae-cli snapshot --comp-name <comp> --time <sec> --out <absolute.png> [--scale <S>] # 0 < S <= 1
apply mode 指針
merge(既定): 既存維持 + 宣言分だけ upsertreplace-managed:aeSceneId:*の管理対象だけ差し替えclear-all: comp を空にして完全再宣言
scene 設計ルール
layers[].idは必須推奨(upsert の安定キー)layers[].parentIdは scene id を参照parentIdを持つレイヤーのtransformは親座標系で宣言し、初回適用と再適用で同じ値を使う- 推測でキーを作らず、必ず
~/ae-agent-skills/scene.schema.jsonを正として合わせる - アニメーション対象プロパティは
animationsで管理 animations[].keyframeModeは既定のreplaceを使い、宣言したキー集合へ完全に置換する- 既存の宣言外キーを意図的に残す場合だけ
keyframeMode: mergeを使う - キーを全削除する場合は
keyframes: []を宣言する keyframes: []後の静止値も所有する場合は、同じpathの値をtransformまたはpropertyValuesに宣言する。未宣言ならAEがキー削除後に保持する値を使う- 同じレイヤー内で同一
propertyPathを複数のanimationへ分割しない - 3Dベクトルには2D入力可(
[x,y] -> [x,y,0]自動補完) - Repeater は
layers[].repeaters[] - Effect 値は
layers[].effects[].params[] - expression は
layers[].expressions[] - Essential Graphics は
layers[].essentialProperties[] - フッテージは
assets[]に1度宣言し、type: footageのレイヤーからsourceIdで参照する - 既存コンポは
assets[]にtype: compとcompIdまたは一意なcompNameで宣言し、type: compのレイヤーからsourceIdで参照する - コンポレイヤーの本編上の配置は
timing.startTime/inPoint/outPointを使う - フッテージの
assets[].pathは絶対パス、scene JSONからの相対パス、または${MEDIA_ROOT}/...のような環境変数付きパスを使える。CLIは適用前に絶対パスへ解決し、未定義変数はエラーにする - カット編集は
timing.sourceIn/sourceOut/timelineInを使う sourceInとsourceOutは必ず対で指定し、同じsourceIdを複数レイヤーから参照してよい- フッテージのカット指定と
inPoint/outPoint/startTimeは混在させない - 音声調整はフッテージレイヤーの
audioで宣言する audio.mutedはミュート状態、audio.levelDbは左右共通のdB値、audio.fadeIn/fadeOutは秒数audio.mutedの既定はfalse、audio.levelDbの既定は0 dB、未指定のフェードは0秒として、再適用時に音声状態を作り直すaudio.fadeIn + audio.fadeOutはカット後のレイヤー尺以内にするaudioと汎用animations/propertyValuesから同じAudio Levelsを同時管理しない- テキストレイヤー全体のスタイルは
textStyleで宣言する textStyle.fontはae-cli list-fontsで取得したPostScript名を使うfillColor/strokeColorは0〜1または0〜255のRGB配列を使うtextStyle.leadingは手動行送りへ切り替わるため、autoLeading: trueと併用しないtextStyleはレイヤー全体の基準スタイル。文字範囲はtextStyleRanges[]、Range SelectorアニメーションはtextAnimators[]を使うtextStyleRanges[]は0始まり・終端を含まないstart/endと文字スタイルを宣言する。After Effects 24.3以降が必要textStyleRangesは再適用時に基準スタイルへ戻せるよう、同じレイヤーのtextStyleと必ず併用するtextAnimators[]はid、Position / Scale / Opacity / Rotation、selectorのStart / End / Offset / Amountとそのanimationを宣言する- selectorの詳細は
units(1〜2)、basedOn(1〜4)、shape(1〜6)、smoothness(0〜100)、easeHigh/easeLow(-100〜100)で宣言する - AEが通常列挙しないselector propertyの往復確認には
properties --property-path <matchName path>を使う textAnimatorsを宣言したレイヤーではaeSceneTextAnimator:*管理アニメーターを置換する。人手作成の別名アニメーターは保持する- 整列・分布はトップレベルの
layout[]に上から順に宣言し、layerIdsはscene layer idを参照する alignはhorizontal/vertical、distributeはaxisとmode: gaps | centersを指定するvisual-centerはvisual bounds中央へアンカーポイントを移し、見た目の位置を保持する。通常はalignより前に置く- 基準は
comp/action-safe/title-safe/selection。safe既定値は10% / 20%で、必要ならmarginPercentで上書きする - layout対象は可視2D AVレイヤーに限る。3D、3D親子関係、Position expressionは使わない
- 2D親子付きレイヤーはlayout対象にできる。親transformを含むvisual boundsから親座標系へ書き戻す
- expression 内の effect 参照は表示名ではなく matchName を推奨(例:
ADBE Slider Control-0001) easeIn/easeOutは[speed, influence]。influenceは0.1〜100の百分率- EffectカラーはAEネイティブRGBA
[r,g,b,a](0〜1)を使い、パラメータは事前にpropertiesで確認する
再適用セマンティクス
- 既存compにも
composition.width/height/duration/frameRate/pixelAspectを宣言値として適用する --validate-onlyのcompositionChangesでcomp設定の変更予定を確認する- animationは既定で既存キーを削除してから再構築するため、人手キーを残す場合は明示的に
keyframeMode: mergeを選ぶ - runtime error時は専用Undo groupを自動rollbackし、transaction markerの消失で成功を検証する。markerを確認できない場合は無関係な履歴を戻さない
- rollback成功後もAEのproject dirty状態は保存時点へ戻らない場合がある。CLIは自動保存しない
フッテージ音声の例
{
"id": "clip-01",
"type": "footage",
"name": "Interview 01",
"sourceId": "interview",
"timing": {
"sourceIn": 12.5,
"sourceOut": 18,
"timelineIn": 0
},
"audio": {
"muted": false,
"levelDb": -6,
"fadeIn": 0.5,
"fadeOut": 0.75
}
}
テキストスタイルの例
{
"id": "title",
"type": "text",
"name": "Title",
"text": "Hello Agent",
"textStyle": {
"font": "ArialMT",
"fontSize": 96,
"fillColor": [255, 240, 210],
"strokeEnabled": true,
"strokeColor": [18, 34, 56],
"strokeWidth": 4,
"tracking": 20,
"leading": 110,
"justification": "center"
}
}
配置の例
"layout": [
{
"type": "align",
"layerIds": ["title"],
"reference": "title-safe",
"horizontal": "center",
"vertical": "top",
"offset": [0, 24]
},
{
"type": "distribute",
"layerIds": ["card-a", "card-b", "card-c"],
"reference": "action-safe",
"axis": "horizontal",
"mode": "gaps"
}
]
最小テンプレート(このまま使える)
以下を対象案件の _edl/min.scene.json として保存して、そのまま validate/apply できる。
{
"composition": {
"name": "Skill_Minimal_Test",
"width": 1280,
"height": 720,
"duration": 3,
"frameRate": 30,
"pixelAspect": 1,
"createIfMissing": true,
"setActive": true
},
"layers": [
{
"id": "t1",
"type": "text",
"name": "Hello",
"text": "Skill only test",
"textStyle": {
"fontSize": 72,
"fillColor": [255, 255, 255],
"justification": "center"
},
"transform": {
"position": [640, 360],
"opacity": 100
}
}
],
"layout": [
{
"type": "align",
"layerIds": ["t1"],
"reference": "title-safe",
"horizontal": "center",
"vertical": "center"
}
]
}
ae-cli apply-scene --scene-file /path/to/project/_edl/min.scene.json --expect-project /path/to/project/main.aep --validate-only
ae-cli apply-scene --scene-file /path/to/project/_edl/min.scene.json --expect-project /path/to/project/main.aep
propertyPath 運用ルール(汎用)
- 目的: 実装コードを読まずに
propertyPathを安定して決める。 propertyPathは基本的に matchName ベースで指定する(表示名依存を避ける)。- 適用前に
ae-cli propertiesで対象レイヤーの実パスを確認し、出力に合わせて JSON へ転記する。 - Shape 内部プロパティは次の順で辿る:
ADBE Root Vectors Group(Contents)ADBE Vector GroupADBE Vectors Group- 各要素(例: Shape Path / Fill / Stroke / Filter)
- Effect パラメータ参照は
layers[].effects[].params[]でも expression でも matchName 優先にする。 - 迷ったら「推測で書く」のではなく、先に
properties出力を正として合わせる。
標準デバッグ手順(実装コードを読まない)
ae-cli healthのproject.pathが対象.aepと一致することを確認ae-cli apply-scene --scene-file <scene.json> --expect-project <project.aep> --validate-onlyae-cli apply-scene --scene-file <scene.json> --expect-project <project.aep>ae-cli expression-errors --comp-name <comp>で失敗箇所を確認- 対象レイヤーに対して
ae-cli properties --layer-name <layer> --comp-name <comp> --include-group <group> --include-group-children --include-keyframesを実行し、propertyPathとキーを確認 - 実寸が関係する場合は
ae-cli bounds --layer-name <layer> --comp-name <comp> --time <sec>でcomp座標のvisual boundsを確認 ae-cli snapshot --comp-name <comp> --time <sec> --out <absolute.png> [--scale 0.5]で見た目を確認- scene JSON を修正して、同じ
--expect-projectを付けて再適用
トラブル時
- validation 失敗:
- JSON構造と型を確認
- apply失敗:
Rollback: succeededと表示されても、health/list-comps/list-footage/layersで対象が元へ戻ったことを確認する- rollback後にdirtyだけがtrueなら、自動保存せず内容を確認してから保存またはproject再読み込みを判断する
- rollback失敗または未検証なら部分変更が残り得るため、対象を確認するまで再適用しない
- expression が効かない:
ae-cli expression-errors
- 意図しない新規レイヤー作成:
layers[].id未指定/変更を確認
- 旧レイヤーが残る:
apply-scene --mode replace-managedまたは--mode clear-allを使う
- 既存シーンへ局所修正したい / 宣言型で表現しづらい:
aftereffects-cliへ切り替え