Known Limitations¶
This page documents limitations of py_aep that arise from the nature of parsing a binary file format rather than querying a running After Effects instance.
Property.value_at_time Accuracy on spatial Properties (~0.015 Maximum Error)¶
Property.value_at_time() for spatial properties (position, 2D/3D) has a
systematic ±0.015 deviation from After Effects' valueAtTime(). This is
not a bug in the parser - it is caused by After Effects' internal spatial
evaluation pipeline.
Evidence: even a perfectly straight, LINEAR-interpolated path shows a sinusoidal deviation pattern in After Effects' own output, peaking at ±0.011. The same deviation appears regardless of whether the keyframe interpolation type is LINEAR or BEZIER.
After Effects appears to process all spatial properties through an arc-length reparameterisation pipeline (likely a polyline or spline approximation) that does not degrade gracefully to exact linear interpolation for straight paths.
Runtime-Only Attributes¶
Many ExtendScript attributes reflect the live state of After Effects and cannot
be derived from the .aep file alone:
| Attribute | Reason |
|---|---|
Application.effects |
Installed effects on the system |
Application.fonts |
Installed fonts on the system |
Application.isRenderEngine |
Launch mode flag |
Application.isWatchFolder |
Launch mode flag |
Application.memoryInUse |
Runtime memory state |
Item.selected |
Runtime-only Selection state |
Project.dirty |
Unsaved changes flag |
RenderQueue.queueNotify |
Runtime state |
RenderQueue.rendering |
Runtime state |
Viewer.maximized |
Non-persisting window state |
Expressions¶
Property.value When Expressions Are Enabled¶
When Property.expression_enabled is True, the value attribute contains
the last static or keyframed value stored in the binary file - not the
result of evaluating the expression. After Effects computes expression results
at runtime using its expression engine; py_aep has no expression evaluator.
prop = layer.transform.property("ADBE Position")
if prop.expression_enabled:
# prop.value is the pre-expression value, not the expression result
print(prop.expression) # the expression string is available
Property.expression_error¶
Property.expression_error is always an empty string. After Effects computes
expression errors at runtime when it evaluates the expression engine; this
information is not stored in the binary .aep file.
Property Metadata¶
Property.default_value¶
Default values are set heuristically by the parser in synthesis/, not
read from the binary format. They are used for Property.is_modified checks.
Some default values may be inaccurate for non-standard property types.
Property.units_text¶
Property.units_text is not read from the binary format, it is based on a
collection of samples. For some properties, the value may be an empty string
even though After Effects displays a unit string in the UI.
Property.canSetExpression¶
Property.can_set_expression combines binary signals with a pure-logic
resolver. For effect parameters, an expressions-disabled flag in the
pard definition header is authoritative; the remaining logic covers
what After Effects determines at runtime from context: the layer type
(camera, light, etc.), whether the layer is 3D, whether position
dimensions are separated, and the light type. Small match-name tables
cover non-effect quirks (extrusion materials, text path options). The
result matches ExtendScript ground truth on 99.9% of 51,000+ validated
properties; the residual mismatches are instance-state cases (e.g.
plugin-supervised parameters whose enablement depends on other
parameter values).
Property.canVaryOverTime¶
For effect parameters, Property.can_vary_over_time is derived from the
parameter definition (pard) flags byte, which matches the After Effects
SDK's PF_ParamFlag_CANNOT_TIME_VARY. For other properties it combines
the tdb4 can_vary_over_time flag with the no_value flag (NO_VALUE
properties always report canVaryOverTime = true in ExtendScript). A
six-entry override table covers the residue (one light option that has no
pard, and the Puppet pin internals). Validated against ExtendScript ground
truth across 51,000+ properties covering every bundled and several
third-party effects, with zero mismatches.
Property.min_value / Property.max_value¶
For effect parameters, the valid range is read from the parameter
definition (pard): plain integers for Integer controls, 16.16 fixed
point for Scalar controls, and 32-bit floats for Slider controls (a
non-finite float means that side is unbounded). A small override table
covers non-effect properties (transform, material, mask).
Known mismatch: about a dozen non-effect properties report bounds where
ExtendScript reports none - ADBE Position_0/_1 and ADBE Scale carry
placeholder [0.0] bound chunks in the binary, and a few layer-style and
light properties carry synthesized bounds. Values are unaffected.
Templates¶
Render settings and output module templates are not stored in the .aep
file - After Effects keeps them in the user preferences. Pass the AE
preferences directory to parse() to make them available:
app = py_aep.parse("myproject.aep", ae_preferences_dir=prefs_dir)
rq_item = app.project.render_queue.add(comp)
print(rq_item.templates) # available render settings templates
rq_item.output_modules[0].apply_template("TIFF Sequence with Alpha")
Without ae_preferences_dir, RenderQueueItem.templates and
OutputModule.templates return an empty list, and RenderQueue.add()
raises (it needs the default templates to build the new item's settings).
The settings of items already in the queue remain available through
OutputModule.settings and RenderQueueItem.settings either way.
Color Space Profiles Are Read-Only¶
Project.working_space and Project.display_color_space are read-only.
The binary chunks that store these settings contain both the profile name and
the full ICC profile data (base64-encoded binary, up to ~50 KB per profile).
Updating only the profile name would leave stale ICC data, producing a file
that After Effects may reject or silently revert to a default profile.
Generating the correct ICC data would require the Adobe ICC profile files
installed on disk (under C:\Program Files (x86)\Common Files\Adobe\Color\ on
Windows), which cannot be assumed in all environments. Bundling these profiles
is not feasible due to licensing constraints.
Other color management settings (color_management_system,
lut_interpolation_method, ocio_configuration_file, working_gamma,
linearize_working_space, linear_blending,
compensate_for_scene_referred_profiles) remain read/write as they do not
depend on embedded ICC data.
Essential Properties¶
Essential Property override values on precomp layers are parsed as regular
properties under the "Essential Properties" group. The UUID linkage between
overrides and their source controller definitions is now partially exposed:
Layer.essential_property_uuidscontains the UUIDs ofLIST:OvG2overrides on a precomp layer.EssentialGraphicsController.uuidcontains the controller's identity UUID from theLIST:CCtldefinition.- Consumers can match UUIDs to link overrides to controllers, but py_aep does not perform this resolution automatically.
The following attributes are not parsed:
Property.essentialPropertySourceProperty.alternateSourceProperty.canSetAlternateSource
Missing Classes¶
The following ExtendScript classes do not exist in py_aep:
| Class | Reason |
|---|---|
System |
OS/machine info - not stored in .aep |
FontsObject |
Runtime collection of installed fonts |
CharacterRange |
Text engine range object (AE 24.6+) |
ComposedLineRange |
Text engine range object (AE 24.6+) |
ParagraphRange |
Text engine range object (AE 24.6+) |
ItemCollection |
Use project.items (Python dict[int, Item]) instead |
LayerCollection |
Use comp.layers (Python list) instead |
Settings |
Application settings - methods only, not stored in .aep |
Preferences |
Application preferences - methods only, not stored in .aep |
File Paths¶
File paths in .aep files are stored as they were saved on the original
system. They may be platform-specific (Windows backslashes vs. Unix forward
slashes) and may not resolve on the current system. FileSource.file returns
the path as stored without modification. FileSource.missing_footage_path
provides the path that After Effects would display for missing footage.
Importing Footage (Project.import_file)¶
Project.import_file() creates footage from a file by reading the media
header (see [media_probe][py_aep.resolvers.media_probe]). After Effects caches
footage metadata (dimensions, duration, frame rate, alpha, audio) in the
project and does not re-read the media when the project is opened, so these
values are extracted from the source file at import time.
- Scope: only
ImportAsType.FOOTAGEis supported.COMP,COMP_CROPPED_LAYERS, andPROJECTimport types are not. - Vector formats (SVG, AI, EPS) cannot be imported: After Effects refuses
to import these as footage (
ImportOptions.canImportAs(FOOTAGE)isfalse); they are only importable asCOMP_CROPPED_LAYERS, which converts the file into a composition of native vector shape layers (ADBE Vector Layer) rather than a file-referencing footage source. There is no footageopti/sspcrepresentation to write, so these raiseValueErrorlike any other unsupported extension. - Supported formats (verified to open in After Effects): PNG, JPEG, BMP,
GIF, TGA, TIFF, OpenEXR, PSD/PSB, QuickTime MOV, and WAV audio.
Image sequences are supported for those still-image formats. The same source
builder backs
FootageItem.replace()/replace_with_sequence()andAVItem.set_proxy()/set_proxy_with_sequence(). - PSD/PSB import as merged footage only: a
.psd/.psbis imported as a single flattened still (the8BPSmerged-layeroptiheader is written so AE resolves it without stalling on a layer-interpretation modal). Importing a PSD as a layered composition is not supported (see the import-type scope above). Other unrecognized extensions (and MP3, which has no duration prober) raise. has_alphais a per-format heuristic, not a full media decode. After Effects allocates an alpha channel for PNG/TIFF/BMP/PSD/GIF regardless of the file's actual channel count, treats JPEG as opaque, and derives alpha from the channel list (EXR), bit depth (TGA: 32-bit only), or codec depth (MOV). These match AE's import for the tested samples.- Image-sequence dimensions: the created
optiasset-info chunk is minimal, so After Effects recomputes the sequence size from the first frame's display window on open.
guessAlphaMode / guessPulldown¶
FootageSource.guess_alpha_mode() and guess_pulldown() are not implemented.
Both inspect the actual media at runtime (edge premultiplication detection,
3:2 pulldown cadence), which requires decoding the footage. When creating
footage, py_aep uses fixed defaults instead: alpha mode STRAIGHT (PREMULTIPLIED
for EXR), and pulldown OFF.