con un clic
manage-ae
// Manage After Effects from Claude — create configs, build compositions, render videos, diagnose issues, and optionally generate AI content via Prompture
// Manage After Effects from Claude — create configs, build compositions, render videos, diagnose issues, and optionally generate AI content via Prompture
Create and validate JSON automation configs for the After Effects automation pipeline
Add methods to existing mixins or create new mixins for the After Effects automation client
Write unit tests following the project's existing patterns and conventions
Create ExtendScript/JSX files that integrate with the Python-to-AE file-based command bridge
| name | manage-ae |
| description | Manage After Effects from Claude — create configs, build compositions, render videos, diagnose issues, and optionally generate AI content via Prompture |
| metadata | {"author":"after-effects-automation","version":"1.0"} |
This skill lets you directly control Adobe After Effects: create automation configs, run pipelines, render videos, diagnose setup issues, and optionally generate AI-powered content using Prompture.
| Action | How |
|---|---|
| Create a config | Build a JSON config file with project settings, timeline, and custom actions |
| Run automation | Execute ae-automation run <config.json> to launch AE, build compositions, and render |
| Render a video | Use the Python API or CLI to render a specific comp from an .aep file |
| Diagnose setup | Run ae-automation diagnose to check AE installation, paths, and scripting |
| Generate template | Run ae-automation generate --template <name> to create .aep files from built-in templates |
| Export video | Run ae-automation export --template <name> to generate + render in one step |
| AI content | Use Prompture to generate text, scripts, scene descriptions, then feed into a config |
Ask the user:
You need:
.aep template file (or use ae-automation generate to create one)Create a JSON file with this structure:
{
"project": {
"project_file": "path/to/template.aep",
"comp_name": "MainComp",
"comp_fps": 30,
"comp_width": 1920,
"comp_height": 1080,
"comp_start_time": "00:00:00",
"comp_end_time": 30,
"output_file": "output.mp4",
"output_dir": "path/to/output",
"renderComp": true,
"debug": false,
"resources": []
},
"timeline": [],
"templates": {}
}
Important conventions:
comp_name is the main composition where scenes are assembled"debug": true to test config loading without launching AEAdd external assets to project.resources:
"resources": [
{"type": "image", "name": "bg", "path": "C:/assets/background.png"},
{"type": "audio", "name": "music", "path": "C:/assets/bgm.mp3"},
{"type": "video", "name": "clip", "path": "C:/assets/footage.mp4"}
]
name is the identifier used to reference this asset in timeline actions"duration" manuallyEach scene duplicates a template composition and applies custom actions:
"timeline": [
{
"name": "intro",
"duration": 5,
"startTime": 0,
"template_comp": "IntroTemplate",
"reverse": false,
"custom_actions": [
{
"change_type": "update_layer_property",
"comp_name": "IntroTemplate",
"layer_name": "Title",
"property_name": "Text.Source Text",
"property_type": "string",
"value": "Welcome"
}
]
}
]
Scene naming: The duplicated comp is named slug(scene_folder + " " + template_comp). For scene index 0, the folder is scene-1, so the comp becomes scene-1-IntroTemplate. Use this derived name in comp_name for custom actions.
8 action types available:
change_type | Purpose | Key fields |
|---|---|---|
update_layer_property | Set text, color, position | comp_name, layer_name, property_name, property_type, value |
update_layer_property_at_frame | Set keyframe at specific frame | Same + frame |
add_resource | Add imported asset to comp | resource_name, comp_name, startTime, duration |
edit_resource | Modify resource layer timing | comp_name, layerIndex, startTime, duration |
swap_items_by_index | Replace layer source | comp_name, layer_index, layer_name |
add_marker | Add composition marker | comp_name, layer_name, marker_name, marker_time |
add_comp | Nest a composition | comp_name, startTime, duration |
template | Apply reusable template | template_name, template_values |
Property dot-notation paths:
Text.Source Text — text contentTransform.Position — [x,y]Transform.Scale — [x,y]Transform.Opacity — 0-100Transform.Rotation — degreesEffects.ColorEffect.Color — effect colorEffects.SliderControl.Slider — effect sliderValue formats:
"value": "Hello""value": "#FF0000" with "property_type": "color" (auto-converted to AE RGBA)"value": "[960,540]" (string representation, parsed by framework.js)"value": "100" (string, parsed by valueParser)<br> in text — converted to AE carriage returns (\r)# Full pipeline: launch AE, build, render
ae-automation run config.json
# Dry run (validate config without launching AE)
# Set "debug": true in the config, then:
ae-automation run config.json
# Or via Python:
python -c "from ae_automation import Client; Client().startBot('config.json')"
If you already have a built .aep and just want to render:
from ae_automation import Client
client = Client()
output = client.renderFile("project.aep", "MainComp", "output_dir/")
print(f"Rendered to: {output}")
Or use the CLI export:
ae-automation export --template tutorial --output-dir renders/
Run diagnostics when things aren't working:
ae-automation diagnose
This checks:
# List available templates
ae-automation generate --list
# Generate a specific template
ae-automation generate --template tutorial --output my_project.aep
# Generate all templates
ae-automation generate --all
When the user wants AI-generated content for their videos, use Prompture to generate text, scene breakdowns, or scripts. Prompture is available at C:\Users\Juan\Documents\GitHub\prompture.
import sys
sys.path.insert(0, r"C:\Users\Juan\Documents\GitHub\prompture")
from prompture import extract_with_model
from pydantic import BaseModel
class VideoScene(BaseModel):
title: str
body_text: str
duration_seconds: float
transition_note: str
class VideoScript(BaseModel):
scenes: list[VideoScene]
total_duration: float
script = extract_with_model(
VideoScript,
"Create a 30-second product launch video script for a tech gadget. "
"Include 4 scenes: intro, features, demo, and outro.",
model_name="openai/gpt-4o" # or any configured provider
)
# Now convert to AE automation config
timeline = []
current_time = 0
for i, scene in enumerate(script.json_object.scenes):
timeline.append({
"name": scene.title,
"duration": scene.duration_seconds,
"startTime": current_time,
"template_comp": "SceneTemplate", # user's template comp
"reverse": False,
"custom_actions": [
{
"change_type": "update_layer_property",
"comp_name": "SceneTemplate",
"layer_name": "Title",
"property_name": "Text.Source Text",
"property_type": "string",
"value": scene.title
},
{
"change_type": "update_layer_property",
"comp_name": "SceneTemplate",
"layer_name": "Body",
"property_name": "Text.Source Text",
"property_type": "string",
"value": scene.body_text
}
]
})
current_time += scene.duration_seconds
from pydantic import BaseModel
class ColorPalette(BaseModel):
primary: str # hex
secondary: str # hex
accent: str # hex
background: str # hex
text: str # hex
palette = extract_with_model(
ColorPalette,
"Generate a modern, professional color palette for a tech product video",
model_name="openai/gpt-4o"
)
# Use in config actions:
# {"change_type": "update_layer_property", "property_type": "color", "value": palette.json_object.primary}
from pydantic import BaseModel
class VideoCopy(BaseModel):
headline: str
subheadline: str
cta_text: str
bullet_points: list[str]
copy = extract_with_model(
VideoCopy,
f"Write compelling video copy for: {user_description}",
model_name="openai/gpt-4o"
)
from ae_automation import Client
client = Client()
# Full pipeline from config
client.startBot("config.json")
# Individual operations (requires AE running)
client.createComp("MyComp", compWidth=1920, compHeight=1080, duration=30, frameRate=30)
client.editComp("MyComp", "Title", "Text.Source Text", "Hello World")
client.addMarker("MyComp", "Controller", "intro", 0.5)
client.renderFile("project.aep", "MyComp", "output/")
# Diagnostics
client.run_full_diagnostic()
# Template generation
from ae_automation.templates import BUILTIN_TEMPLATES
client.buildTemplate(BUILTIN_TEMPLATES["tutorial"], "output.aep")
Create multiple videos from a data source:
import json
from ae_automation import Client
# Load base config
with open("base_config.json") as f:
base = json.load(f)
videos = [
{"title": "Episode 1", "subtitle": "Getting Started", "color": "#FF5733"},
{"title": "Episode 2", "subtitle": "Advanced Tips", "color": "#33FF57"},
]
for i, video in enumerate(videos):
config = json.loads(json.dumps(base)) # deep copy
config["project"]["output_file"] = f"episode_{i+1}.mp4"
for scene in config["timeline"]:
for action in scene["custom_actions"]:
if action.get("layer_name") == "Title":
action["value"] = video["title"]
if action.get("layer_name") == "Subtitle":
action["value"] = video["subtitle"]
config_path = f"config_ep{i+1}.json"
with open(config_path, "w") as f:
json.dump(config, f, indent=2)
Client().startBot(config_path)
Use the templates section to avoid repeating actions:
{
"templates": {
"set_scene_text": {
"custom_actions": [
{
"change_type": "update_layer_property",
"comp_name": "{comp}",
"layer_name": "Title",
"property_name": "Text.Source Text",
"property_type": "string",
"value": "{title}"
},
{
"change_type": "update_layer_property",
"comp_name": "{comp}",
"layer_name": "Body",
"property_name": "Text.Source Text",
"property_type": "string",
"value": "{body}"
}
]
}
}
}
Then reference in timeline:
{
"change_type": "template",
"template_name": "set_scene_text",
"template_values": {
"comp": "scene-1-ContentTemplate",
"title": "Welcome",
"body": "This is the intro"
}
}
python install_ae_runner.py to enable the file-based command queue<br> tags become AE carriage returns; straight quotes are preservedaerender.exe — set AERENDER_PATH in .env if not in default location"debug": true) skips AE launch — good for testing config structure.env)