aeset 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- aeset-0.1.0/PKG-INFO +105 -0
- aeset-0.1.0/README.md +89 -0
- aeset-0.1.0/aeset/__init__.py +1 -0
- aeset-0.1.0/aeset/cli.py +100 -0
- aeset-0.1.0/aeset/launcher.py +33 -0
- aeset-0.1.0/aeset/scaffold.py +96 -0
- aeset-0.1.0/aeset/templates/blank.aep +0 -0
- aeset-0.1.0/aeset.egg-info/PKG-INFO +105 -0
- aeset-0.1.0/aeset.egg-info/SOURCES.txt +13 -0
- aeset-0.1.0/aeset.egg-info/dependency_links.txt +1 -0
- aeset-0.1.0/aeset.egg-info/entry_points.txt +2 -0
- aeset-0.1.0/aeset.egg-info/requires.txt +2 -0
- aeset-0.1.0/aeset.egg-info/top_level.txt +1 -0
- aeset-0.1.0/pyproject.toml +36 -0
- aeset-0.1.0/setup.cfg +4 -0
aeset-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: aeset
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A macOS CLI tool for After Effects project scaffolding
|
|
5
|
+
Author-email: Ahmed Alghali <a7medalghali777@gmail.com>
|
|
6
|
+
Project-URL: Homepage, https://github.com/a7med7x7/aeset
|
|
7
|
+
Project-URL: Bug Tracker, https://github.com/a7med7x7/aeset/issues
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Operating System :: MacOS :: MacOS X
|
|
11
|
+
Classifier: Topic :: Multimedia :: Video
|
|
12
|
+
Requires-Python: >=3.11
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
Requires-Dist: click
|
|
15
|
+
Requires-Dist: questionary
|
|
16
|
+
|
|
17
|
+
# Aeset — After Effects Project Scaffolding Tool
|
|
18
|
+
|
|
19
|
+
Every video editor or motion designer wastes 10–20 minutes at the start of every project doing the exact same thing: creating folders by hand, naming them consistently, opening After Effects, and setting up a new composition with the right resolution, framerate, and duration. It is not creative work. It is repetitive work. Multiply it by 50 projects a year and you have lost a full work week to folder creation and blank composition setup.
|
|
20
|
+
|
|
21
|
+
Aeset is a tool built to solve this for After Effects on macOS. It takes the "scaffolding" logic used by software developers and applies it to the motion design world.
|
|
22
|
+
|
|
23
|
+
## 1. What The Tool Does
|
|
24
|
+
|
|
25
|
+
The user opens their terminal, navigates to where they want the project to live, and runs:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
aeset
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The tool then asks a series of interactive questions:
|
|
32
|
+
- Project name (e.g., Nike_Ident_2026)
|
|
33
|
+
- Project type (Commercial, Personal, etc.)
|
|
34
|
+
- Resolution (Full HD, 4K, Vertical, etc.)
|
|
35
|
+
- Frame rate (24, 25, 30, 60 fps)
|
|
36
|
+
- Duration in seconds
|
|
37
|
+
- Color space (sRGB, Rec. 709, ACES)
|
|
38
|
+
|
|
39
|
+
After those answers, the tool:
|
|
40
|
+
1. Creates a standardized folder tree inside a new project directory.
|
|
41
|
+
2. Copies a blank .aep template file into the project folder.
|
|
42
|
+
3. Generates a small ExtendScript .jsx file containing the user's specs.
|
|
43
|
+
4. Opens After Effects with the project file via a macOS system call.
|
|
44
|
+
5. Fires an AppleScript command that tells After Effects to run the .jsx, which creates the composition and internal project bins (folders) automatically.
|
|
45
|
+
|
|
46
|
+
## 2. Folder Structure Generated
|
|
47
|
+
|
|
48
|
+
Aeset generates a directory layout that follows conventions used by professional motion studios. The core principle is: never mix source files with outputs.
|
|
49
|
+
|
|
50
|
+
### On Disk:
|
|
51
|
+
```
|
|
52
|
+
<ProjectName>/
|
|
53
|
+
├── project/
|
|
54
|
+
│ ├── <ProjectName>.aep (copy of blank .aep template)
|
|
55
|
+
│ └── setup.jsx (temporary setup script)
|
|
56
|
+
├── footage/
|
|
57
|
+
│ ├── video/ (raw video clips)
|
|
58
|
+
│ ├── audio/ (music, SFX, voiceover)
|
|
59
|
+
│ └── renders/ (outputs from C4D, Blender, etc.)
|
|
60
|
+
├── assets/
|
|
61
|
+
│ ├── images/ (static graphics, PNGs, PSDs, AI files)
|
|
62
|
+
│ ├── fonts/ (local fonts scoped to this project)
|
|
63
|
+
│ └── documents/ (briefs, scripts, reference PDFs)
|
|
64
|
+
├── exports/
|
|
65
|
+
│ ├── drafts/ (work-in-progress renders)
|
|
66
|
+
│ └── final/ (delivered, approved renders)
|
|
67
|
+
└── README.md (auto-generated project notes)
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Inside After Effects:
|
|
71
|
+
The tool also creates corresponding bins in the Project Panel to keep your workspace clean:
|
|
72
|
+
- _COMPS (containing your main composition)
|
|
73
|
+
- _FOOTAGE
|
|
74
|
+
- _ASSETS
|
|
75
|
+
- _AUDIO
|
|
76
|
+
|
|
77
|
+
## 3. The Mechanism
|
|
78
|
+
|
|
79
|
+
### The .aep file
|
|
80
|
+
An .aep file is a binary format that cannot be easily generated by code. Because of this, Aeset ships with a hand-crafted blank .aep template. Every time the tool runs, it copies this template and renames it.
|
|
81
|
+
|
|
82
|
+
### The .jsx file
|
|
83
|
+
The tool generates a plain text ExtendScript file at runtime. This script has full programmatic access to After Effects. It uses the specs you provided in the terminal to build your composition and organize your project panel.
|
|
84
|
+
|
|
85
|
+
### The AppleScript Trigger
|
|
86
|
+
The .jsx is triggered explicitly after After Effects opens using a macOS AppleScript command (DoScript). This bridges the gap between the Python-based CLI and the Adobe environment.
|
|
87
|
+
|
|
88
|
+
## 4. Installation and Requirements
|
|
89
|
+
|
|
90
|
+
### Installation
|
|
91
|
+
Aeset can be installed via pip:
|
|
92
|
+
```bash
|
|
93
|
+
pip install aeset
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Requirements
|
|
97
|
+
- macOS: AppleScript and the 'open' command are macOS-specific.
|
|
98
|
+
- Adobe After Effects 2025: The tool is currently configured to target the 2025 version.
|
|
99
|
+
- Python 3.11+
|
|
100
|
+
|
|
101
|
+
## 5. Constraints and Assumptions
|
|
102
|
+
|
|
103
|
+
- No Adobe credentials required: The tool uses only local scripting.
|
|
104
|
+
- After Effects must already be installed: The tool does not manage the AE installation itself.
|
|
105
|
+
- Local execution: All files are generated and stored locally on your machine.
|
aeset-0.1.0/README.md
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Aeset — After Effects Project Scaffolding Tool
|
|
2
|
+
|
|
3
|
+
Every video editor or motion designer wastes 10–20 minutes at the start of every project doing the exact same thing: creating folders by hand, naming them consistently, opening After Effects, and setting up a new composition with the right resolution, framerate, and duration. It is not creative work. It is repetitive work. Multiply it by 50 projects a year and you have lost a full work week to folder creation and blank composition setup.
|
|
4
|
+
|
|
5
|
+
Aeset is a tool built to solve this for After Effects on macOS. It takes the "scaffolding" logic used by software developers and applies it to the motion design world.
|
|
6
|
+
|
|
7
|
+
## 1. What The Tool Does
|
|
8
|
+
|
|
9
|
+
The user opens their terminal, navigates to where they want the project to live, and runs:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
aeset
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
The tool then asks a series of interactive questions:
|
|
16
|
+
- Project name (e.g., Nike_Ident_2026)
|
|
17
|
+
- Project type (Commercial, Personal, etc.)
|
|
18
|
+
- Resolution (Full HD, 4K, Vertical, etc.)
|
|
19
|
+
- Frame rate (24, 25, 30, 60 fps)
|
|
20
|
+
- Duration in seconds
|
|
21
|
+
- Color space (sRGB, Rec. 709, ACES)
|
|
22
|
+
|
|
23
|
+
After those answers, the tool:
|
|
24
|
+
1. Creates a standardized folder tree inside a new project directory.
|
|
25
|
+
2. Copies a blank .aep template file into the project folder.
|
|
26
|
+
3. Generates a small ExtendScript .jsx file containing the user's specs.
|
|
27
|
+
4. Opens After Effects with the project file via a macOS system call.
|
|
28
|
+
5. Fires an AppleScript command that tells After Effects to run the .jsx, which creates the composition and internal project bins (folders) automatically.
|
|
29
|
+
|
|
30
|
+
## 2. Folder Structure Generated
|
|
31
|
+
|
|
32
|
+
Aeset generates a directory layout that follows conventions used by professional motion studios. The core principle is: never mix source files with outputs.
|
|
33
|
+
|
|
34
|
+
### On Disk:
|
|
35
|
+
```
|
|
36
|
+
<ProjectName>/
|
|
37
|
+
├── project/
|
|
38
|
+
│ ├── <ProjectName>.aep (copy of blank .aep template)
|
|
39
|
+
│ └── setup.jsx (temporary setup script)
|
|
40
|
+
├── footage/
|
|
41
|
+
│ ├── video/ (raw video clips)
|
|
42
|
+
│ ├── audio/ (music, SFX, voiceover)
|
|
43
|
+
│ └── renders/ (outputs from C4D, Blender, etc.)
|
|
44
|
+
├── assets/
|
|
45
|
+
│ ├── images/ (static graphics, PNGs, PSDs, AI files)
|
|
46
|
+
│ ├── fonts/ (local fonts scoped to this project)
|
|
47
|
+
│ └── documents/ (briefs, scripts, reference PDFs)
|
|
48
|
+
├── exports/
|
|
49
|
+
│ ├── drafts/ (work-in-progress renders)
|
|
50
|
+
│ └── final/ (delivered, approved renders)
|
|
51
|
+
└── README.md (auto-generated project notes)
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Inside After Effects:
|
|
55
|
+
The tool also creates corresponding bins in the Project Panel to keep your workspace clean:
|
|
56
|
+
- _COMPS (containing your main composition)
|
|
57
|
+
- _FOOTAGE
|
|
58
|
+
- _ASSETS
|
|
59
|
+
- _AUDIO
|
|
60
|
+
|
|
61
|
+
## 3. The Mechanism
|
|
62
|
+
|
|
63
|
+
### The .aep file
|
|
64
|
+
An .aep file is a binary format that cannot be easily generated by code. Because of this, Aeset ships with a hand-crafted blank .aep template. Every time the tool runs, it copies this template and renames it.
|
|
65
|
+
|
|
66
|
+
### The .jsx file
|
|
67
|
+
The tool generates a plain text ExtendScript file at runtime. This script has full programmatic access to After Effects. It uses the specs you provided in the terminal to build your composition and organize your project panel.
|
|
68
|
+
|
|
69
|
+
### The AppleScript Trigger
|
|
70
|
+
The .jsx is triggered explicitly after After Effects opens using a macOS AppleScript command (DoScript). This bridges the gap between the Python-based CLI and the Adobe environment.
|
|
71
|
+
|
|
72
|
+
## 4. Installation and Requirements
|
|
73
|
+
|
|
74
|
+
### Installation
|
|
75
|
+
Aeset can be installed via pip:
|
|
76
|
+
```bash
|
|
77
|
+
pip install aeset
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Requirements
|
|
81
|
+
- macOS: AppleScript and the 'open' command are macOS-specific.
|
|
82
|
+
- Adobe After Effects 2025: The tool is currently configured to target the 2025 version.
|
|
83
|
+
- Python 3.11+
|
|
84
|
+
|
|
85
|
+
## 5. Constraints and Assumptions
|
|
86
|
+
|
|
87
|
+
- No Adobe credentials required: The tool uses only local scripting.
|
|
88
|
+
- After Effects must already be installed: The tool does not manage the AE installation itself.
|
|
89
|
+
- Local execution: All files are generated and stored locally on your machine.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.0"
|
aeset-0.1.0/aeset/cli.py
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import click
|
|
2
|
+
import questionary
|
|
3
|
+
import pathlib
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
from .scaffold import create_project_folders, generate_jsx, copy_template_aep, generate_readme
|
|
6
|
+
from .launcher import launch_after_effects, run_jsx_via_applescript
|
|
7
|
+
|
|
8
|
+
@click.command()
|
|
9
|
+
@click.option('--no-launch', is_flag=True, help="Create the project but do not launch After Effects.")
|
|
10
|
+
def main(no_launch):
|
|
11
|
+
"""Aeset — After Effects Project Scaffolding Tool."""
|
|
12
|
+
|
|
13
|
+
click.echo(click.style("\n🚀 Aeset — After Effects Project Scaffolder\n", fg="cyan", bold=True))
|
|
14
|
+
|
|
15
|
+
# 1. Collect inputs
|
|
16
|
+
project_name = questionary.text(
|
|
17
|
+
"Project name",
|
|
18
|
+
validate=lambda text: len(text) > 0 or "Project name cannot be empty."
|
|
19
|
+
).ask()
|
|
20
|
+
|
|
21
|
+
if not project_name:
|
|
22
|
+
return
|
|
23
|
+
|
|
24
|
+
project_type = questionary.select(
|
|
25
|
+
"Project type",
|
|
26
|
+
choices=["Commercial", "Personal", "Motion Test", "Music Video"]
|
|
27
|
+
).ask()
|
|
28
|
+
|
|
29
|
+
resolution = questionary.select(
|
|
30
|
+
"Resolution",
|
|
31
|
+
choices=[
|
|
32
|
+
"1920×1080 (Full HD)",
|
|
33
|
+
"3840×2160 (4K)",
|
|
34
|
+
"1080×1080 (Square / Instagram)",
|
|
35
|
+
"1080×1920 (Vertical / Reels)"
|
|
36
|
+
]
|
|
37
|
+
).ask()
|
|
38
|
+
# Clean up resolution choice
|
|
39
|
+
resolution = resolution.split(" ")[0]
|
|
40
|
+
|
|
41
|
+
fps = questionary.select(
|
|
42
|
+
"Frame rate",
|
|
43
|
+
choices=["24", "25", "30", "60"]
|
|
44
|
+
).ask()
|
|
45
|
+
fps = int(fps)
|
|
46
|
+
|
|
47
|
+
duration = questionary.text(
|
|
48
|
+
"Duration (seconds)",
|
|
49
|
+
default="10",
|
|
50
|
+
validate=lambda text: text.isdigit() or "Duration must be an integer."
|
|
51
|
+
).ask()
|
|
52
|
+
duration = int(duration)
|
|
53
|
+
|
|
54
|
+
color_space = questionary.select(
|
|
55
|
+
"Color space",
|
|
56
|
+
choices=["sRGB", "Rec. 709", "ACES"]
|
|
57
|
+
).ask()
|
|
58
|
+
|
|
59
|
+
# Create project directory
|
|
60
|
+
project_path = pathlib.Path.cwd() / project_name
|
|
61
|
+
if project_path.exists():
|
|
62
|
+
if not questionary.confirm(f"Directory {project_name} already exists. Overwrite?").ask():
|
|
63
|
+
click.echo("Aborted.")
|
|
64
|
+
return
|
|
65
|
+
|
|
66
|
+
# 2. Scaffolding
|
|
67
|
+
config = {
|
|
68
|
+
"type": project_type,
|
|
69
|
+
"resolution": resolution,
|
|
70
|
+
"fps": fps,
|
|
71
|
+
"duration": duration,
|
|
72
|
+
"color_space": color_space,
|
|
73
|
+
"date": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
click.echo(f"✔ Creating {project_name}/...")
|
|
77
|
+
create_project_folders(project_path)
|
|
78
|
+
|
|
79
|
+
click.echo("✔ Copying project template...")
|
|
80
|
+
aep_path = copy_template_aep(project_path, project_name)
|
|
81
|
+
|
|
82
|
+
click.echo("✔ Generating composition config...")
|
|
83
|
+
jsx_path = generate_jsx(project_path, project_name, config)
|
|
84
|
+
|
|
85
|
+
click.echo("✔ Generating README.md...")
|
|
86
|
+
generate_readme(project_path, project_name, config)
|
|
87
|
+
|
|
88
|
+
# 3. Launch
|
|
89
|
+
if not no_launch:
|
|
90
|
+
click.echo("✔ Opening After Effects...")
|
|
91
|
+
if launch_after_effects(aep_path):
|
|
92
|
+
click.echo("✔ Triggering setup script...")
|
|
93
|
+
run_jsx_via_applescript(jsx_path)
|
|
94
|
+
else:
|
|
95
|
+
click.echo(click.style("✘ Could not launch After Effects automatically.", fg="red"))
|
|
96
|
+
|
|
97
|
+
click.echo(click.style(f"\n🎉 Done! Project {project_name} is ready.\n", fg="green", bold=True))
|
|
98
|
+
|
|
99
|
+
if __name__ == "__main__":
|
|
100
|
+
main()
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import subprocess
|
|
2
|
+
import time
|
|
3
|
+
import pathlib
|
|
4
|
+
|
|
5
|
+
def launch_after_effects(aep_path: pathlib.Path, ae_version: str = "Adobe After Effects 2025"):
|
|
6
|
+
"""Launches After Effects and opens the specified .aep file."""
|
|
7
|
+
abs_path = str(aep_path.resolve())
|
|
8
|
+
|
|
9
|
+
# Use 'open' command which is usually most reliable for launching with a file
|
|
10
|
+
try:
|
|
11
|
+
subprocess.run(["open", abs_path, "-a", ae_version], check=True)
|
|
12
|
+
return True
|
|
13
|
+
except Exception as e:
|
|
14
|
+
print(f"Error opening project: {e}")
|
|
15
|
+
return False
|
|
16
|
+
|
|
17
|
+
def run_jsx_via_applescript(jsx_path: pathlib.Path, ae_version: str = "Adobe After Effects 2025"):
|
|
18
|
+
"""Triggers a .jsx script in After Effects using AppleScript DoScript."""
|
|
19
|
+
# Use absolute path and ensure it's escaped for JavaScript
|
|
20
|
+
script_path = str(jsx_path.absolute())
|
|
21
|
+
|
|
22
|
+
# We send a piece of JavaScript code to AE: $.evalFile("/path/to/script.jsx");
|
|
23
|
+
js_to_run = f"$.evalFile('{script_path}');"
|
|
24
|
+
applescript = f'tell application "{ae_version}" to DoScript "{js_to_run}"'
|
|
25
|
+
|
|
26
|
+
try:
|
|
27
|
+
# Give AE a moment to open/load the project before sending the command
|
|
28
|
+
time.sleep(10)
|
|
29
|
+
subprocess.run(["osascript", "-e", applescript], check=True)
|
|
30
|
+
return True
|
|
31
|
+
except subprocess.CalledProcessError as e:
|
|
32
|
+
print(f"Error running AppleScript: {e}")
|
|
33
|
+
return False
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import pathlib
|
|
2
|
+
import shutil
|
|
3
|
+
from typing import Dict, Any
|
|
4
|
+
|
|
5
|
+
def create_project_folders(project_path: pathlib.Path):
|
|
6
|
+
"""Creates the standard folder structure for an After Effects project."""
|
|
7
|
+
folders = [
|
|
8
|
+
"project",
|
|
9
|
+
"footage/video",
|
|
10
|
+
"footage/audio",
|
|
11
|
+
"footage/renders",
|
|
12
|
+
"assets/images",
|
|
13
|
+
"assets/fonts",
|
|
14
|
+
"assets/documents",
|
|
15
|
+
"exports/drafts",
|
|
16
|
+
"exports/final",
|
|
17
|
+
]
|
|
18
|
+
for folder in folders:
|
|
19
|
+
(project_path / folder).mkdir(parents=True, exist_ok=True)
|
|
20
|
+
|
|
21
|
+
def generate_jsx(project_path: pathlib.Path, project_name: str, config: Dict[str, Any]):
|
|
22
|
+
"""Generates an ExtendScript .jsx file with the project configuration."""
|
|
23
|
+
# resolution is "1920×1080"
|
|
24
|
+
res_parts = config["resolution"].split("×")
|
|
25
|
+
width = int(res_parts[0])
|
|
26
|
+
height = int(res_parts[1])
|
|
27
|
+
|
|
28
|
+
fps = config["fps"]
|
|
29
|
+
duration = config["duration"]
|
|
30
|
+
|
|
31
|
+
jsx_content = f"""// Auto-generated by aeset — do not edit manually
|
|
32
|
+
var projectName = "{project_name}";
|
|
33
|
+
var width = {width};
|
|
34
|
+
var height = {height};
|
|
35
|
+
var fps = {fps};
|
|
36
|
+
var duration = {duration};
|
|
37
|
+
|
|
38
|
+
app.beginUndoGroup("Scaffold Project");
|
|
39
|
+
|
|
40
|
+
// 1. Create Folder Structure in AE Project Panel
|
|
41
|
+
var compFolder = app.project.items.addFolder("_COMPS");
|
|
42
|
+
var footageFolder = app.project.items.addFolder("_FOOTAGE");
|
|
43
|
+
var assetsFolder = app.project.items.addFolder("_ASSETS");
|
|
44
|
+
var audioFolder = app.project.items.addFolder("_AUDIO");
|
|
45
|
+
|
|
46
|
+
// 2. Create the main Composition
|
|
47
|
+
var comp = app.project.items.addComp(
|
|
48
|
+
projectName,
|
|
49
|
+
width,
|
|
50
|
+
height,
|
|
51
|
+
1.0,
|
|
52
|
+
duration,
|
|
53
|
+
fps
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
// 3. Move comp into the COMPS folder
|
|
57
|
+
comp.parentFolder = compFolder;
|
|
58
|
+
|
|
59
|
+
comp.openInViewer();
|
|
60
|
+
app.endUndoGroup();
|
|
61
|
+
|
|
62
|
+
app.project.save();
|
|
63
|
+
"""
|
|
64
|
+
jsx_path = project_path / "project" / "setup.jsx"
|
|
65
|
+
jsx_path.write_text(jsx_content)
|
|
66
|
+
return jsx_path
|
|
67
|
+
|
|
68
|
+
def copy_template_aep(project_path: pathlib.Path, project_name: str):
|
|
69
|
+
"""Copies the blank .aep template to the new project directory."""
|
|
70
|
+
# it finds the template relative to this file
|
|
71
|
+
template_path = pathlib.Path(__file__).parent / "templates" / "blank.aep"
|
|
72
|
+
dest_path = project_path / "project" / f"{project_name}.aep"
|
|
73
|
+
|
|
74
|
+
if not template_path.exists():
|
|
75
|
+
# For development, if blank.aep isn't there, it create a placeholder
|
|
76
|
+
template_path.parent.mkdir(parents=True, exist_ok=True)
|
|
77
|
+
template_path.write_text("DUMMY AEP BINARY CONTENT")
|
|
78
|
+
|
|
79
|
+
shutil.copy2(template_path, dest_path)
|
|
80
|
+
return dest_path
|
|
81
|
+
|
|
82
|
+
def generate_readme(project_path: pathlib.Path, project_name: str, config: Dict[str, Any]):
|
|
83
|
+
"""Generates a README.md for the project with metadata."""
|
|
84
|
+
readme_content = f"""# {project_name}
|
|
85
|
+
|
|
86
|
+
**Project Type:** {config["type"]}
|
|
87
|
+
**Resolution:** {config["resolution"]}
|
|
88
|
+
**Frame Rate:** {config["fps"]} fps
|
|
89
|
+
**Duration:** {config["duration"]} seconds
|
|
90
|
+
**Color Space:** {config["color_space"]}
|
|
91
|
+
**Created:** {config["date"]}
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
Auto-generated by aeset.
|
|
95
|
+
"""
|
|
96
|
+
(project_path / "README.md").write_text(readme_content)
|
|
Binary file
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: aeset
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A macOS CLI tool for After Effects project scaffolding
|
|
5
|
+
Author-email: Ahmed Alghali <a7medalghali777@gmail.com>
|
|
6
|
+
Project-URL: Homepage, https://github.com/a7med7x7/aeset
|
|
7
|
+
Project-URL: Bug Tracker, https://github.com/a7med7x7/aeset/issues
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Operating System :: MacOS :: MacOS X
|
|
11
|
+
Classifier: Topic :: Multimedia :: Video
|
|
12
|
+
Requires-Python: >=3.11
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
Requires-Dist: click
|
|
15
|
+
Requires-Dist: questionary
|
|
16
|
+
|
|
17
|
+
# Aeset — After Effects Project Scaffolding Tool
|
|
18
|
+
|
|
19
|
+
Every video editor or motion designer wastes 10–20 minutes at the start of every project doing the exact same thing: creating folders by hand, naming them consistently, opening After Effects, and setting up a new composition with the right resolution, framerate, and duration. It is not creative work. It is repetitive work. Multiply it by 50 projects a year and you have lost a full work week to folder creation and blank composition setup.
|
|
20
|
+
|
|
21
|
+
Aeset is a tool built to solve this for After Effects on macOS. It takes the "scaffolding" logic used by software developers and applies it to the motion design world.
|
|
22
|
+
|
|
23
|
+
## 1. What The Tool Does
|
|
24
|
+
|
|
25
|
+
The user opens their terminal, navigates to where they want the project to live, and runs:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
aeset
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The tool then asks a series of interactive questions:
|
|
32
|
+
- Project name (e.g., Nike_Ident_2026)
|
|
33
|
+
- Project type (Commercial, Personal, etc.)
|
|
34
|
+
- Resolution (Full HD, 4K, Vertical, etc.)
|
|
35
|
+
- Frame rate (24, 25, 30, 60 fps)
|
|
36
|
+
- Duration in seconds
|
|
37
|
+
- Color space (sRGB, Rec. 709, ACES)
|
|
38
|
+
|
|
39
|
+
After those answers, the tool:
|
|
40
|
+
1. Creates a standardized folder tree inside a new project directory.
|
|
41
|
+
2. Copies a blank .aep template file into the project folder.
|
|
42
|
+
3. Generates a small ExtendScript .jsx file containing the user's specs.
|
|
43
|
+
4. Opens After Effects with the project file via a macOS system call.
|
|
44
|
+
5. Fires an AppleScript command that tells After Effects to run the .jsx, which creates the composition and internal project bins (folders) automatically.
|
|
45
|
+
|
|
46
|
+
## 2. Folder Structure Generated
|
|
47
|
+
|
|
48
|
+
Aeset generates a directory layout that follows conventions used by professional motion studios. The core principle is: never mix source files with outputs.
|
|
49
|
+
|
|
50
|
+
### On Disk:
|
|
51
|
+
```
|
|
52
|
+
<ProjectName>/
|
|
53
|
+
├── project/
|
|
54
|
+
│ ├── <ProjectName>.aep (copy of blank .aep template)
|
|
55
|
+
│ └── setup.jsx (temporary setup script)
|
|
56
|
+
├── footage/
|
|
57
|
+
│ ├── video/ (raw video clips)
|
|
58
|
+
│ ├── audio/ (music, SFX, voiceover)
|
|
59
|
+
│ └── renders/ (outputs from C4D, Blender, etc.)
|
|
60
|
+
├── assets/
|
|
61
|
+
│ ├── images/ (static graphics, PNGs, PSDs, AI files)
|
|
62
|
+
│ ├── fonts/ (local fonts scoped to this project)
|
|
63
|
+
│ └── documents/ (briefs, scripts, reference PDFs)
|
|
64
|
+
├── exports/
|
|
65
|
+
│ ├── drafts/ (work-in-progress renders)
|
|
66
|
+
│ └── final/ (delivered, approved renders)
|
|
67
|
+
└── README.md (auto-generated project notes)
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Inside After Effects:
|
|
71
|
+
The tool also creates corresponding bins in the Project Panel to keep your workspace clean:
|
|
72
|
+
- _COMPS (containing your main composition)
|
|
73
|
+
- _FOOTAGE
|
|
74
|
+
- _ASSETS
|
|
75
|
+
- _AUDIO
|
|
76
|
+
|
|
77
|
+
## 3. The Mechanism
|
|
78
|
+
|
|
79
|
+
### The .aep file
|
|
80
|
+
An .aep file is a binary format that cannot be easily generated by code. Because of this, Aeset ships with a hand-crafted blank .aep template. Every time the tool runs, it copies this template and renames it.
|
|
81
|
+
|
|
82
|
+
### The .jsx file
|
|
83
|
+
The tool generates a plain text ExtendScript file at runtime. This script has full programmatic access to After Effects. It uses the specs you provided in the terminal to build your composition and organize your project panel.
|
|
84
|
+
|
|
85
|
+
### The AppleScript Trigger
|
|
86
|
+
The .jsx is triggered explicitly after After Effects opens using a macOS AppleScript command (DoScript). This bridges the gap between the Python-based CLI and the Adobe environment.
|
|
87
|
+
|
|
88
|
+
## 4. Installation and Requirements
|
|
89
|
+
|
|
90
|
+
### Installation
|
|
91
|
+
Aeset can be installed via pip:
|
|
92
|
+
```bash
|
|
93
|
+
pip install aeset
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Requirements
|
|
97
|
+
- macOS: AppleScript and the 'open' command are macOS-specific.
|
|
98
|
+
- Adobe After Effects 2025: The tool is currently configured to target the 2025 version.
|
|
99
|
+
- Python 3.11+
|
|
100
|
+
|
|
101
|
+
## 5. Constraints and Assumptions
|
|
102
|
+
|
|
103
|
+
- No Adobe credentials required: The tool uses only local scripting.
|
|
104
|
+
- After Effects must already be installed: The tool does not manage the AE installation itself.
|
|
105
|
+
- Local execution: All files are generated and stored locally on your machine.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
aeset/__init__.py
|
|
4
|
+
aeset/cli.py
|
|
5
|
+
aeset/launcher.py
|
|
6
|
+
aeset/scaffold.py
|
|
7
|
+
aeset.egg-info/PKG-INFO
|
|
8
|
+
aeset.egg-info/SOURCES.txt
|
|
9
|
+
aeset.egg-info/dependency_links.txt
|
|
10
|
+
aeset.egg-info/entry_points.txt
|
|
11
|
+
aeset.egg-info/requires.txt
|
|
12
|
+
aeset.egg-info/top_level.txt
|
|
13
|
+
aeset/templates/blank.aep
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
aeset
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "aeset"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "A macOS CLI tool for After Effects project scaffolding"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
authors = [
|
|
11
|
+
{ name = "Ahmed Alghali", email = "a7medalghali777@gmail.com" }
|
|
12
|
+
]
|
|
13
|
+
requires-python = ">=3.11"
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Programming Language :: Python :: 3",
|
|
16
|
+
"License :: OSI Approved :: MIT License",
|
|
17
|
+
"Operating System :: MacOS :: MacOS X",
|
|
18
|
+
"Topic :: Multimedia :: Video",
|
|
19
|
+
]
|
|
20
|
+
dependencies = [
|
|
21
|
+
"click",
|
|
22
|
+
"questionary",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
[project.urls]
|
|
26
|
+
"Homepage" = "https://github.com/a7med7x7/aeset"
|
|
27
|
+
"Bug Tracker" = "https://github.com/a7med7x7/aeset/issues"
|
|
28
|
+
|
|
29
|
+
[project.scripts]
|
|
30
|
+
aeset = "aeset.cli:main"
|
|
31
|
+
|
|
32
|
+
[tool.setuptools]
|
|
33
|
+
packages = ["aeset"]
|
|
34
|
+
|
|
35
|
+
[tool.setuptools.package-data]
|
|
36
|
+
aeset = ["templates/*.aep"]
|
aeset-0.1.0/setup.cfg
ADDED