Parsing AEP Files
AfterEffects Project files are the proprietary file format used by Adobe AfterEffects.
It's a binary format based on the RIFX container format.
The structure resembles that of a Lottie JSON exported from AE.
RIFF
A RIFF is composed of "chunks" with the following format
Field | Size | Description |
---|---|---|
Header | 4 | ASCII name describing the type of the chunk |
Size | 4 | uint32 size of the data section |
Data | Size | Data within the chunk |
RIFX is an extension of the RIFF format, the difference being RIFX uses big-endian notation for storing numbers.
A RIFF file will be structured in the same way as a chunk:
Field | Size | Description |
---|---|---|
Header | 4 | RIFF or RIFX |
Size | 4 | uint32 size of the chunk |
Format | 4 | Format Identifier |
Chunks | * | Rest of the chunks |
AEP-Specific Parsing
It should always be RIFX
format (big endian). The format identifier
for AEP is Egg!
.
When parsing the RIFF structure, keep in mind the following chunks will contain other chunks:
And that LIST
btdk
contains data in a different format, and
it should not be parsed as a RIFF LIST
.
At the end of the RIFF data, the AEP file has some XML-encoded metadata.
Basic Types
Type | Size | Description |
---|---|---|
id |
4 | ASCII-encoded chunk identifier |
uint16 |
2 | Unsigned integer |
uint32 |
4 | Unsigned integer |
sint16 |
2 | Twos-complement signed integer |
float32 |
4 | IEEE float |
float64 |
8 | IEEE float |
string |
* | Text, usually utf-8 encoded |
string0 |
* | NUL terminated string, note that you might find junk data after the NUL (This can be caused by renaming something to a shorter name) |
bytes |
* | Unformatted / unknown data |
Time
Time values are stored as uint16
. they are scaled by a factor you can find in cdta
.
To get the actual value in frames you need to do the following:
time_frames = time_value / cdta.time_scale
Additionally, layers specify a start time, which shifts all the time values by a fixed amount.
If you are within a layer the expression looks like this:
time_frames = (time_value + ldta.start_time) / (cdta.time_scale)
Flags
Flags is byte data, that will be specified using two integers: byte and bit index.
You'll get the value of the flag you'll need to do the following:
flag = (flags[byte] & (1 << bit)) != 0
AfterEffects Logic
Project Structure
The contents of the project are in the top-level LIST
Fold
.
Inside here you'll find (among other things) LIST
Item
chunks,
they all contain an idta
which tells you how to interpret the item and its ID.
Compositions
idta
has type of 4
. You need to know which composition to extract as
a lottie corresponds to a specific comp (with other compositions showing
as assets for precomps).
The name of the composition is in the first Utf8
chunk.
Its properties are in cdta
.
Then look for LIST
Layr
to parse layers.
Folders
idta
type 1
. These contain additional items inside them.
The name of the folder is in the first Utf8
chunk.
Look for a LIST
Sfdr
and iterate through it for the child items.
Assets
idta
type 7
. These can have different kinds of contents.
LIST
Pin
will contain the asset data:
Look for sspc
to get the size for visual assets.
The type of asset is defined in the first 4 bytes of opti
.
Solids
For some the Item
has an Utf8
but it seems to always be empty
need to find the name from opti
.
Files
The Uft8
in Item
only has a value if the user has set an explicit value for the name.
The file path is in LIST
Pin
> LIST
Als2
> alas
.
Interpret it as JSON and get fullpath
.
the first 4 bytes of opti
will change based on the file format.
There will also be a LIST
CLRS
with some Utf8
, in there there's
some JSON with base64-encoded ICC color profiles.
Layers
Layers are defined in LIST
Layr
.
There are different types of layers:
Shape Layer
For shapes look for the match name ADBE Root Vectors Group
.
Camera Layer
For camera settings look for the match name ADBE Camera Options Group
.
Text Layer
For text contents look for the match name ADBE Text Properties
.
Asset Layer
(Also known as AVLayer in AE) They have a non-zero Source ID in ldta
.
Image layers and similar will point to an appropriate asset.
Several layer types point to a solid asset, you need to check the layer attributes to distinguish between them:
- Solid layers
- Null layers
- Adjustment layers
Light Layer
For light settings look for the match name ADBE Light Options Group
.
Property Groups
Most objects are described as a property groups.
These have the following structure:
LIST
tdgp
: Property group
Then follows a list of properties, all introduced by their
match name (tdmn
).
After a match name, you'll find the data for the property, which might be an actual propert (see the section below), other groups, or layer effects.
This structure is used both for objects (that have a fixed set of properties) and groups/collections whose contents might vary.
For objects with fixed properties you will not find duplicate match names but you might find duplicates within collections.
Properties
Properties, like objects are introduced by their match name, the chunks following that depends on the type of property.
The core of a property is defined in LIST
tdbs
with the following structure:
LIST
tdbs
: Property definition
For simple properties, with vector or scalar values, you get the structure above.
For more complex properties, you get an outer object that contains that data as well as a list of values. You'll get the value for the keyframes (or the static value) from that list.
Color properties are laid out as ARGB floats in [0, 255].
Note that the keyframe structure in ldat
changes based on the info found in tdb4
.
Shape
Gradient Colors
LIST
GCst
LIST
tdbs
: Property definitionLIST
GCky
: Keyframe valuesUtf8
Gradient XML (repeated)
Orientation
Marker
Text Document
Expressions
Bodymovin modifies expressions when converting into lottie, if you add expressions but fail to convert them, the animation might not play properly.
Assets
Image
Defined within LIST
Item
, it will have idta
with type 7
.
Within that there's a LIST
Pin
, containing the following:
LIST
Als2
with alas
, which in turn has some JSON.
Inside the JSON you can get fullpath
.
opti
: Contains the asset name.
LIST
CLRS
, the last Utf8
here has some JSON with a base64-encoded color profile.
Shapes
Stroke Dashes
Look for the match name ADBE Vector Stroke Dashes
.
Inside of it you'll find a bunch of properties with match name
ADBE Vector Stroke Dash n
or ADBE Vector Stroke Gap n
, where n
is
an ineger starting from 1.
You will also find a single ADBE Vector Stroke Offset
.
They are all animatable lengths and fairly straighforward.
Note that lottie-web wants a unique "name" for these, and the file doesn't provide this but you can generate one based on the match name.
Transforms
Split Position
When a position is split the Position attribute is removed and you can get the data from Position_0 and Position_1.
For some reason Position_0 and Position_1 are present (with value 0
) even when the position is not split.
Their tdsb
seems to change from 1
(not split) to 3
(split).
Effects
The effects used in by the file are defined in the top-level chunk LIST
EfdG
, instanciations of these effects
are present in the layers that use them.
LIST
EfdG
: Effect definitions
Note that the first paramter in an effect should be ignored.
The effects in a later are listed under ADBE Effect Parade
:
Match Names
Follows a list of known match names grouped by object type.
For properties that specify a default value, you should assume they have the specified value if they are not present in the AEP file.
Layers
Match Name | Description | Default |
---|---|---|
ADBE Root Vectors Group |
shapes |
|
ADBE Layer Styles |
styles |
|
ADBE Transform Group |
ks |
|
ADBE Layer Styles |
sy |
|
ADBE Extrsn Options Group |
||
ADBE Material Options Group |
||
ADBE Audio Group |
||
ADBE Layer Sets |
||
ADBE Time Remapping |
tm |
|
ADBE Effect Parade |
ef |
|
ADBE Marker |
Markers |
Match Name | Description | Default |
---|---|---|
ADBE Camera Options Group |
Camera Layer | Marks a layer as a camera layer |
ADBE Camera Aperture |
pe |
|
ADBE Camera Zoom |
Match Name | Description | Default |
---|---|---|
ADBE Text Properties |
Text Data | |
ADBE Text Document |
d |
|
ADBE Text Path Options |
p |
|
ADBE Text More Options |
m |
Shapes
Match Name | Description | Default |
---|---|---|
ADBE Vector Group |
Group | |
ADBE Vector Blend Mode |
bm 12 |
|
ADBE Vectors Group |
it |
|
ADBE Vector Transform Group |
Transform | |
ADBE Vector Materials Group |
Match Name | Description | Default |
---|---|---|
ADBE Vector Shape - Rect |
Rectangle | |
ADBE Vector Shape Direction |
d 1 |
|
ADBE Vector Rect Position |
p |
|
ADBE Vector Rect Size |
s |
|
ADBE Vector Rect Roundness |
r |
Match Name | Description | Default |
---|---|---|
ADBE Vector Shape - Ellipse |
Ellipse | |
ADBE Vector Shape Direction |
d 1 |
|
ADBE Vector Ellipse Position |
p |
|
ADBE Vector Ellipse Size |
s |
Match Name | Description | Default |
---|---|---|
ADBE Vector Shape - Ellipse |
Ellipse | |
ADBE Vector Shape Direction |
d 1 |
|
ADBE Vector Ellipse Position |
p |
|
ADBE Vector Ellipse Size |
s |
Match Name | Description | Default |
---|---|---|
ADBE Vector Shape - Star |
PolyStar | |
ADBE Vector Shape Direction |
d 1 |
|
ADBE Vector Star Type |
sy 1 |
|
ADBE Vector Star Points |
pt 3 |
|
ADBE Vector Star Position |
p |
|
ADBE Vector Star Rotation |
r |
|
ADBE Vector Star Inner Radius |
ir |
|
ADBE Vector Star Outer Radius |
or |
|
ADBE Vector Star Inner Roundess |
is |
|
ADBE Vector Star Outer Roundess |
os |
Match Name | Description | Default |
---|---|---|
ADBE Vector Shape - Group |
Path | |
ADBE Vector Shape Direction |
d 1 |
|
ADBE Vector Shape |
ks 4 |
Shape Styles
Match Name | Description | Default |
---|---|---|
ADBE Vector Graphic - Fill |
Fill | |
ADBE Vector Blend Mode |
bm 12 |
|
ADBE Vector Fill Color |
c 5 |
[255, 255, 0, 0] |
ADBE Vector Fill Opacity |
o |
100 |
ADBE Vector Fill Rule |
r 1 |
1 |
ADBE Vector Composite Order |
if 2, it should be drawn over the previous shape | 1 |
Match Name | Description | Default |
---|---|---|
ADBE Vector Graphic - Stroke |
Stroke | |
ADBE Vector Blend Mode |
bm 12 |
|
ADBE Vector Stroke Color |
c 5 |
[255, 255, 255, 255, ] |
ADBE Vector Stroke Opacity |
o |
100 |
ADBE Vector Stroke Width |
w |
2 |
ADBE Vector Stroke Line Cap |
lc 1 |
1 |
ADBE Vector Stroke Line Join |
lj 1 |
1 |
ADBE Vector Stroke Miter Limit |
ml2 |
4 |
ADBE Vector Stroke Dashes |
d |
|
ADBE Vector Stroke Taper |
||
ADBE Vector Stroke Wave |
||
ADBE Vector Composite Order |
if 2, it should be drawn over the previous shape | 1 |
Match Name | Description | Default |
---|---|---|
ADBE Vector Stroke Taper |
All properties are percentages in [0, 100] | |
ADBE Vector Taper Start Length |
||
ADBE Vector Taper End Length |
||
ADBE Vector Taper Start Width |
||
ADBE Vector Taper End Width |
||
ADBE Vector Taper Start Ease |
||
ADBE Vector Taper End Ease |
Match Name | Description | Default |
---|---|---|
ADBE Vector Stroke Wave |
||
ADBE Vector Taper Wave Amount |
||
ADBE Vector Taper Wave Units |
1 for pixels, 2 for cycles | |
ADBE Vector Taper Wavelength |
||
ADBE Vector Taper Wave Phase |
Match Name | Description | Default |
---|---|---|
ADBE Vector Graphic - G-Fill |
Gradient Fill | |
ADBE Vector Blend Mode |
bm 12 |
|
ADBE Vector Grad Start Pt |
s |
|
ADBE Vector Grad End Pt |
e |
[100, 0] |
ADBE Vector Grad HiLite Length |
h |
|
ADBE Vector Grad HiLite Angle |
a |
|
ADBE Vector Grad Colors |
g 6 |
|
ADBE Vector Fill Opacity |
o |
100 |
ADBE Vector Fill Rule |
r 1 |
1 |
ADBE Vector Composite Order |
if 2, it should be drawn over the previous shape | 1 |
Match Name | Description | Default |
---|---|---|
ADBE Vector Graphic - G-Stroke |
Gradient Stroke | |
ADBE Vector Blend Mode |
bm 12 |
|
ADBE Vector Grad Type |
t |
|
ADBE Vector Grad Start Pt |
s |
|
ADBE Vector Grad End Pt |
e |
|
ADBE Vector Grad HiLite Length |
h |
|
ADBE Vector Grad HiLite Angle |
a |
|
ADBE Vector Grad Colors |
g 6 |
|
ADBE Vector Stroke Opacity |
o |
100 |
ADBE Vector Stroke Width |
w |
2 |
ADBE Vector Stroke Line Cap |
lc 1 |
1 |
ADBE Vector Stroke Line Join |
lj 1 |
1 |
ADBE Vector Stroke Miter Limit |
ml2 |
|
ADBE Vector Stroke Dashes |
d |
|
ADBE Vector Stroke Taper |
||
ADBE Vector Stroke Wave |
||
ADBE Vector Composite Order |
if 2, it should be drawn over the previous shape | 1 |
Shape Modifiers
Match Name | Description | Default |
---|---|---|
ADBE Vector Filter - Merge |
Merge | |
ADBE Vector Merge Type |
mm |
Match Name | Description | Default |
---|---|---|
ADBE Vector Filter - Offset |
Offset Path | |
ADBE Vector Offset Amount |
a |
|
ADBE Vector Offset Line Join |
lj 1 |
|
ADBE Vector Offset Miter Limit |
ml |
Match Name | Description | Default |
---|---|---|
ADBE Vector Filter - PB |
Pucker Bloat | |
ADBE Vector PuckerBloat Amount |
a |
Match Name | Description | Default |
---|---|---|
ADBE Vector Filter - Repeater |
Repeater | |
ADBE Vector Repeater Transform |
tr |
|
ADBE Vector Repeater Copies |
c 3 |
|
ADBE Vector Repeater Offset |
o |
|
ADBE Vector Repeater Order |
m 1 |
Match Name | Description | Default |
---|---|---|
ADBE Vector Filter - RC |
Rounded Corners | |
ADBE Vector RoundCorner Radius |
r |
Match Name | Description | Default |
---|---|---|
ADBE Vector Filter - Trim |
Trim | |
ADBE Vector Trim Start |
s |
|
ADBE Vector Trim End |
e |
|
ADBE Vector Trim Offset |
o |
Match Name | Description | Default |
---|---|---|
ADBE Vector Filter - Twist |
Twist | |
ADBE Vector Twist Angle |
a |
|
ADBE Vector Twist Center |
c |
Match Name | Description | Default |
---|---|---|
ADBE Vector Filter - Roughen |
||
ADBE Vector Roughen Size |
||
ADBE Vector Roughen Detail |
||
ADBE Vector Roughen Points |
||
ADBE Vector Temporal Freq |
||
ADBE Vector Correlation |
||
ADBE Vector Temporal Phase |
||
ADBE Vector Spatial Phase |
||
ADBE Vector Random Seed |
Match Name | Description | Default |
---|---|---|
ADBE Vector Filter - Wiggler |
||
ADBE Vector Xform Temporal Freq |
||
ADBE Vector Correlation |
||
ADBE Vector Temporal Phase |
||
ADBE Vector Spatial Phase |
||
ADBE Vector Random Seed |
||
ADBE Vector Wiggler Transform |
Match Name | Description | Default |
---|---|---|
ADBE Vector Filter - Zigzag |
Zig Zag | |
ADBE Vector Zigzag Size |
s |
|
ADBE Vector Zigzag Detail |
r |
|
ADBE Vector Zigzag Points |
pt 3 |
Transforms
Match Name | Description | Default |
---|---|---|
ADBE Transform Group |
Transform | |
ADBE Anchor Point |
a |
[0, 0] |
ADBE Position |
p |
Half of the comp size |
ADBE Position_0 |
Split position X | |
ADBE Position_1 |
Split position Y | |
ADBE Position_2 |
Split position Z | |
ADBE Scale |
s 7 |
[1, 1] |
ADBE Orientation |
or |
|
ADBE Rotate X |
rx |
|
ADBE Rotate Y |
ry |
|
ADBE Rotate Z |
rz or just normal rotation |
0 |
ADBE Opacity |
o 7 |
1 |
ADBE Envir Appear in Reflect |
Single float, probably a boolean? |
Match Name | Description | Default |
---|---|---|
ADBE Vector Transform Group |
Transform Shape | |
ADBE Vector Anchor Point |
a |
|
ADBE Vector Anchor |
a |
probably an outdated name |
ADBE Vector Position |
p |
|
ADBE Vector Scale |
s |
|
ADBE Vector Rotate X |
rx |
|
ADBE Vector Rotate Y |
ry |
|
ADBE Vector Rotate Z |
rz or just normal rotation |
|
ADBE Vector Rotation |
r |
|
ADBE Vector Group Opacity |
o |
1 |
Match Name | Description | Default |
---|---|---|
ADBE Vector Repeater Transform |
Repeater Transform | |
ADBE Vector Repeater Anchor Point |
a |
|
ADBE Vector Repeater Position |
p |
|
ADBE Vector Repeater Scale |
s 7 |
|
ADBE Vector Repeater Rotation |
r |
|
ADBE Vector Repeater Start Opacity |
so 7 |
1 |
ADBE Vector Repeater End Opacity |
so 7 |
1 |
Effects
Match Name | Description | Default |
---|---|---|
ADBE Tint |
Tint Effect | ty =20 |
ADBE Fill |
Fill Effect | ty =21 |
ADBE Stroke |
Stroke Effect | ty =22 |
ADBE Tritone |
Tritone Effect | ty =23 |
ADBE Pro Levels2 |
Pro Levels Effect | ty =24 |
ADBE Drop Shadow |
Drop Shadow Effect | ty =25 |
ADBE Radial Wipe |
Radial Wipe | ty =26 |
ADBE Displacement Map |
Displacement Map Effect | ty =27 |
ADBE Set Matte3 |
Set Matte Effect | ty =28 |
ADBE Gaussian Blur 2 |
Gaussian Blur Effect | ty =29 |
ADBE Twirl |
Twirl Effect | ty =30 |
ADBE MESH WARP |
Mesh Warp Effect | ty =31 |
ADBE Ripple |
Wavy Effect | ty =32 |
ADBE Spherize |
Spherize Effect | ty =33 |
ADBE FreePin3 |
Puppet Effect | ty =34 |
Match Name | Description | Default |
---|---|---|
ADBE Effect Built In Params |
Marks a LIST tdgp with built-in effect properties |
|
ADBE Effect Mask Opacity |
Match Name | Description | Default |
---|---|---|
ADBE Paint Group |
Data for the paint effect | |
ADBE Paint Atom |
Contains the following properties | |
ADBE Paint Duration |
||
ADBE Paint Shape |
||
ADBE Paint Transform |
Same as other transform but match names starting with ADBE Paint |
|
ADBE Paint Properties |
contains the following | |
ADBE Paint Clone Layer |
Misc
Match Name | Description | Default |
---|---|---|
ADBE Group End |
Indicates the end of a LIST tdgp |
Notes
Enumerations
Most enumerated values are the same in Lottie and AEP, this section lists the exceptions to this
Blend Mode
Name | AEP | Lottie |
---|---|---|
Normal | 1 | 0 |
Darken | 3 | 4 |
Multiply | 4 | 1 |
Color Burn | 5 | 7 |
Linear Burn | 6 | |
Darker Color | 7 | |
Lighten | 9 | 5 |
Screen | 10 | 2 |
Color Dodge | 11 | 6 |
Linear Dodge | 12 | |
Lighter Color | 13 | |
Overlay | 15 | 3 |
Soft Light | 16 | 9 |
Hard Light | 17 | 8 |
Linear Light | 18 | |
Vivid Light | 19 | |
Pin Light | 20 | |
Hard Mix | 21 | 16 |
Difference | 23 | 10 |
Exclusion | 24 | 11 |
Hue | 26 | 12 |
Saturation | 27 | 13 |
Color | 28 | 14 |
Luminosity | 29 | 15 |
Chunk Data
Note that chunks might have extra data after what is described here, always parse exactly as many bytes as specified in the chunk header.
LIST
This chunk is defined by the RIFF specs, its data has the following format:
Starts with an id
, specifying the type of the list, then followed by sub-chunks.
The format of specific LIST
types are described later in this document.
Note that the LIST
btdk
doesn't conform to RIFF,
so take care to not read over the chunk length.
Utf8
Contains utf-8 encoded text. Sometimes it contains the string -_0_/-
which (I guess)
is used as a placeholder for objects lacking a name.
tdsn
/ fnam
/ pdnm
Contains a Utf8
chunk, used for object names
tdmn
Contains a NUL-terminated string (You'll need to strip excess \0
) and defines a Match Name.
fdta
Folder data.
cdta
Composition data.
Field Name | Size | Type | Description |
---|---|---|---|
5 | |||
Time Scale | 2 | uint16 |
How much Time values are scaled by |
14 | |||
Playhead | 2 | Time | Playhead time |
6 | |||
In Time | 2 | Time | Same as ip in Lottie |
6 | |||
Out Time | 2 | Time | Same as op in Lottie |
6 | |||
Comp duration | 2 | Time | Duration setting in AE |
5 | |||
Color | 3 | bytes |
Color as 24 bit RGB |
85 | |||
Width | 2 | uint16 |
Same as w in Lottie |
Height | 2 | uint16 |
Same as h in Lottie |
12 | |||
Framerate | 2 | uint16 |
Same as fr in Lottie |
Note that End Time might have a value of FFFF, if that's the case assume it to be the same as Comp Duration.
ldta
Layer data, it seems that AE23 adds 4 extra 00
bytes at the end compared to older versions.
Field Name | Size | Type | Description |
---|---|---|---|
Layer ID | 4 | uint32 |
|
Quality | 2 | uint16 |
0 : Wireframe, 1 : Draft, 2 : Best |
7 | |||
Start Time | 2 | sint16 |
Time offset for times withing the layer |
6 | |||
In Time | 2 | Time | Same as ip in Lottie |
6 | |||
Out Time | 2 | Time | Same as op in Lottie |
6 | |||
Attributes | 3 | Flags | |
Source ID | 4 | uint32 |
Item id for the used asset |
17 | |||
Label Color Index | 1 | uint8 |
Color on the timeline |
2 | |||
Layer Name | 32 | string0 |
It's repeated in the Utf8 chunk right after |
11 | |||
Matte Mode | 1 | uint8 |
|
Layer Type | 1 | uint8 |
|
Parent ID | 4 | uint32 |
ID of the parent layer, if any |
24 | |||
Matte Layer ID | 4 | uint32 |
Id of the layer masking the current layer, if any |
With the following Attributes:
- Guide: (0, 1) Guide layers aren't rendered
- Bicubic Sampling: (0, 6)
- Auto Orient: (1, 0)
- Adjustment: (1, 1) Whether it's an adjustment layer
- Threedimensional: (1, 2)
- Solo: (1, 3) (UI thing, only displays that layer)
- Null: (1, 7) Whether it's a null layer
- Visible: (2, 0)
- Effects: (2, 2)
- Motion Blur: (2, 3)
- Locked: (2, 5)
- Shy: (2, 6) (Used to hide some layers in the AE UI)
- Conitnuosly Rasterize (vector) / Collapse Transform (comps): (2, 7)
Layer Types:
- 0: Asset Layer
- 1: Light Layer
- 2: Camera Layer
- 3: Text Layer
- 4: Shape Layer
Label Colors:
- None (shows as grey)
- Red
- Yellow
- Aqua
- Pink
- Lavender
- Peach
- Sea Foam
- Blue
- Green
- Purple
- Orange
- Brown
- Fuchsia
- Cyan
- Sandstone
- Dark Green
Matte Modes:
- No Matte
- Alpha
- Inverted Alpha
- Luma
- Inverted Luma
idta
Item data.
Field Name | Size | Type | Description |
---|---|---|---|
Type | 2 | uint16 |
|
14 | |||
ID | 4 | uint32 |
ID used to reference this item |
The Type field above can have the following values:
1
: Folder4
: Composition7
: Footage
The last 2 bytes of this field seem to change every time you make a change.
tdb4
Property metadata.
Field Name | Size | Type | Description |
---|---|---|---|
2 | Always db 99 ? |
||
Components | 2 | uint16 |
Number of values in a multi-dimensional |
Attributes | 2 | Flags | |
1 | |||
1 | Some sort of flag, it has value 03 for position properties |
||
2 | |||
2 | |||
2 | Always 0000 ? |
||
2 | 2nd most significant bit always on, perhaps some kind of flag | ||
8 | float64 |
Most of the time 0.0001 |
|
8 | float64 |
Most of the time 1.0 , sometimes 1.777 |
|
8 | float64 |
Always 1.0 ? |
|
8 | float64 |
Always 1.0 ? |
|
8 | float64 |
Always 1.0 ? |
|
Type? | 4 | Flags | See below |
1 | Seems correlated with the previous byte, it's set for 04 for enum properties |
||
7 | Bunch of 00 |
||
Animated | 1 | Set to 1 when animated, kinda the reverse of the Static bit in Attributes |
|
7 | Bunch of 00 |
||
4 | Usually 0, probs flags | ||
4 | Mst likely flags, only last byte seems to contain data | ||
8 | float64 |
Always 0.0 ? |
|
8 | float64 |
Mostly 0.0 , sometimes 0.333 |
|
8 | float64 |
Always 0.0 ? |
|
8 | float64 |
Mostly 0.0 , sometimes 0.333 |
|
4 | Probs some flags | ||
4 | Probs some flags |
Attributes:
- Position: (1, 3). When
true
, this is a position property, which changes how animated values are parsed. - Static: (1, 0). When
false
, the property is animated and it will have acdat
.
Types:
- No Value: (1, 0). Used for properties like shapes, gradients, etc, where the values are not in the keyframe.
- Color: (3, 0). Set for color properties (they have a different keyframe format).
cdat
Property static value.
For multi-dimensional properties, you look at the number of components in tdb4
and parse that many float64
, that's the value of the property.
shph
Header for bezier shape data, contained within LIST
shap
.
It's followed by a LIST
list
with bezier data.
Field Name | Size | Type | Description |
---|---|---|---|
3 | |||
Attributes | 1 | Flags | |
Top Left | 2 | float32 |
Top-left corner of the shape area, relative to the layer position |
Bottom Right | 2 | float32 |
Bottom-right corner of the shape area, relative to the layer position |
4 |
Flags:
- Open: (0, 3). When
true
, the shape is open (it's missing the segment connecting the last point to the first)
lhd3
Inside a LIST
list
, defines the data format, followed by ldat
.
Field Name | Size | Type | Description |
---|---|---|---|
4 | Seems to always be 00 d0 0b ee |
||
6 | All 00 |
||
Count | 2 | uint16 |
Number of items |
4 | The last byte is the only one that changes, greatest variation is on shapes | ||
2 | All 00 |
||
Item Size | 2 | uint16 |
Size of an item in the list |
3 | All 00 |
||
Type? | 1 | ||
4 | 00 00 00 01 |
||
2 | All 00 |
||
2 | Some kind of flags | ||
20 | All 00 |
Item Type | Size | Type |
---|---|---|
Gide |
00 01 |
02 |
LItm |
00 80 |
01 |
LRdr |
08 c6 |
01 |
Color Kf | 00 98 |
04 |
1D Kf | 00 30 |
04 |
2D Kf | 00 58 |
04 |
2D pos Kf | 00 68 |
04 |
3D Kf | 00 80 |
04 |
3D pos Kf | 00 80 |
04 |
Marker Kf | 00 10 |
04 |
Orientation Kf | 00 50 |
04 |
No Value Kf | 00 40 |
04 |
The corresponding ldat
should have Item Size * Count bytes, and it's omitted if Count is 0.
ldat
Inside a LIST
list
, contains the list data, preceded by lhd3
.
The number of element is the one defined in lhd3
.
It has a different format based on certain conditions, follow some of the possible element formats.
The size of an item is found like so:
item_size = ldat_chunk_length / lhd3_count
Keyframe (common)
All keyframe items start like this:
Field Name | Size | Type | Description |
---|---|---|---|
1 | |||
Time | 2 | Time | Time of the keyframe, seems they always start from 0. |
2 | |||
Attributes | 1 | Flags | |
Label Color | 1 | uint8 |
Color index, see ldta for values |
Extra Attributes | 1 | Flags |
Attributes:
- Linear (0, 0) seems to be on then Ease is off
- Ease (0, 1)
- Hold (0, 2)
Extra Attributes:
Least significant 3 bits seems to always be on.
- Continuous Bezier (0, 3)
- Auto Bezier (0, 4)
- Roving across time (0, 5)
Keyframe - Multi-Dimensional
Given n
as the number of dimensions found in tdb4
(eg: 3 for 3D positions):
Field Name | Size | Type | Description |
---|---|---|---|
Value | 8* n | float64[n] |
Value |
In Speed | 8* n | float64[n] |
|
In Influence | 8* n | float64[n] |
|
Out Speed | 8* n | float64[n] |
|
Out Influence | 8* n | float64[n] |
Keyframe - Position
If the property is an animated position, the keyframe is formatted like so:
Field Name | Size | Type | Description |
---|---|---|---|
8 | |||
8 | float64 |
||
In Speed | 8 | float64 |
|
In Influence | 8 | float64 |
|
Out Speed | 8 | float64 |
|
Out Influence | 8 | float64 |
|
Value | 8* n | float64[n] |
Value |
Tan In | 8* n | float64[n] |
Spatial tangents |
Tan Out | 8* n | float64[n] |
Spatial tangents |
Keyframe - No Value
Used for shapes and gradients (Special set in tdb4
)
Field Name | Size | Type | Description |
---|---|---|---|
8 | |||
8 | float64 |
||
In Speed | 8 | float64 |
|
In Influence | 8 | float64 |
|
Out Speed | 8 | float64 |
|
Out Influence | 8 | float64 |
|
8 |
Keyframe - Color
Field Name | Size | Type | Description |
---|---|---|---|
8 | |||
8 | float64 |
||
In Speed | 8 | float64 |
|
In Influence | 8 | float64 |
|
Out Speed | 8 | float64 |
|
Out Influence | 8 | float64 |
|
Value | 8*4 | float64[4] |
ARGB 255 |
8*8 | float64[8] |
Shape Data
Bezier data, positions are relative to the area defined by shph
.
The list is a sequence of points, appearing in this order:
- Vertex 0
- Out Tangent 0
- In Tangent 1
- Vertex 1
- Out Tangent 1
- ...
Note that all coordinates are relative to the area in shph
but not to each other.
A coordinate of [0, 0] will correspond to the top-left corner in shph
,
and [1, 1] corresponds to the bottom-right.
Field Name | Size | Type | Description |
---|---|---|---|
X | 4 | float32 |
X Coordinate |
XY | 4 | float32 |
X Coordinate |
pprf
Color profile information as ICC data.
wsnm
Worspace name.
Utf-16 encoded string, contains the name of the "workspace" (window layout in AE)
It's always followed by an Utf8
with the same content.
tdum
/ tduM
float64
values often found inside LIST
tdbs
.
In some cases they seem to indicate minimum and maximum values for that
property but there are some cases in which they are both 0.0
.
ppSn
Contains a float64
, unknown meaning.
otda
Orientation data
Field Name | Size | Type | Description |
---|---|---|---|
X | 8 | float64 |
X Coordinate |
Y | 8 | float64 |
Y Coordinate |
Z | 8 | float64 |
Z Coordinate |
opti
Asset data, format depends on type
Field Name | Size | Type | Description |
---|---|---|---|
Type | 4 | string |
Asset type |
Solid
Type Soli
, data for solid layers.
Field Name | Size | Type | Description |
---|---|---|---|
6 | |||
Alpha | 4 | float32 |
|
Red | 4 | float32 |
|
Green | 4 | float32 |
|
Blue | 4 | float32 |
|
Name | 256 | string0 |
Color components are in [0, 1].
sspc
Footage / asset data.
Field Name | Size | Type | Description |
---|---|---|---|
32 | |||
Width | 2 | uint16 |
|
2 | |||
Height | 2 | uint16 |
alas
JSON string containing external asset info.
head
Seems the first 6 bytes contain AE version information.
I haven't been able to decode it fully but here's a list of values encountered in the wild:
Version | Bytes |
---|---|
15.0 | 5c 06 07 38 06 b4 |
16.0 | 5d 04 0b 00 06 eb |
16.0.1 | 5d 04 0b 00 0e 30 |
16.1.2 | 5d 05 0b 00 96 37 |
16.1.3 | 5d 05 0b 00 9e 05 |
17.0 | 5d 09 4b 08 06 2b |
17.0.4 | 5d 0b 0b 08 26 3b |
18.2.1 | 5d 1b 0b 11 0e 08 |
18.4 | 5d 1d 0b 12 06 26 |
22.0 | 5d 1d 0b 70 06 6f |
22.6 | 5d 2b 0b 33 06 3b |
23.2.1 | 5e 03 0b 39 0e 03 |
EfDC
The first byte contains the number of LIST
EfDf
in a LIST
EfdG
parn
Contains a uint64
with the number of parameters in a LIST
parT
.
pard
Effect parameter definition.
Field Name | Size | Type | Description |
---|---|---|---|
15 | |||
Type | 1 | uint8 |
Parameter type |
Name | 32 | string0 |
|
4 | |||
Default? | 4 | ||
Last used value? |
Types:
Type Name | AEP | Lottie | Lottie Object |
---|---|---|---|
Layer | 0 |
10 |
Effect Value Layer |
Scalar | 2 |
0 |
Effect Value Slider |
Angle | 3 |
1 |
Effect Value Angle |
Boolean | 4 |
4 |
Effect Value Checkbox |
Color | 5 |
2 |
Effect Value Color |
2D | 6 |
3 |
Effect Value Point |
Enum | 7 |
7 |
Effect Value Drop Down |
Paint Group | 9 |
||
Slider | 10 |
0 |
Effect Value Slider |
Group | 13 |
5 |
Custom Effect |
Unknown | 15 |
6 |
Effect No Value |
3D | 16 |
3 |
Effect Value Point |
prin
Seems to always have the same content:
4 00
bytes, the string ADBE Escher
, 37 00
, the string Classic 3D
,
41 00
, and ends with 01
.
prda
Seems to always have the same content: 3 00
, a 01
, 8 00
.
NmHd
Marker attributes
Name | Size | Type | Description |
---|---|---|---|
3 | |||
Attributes | 1 | Flags | |
Duration | 4 | uint32 |
Duration in frames |
4 | |||
Label Color | 1 | uint8 |
Color index, see ldta for values |
Flags:
- Protected: (0, 1) The marker signals a protected region
- ???: (0, 2) This flags seems to always be on
tdsb
4 bytes specifying flags for a tdgp
.
the least significant bit marks if an object is visible.
LIST
Fold
Top level item.
LIST
Item
Item, you can check its properties with idta
contained inside it.
LIST
Layr
Defines a layer.
Layer metadata is found in a ldta
, the layer name is in a Utf8
.
Go through its LIST
tdgp
to get shapes and transforms.
You will find the following match names within it:
ADBE Root Vectors Group
: Contains shape data (shape layer in lottie)ADBE Camera Options Group
: Lottie camera layerADBE Transform Group
: Layer transformADBE Layer Styles
: Layer styles
LIST
tdgp
Defines a list of an object. To know what type of object, you need to check
the tdmn
preceding this chunk.
Flags for the objects are in tdsb
.
The name of the object is in tdsn
> Utf8
.
Then follows a sequence of properties / objects defined as such:
tdmn
specifies the match name of the object, then it's followed by
chunks that describe said object (usually more LIST
s).
Usually the last chunk here is a tdmn
with value ADBE Group End
.
LIST
tdbs
Defines an object's property. To know which property, you need to
check the tdmn
preceding this chunk.
It will contain a tdb4
, and usually cdat
(static) or a List
list
(animated).
For properties with expressions, it will have a Utf8
with the expression code.
LIST
GCst
Defines a gradient.
Contains a LIST
tdbs
and a LIST
GCky
.
LIST
GCky
Gradient color keyframes.
Contains a sequence of Utf8
formatted in XML with the gradient definition
for each keyframe.
LIST
om-s
Contains a LIST
tdbs
and a LIST
omks
to define a shape property.
LIST
omks
Bezier shape data.
Contains a sequence of LIST
shap
with the shape data for each keyframe.
LIST
shap
Contains a shph
and a LIST
list
with the shape data.
LIST
CPPl
Contains a pprf
.
LIST
list
For animated properties it replaces cdat
.
The list header is defined in the chunk lhd3
, the list data in ldat
.
LIST
SLay
/ LIST
DLay
/ LIST
CLay
They seem to be camera layers used to store internal views, not exported to lottie.
SLay
(Side views?) have names like "Top" and "Front", perhaps they define 3d views.
CLay
: Custom views.
DLay
: Default views.
LIST
SecL
Composition Markers Layer.
Contains ldta
and like other layers.
in LIST
tbgp
look for the match name ADBE Marker
, the data is in
the LIST
mrst
.
LIST
mrst
Marker property.
Contains a LIST
tdbs
that defines the property, which should always be animated
when present.
Marker keyframe values are available in LIST
mrky
.
LIST
mrky
Marker keyframes.
contains a LIST
Nmrd
for each keyframe
LIST
Nmrd
Marker data
There's a NmHd
with the attributes.
The marker comment is in the first Utf8
LIST
otst
Orientation property.
Contains a LIST
tdbs
and a LIST
otky
to define a shape property.
LIST
otky
Contains a sequence of otda
with the orientation data for each keyframe.
LIST
CpS2
They contain a CsCt
and two Utf8
, the last of which seems to
contain a locale name (eg: en_US
)
LIST
Als2
Contains alas
for external assets.
LIST
Sfdr
Asset folder contents, contains several LIST
Item
.
LIST
btdk
For some reason this doesn't conform to the RIFX specs, instead of a list its data is encoded in Carousel Object Structure (COS).
The COS format is the same used in PDF but it's extremely difficult to find detailed information on it, the best technical specs is this very old PDF 1.7 specification.
Once you parse the COS, you can find the following data:
0.1.0
: Array of available fonts:0.99
:CoolTypeFont
0.0.0
: Font family (seems to have bold/italic encoded in the name)0.0.2
:0
or1
?
1.1
: Array of text documents (one for each keyframe) in this format:0.0
: Text0.5.0
: Array of paragraph styles0.0.5
Paragraph Style:0
: Text align (0
: left,1
: right,2
: center)
1
: Length (in characters) the style applies to
0.6.0
: Array of character styles:0.0.6
: Character Style:0
: Index of the font from the array of available fonts1
: Font size2
: Faux Bold3
: Faux Italic12
:0
: Normal,1
: Small caps,2
: All caps13
:0
: Normal,1
: Superscript,2
: Subscript53.0.1
: Fill color in ARGB [0, 1]54.0.1
: Stroke color in ARGB [0, 1]57
: Stroke enabled58
: Stroke over fill63
: Stroke width
1
: Length (in characters) the style applies to
LIST
sspc
Effect Definiton.
The generic effect name is in fnam
> Utf8
.
The effect parameters are defined in LIST
parT
.
If the effect type has already been encountered, you might not find the
LIST
parT
here, you might need to match the name to an entry in LIST
EfdG
.
It finally contains a LIST
tdgp
where the effect properties are present
like any other animated property. You can also find the name
of the effect object in fnam
> Utf8
.
Inside there you can also find a match name with ADBE Effect Built In Params
which will contain values for built-in effect parameters.
LIST
parT
Effect parameters.
Contains a parn
with the number of parameters, then follows
a list of tdmn
with the match name of the parameter followed by
pard
with its definition.
Enum parameters have their values in a pdnm
separated by |
pipes.
The first property seems to be a dummy?
LIST
EfdG
Effect definitions.
This is where effect types used by the project are defined.
Basically it repeats the first instance of any effect found in the layers.
it contains a EfDC
with the number of effects, and that many LIST
EfDf
.
LIST
EfDf
Effect type definition.
Contains a tdmn
with the match name of the effect and a LIST
sspc
.
LIST
ExEn
Contains a Utf8
with the expression language (eg: javascript-1.0
).
LIST
PRin
Contains a prin
and a prda
.
LIST
Pin
Asset properties.
Contains:
Gradient XML
Gradient data seems to be stored in a convoluted XML structure.
The easiest way to describe it is as a mapping, the elements can be parsed like so:
Tag Name | Logical Type | Description |
---|---|---|
prop.map |
Top-level, just get its first child | |
prop.list |
dict |
Mapping of key-value pairs |
prop.pair |
Item in prop.list |
|
key |
str |
Property key |
array |
list |
Array of values, the first item is array.type which specifies the type |
int |
int |
|
float |
float |
|
string |
str |
If you interpret the XML as a mapping, you can gather the following info:
{
"Gradient Color Data":
{
"Alpha Stops":
{
"Stops List":
{
"Stop-0":
{
"Stops Alpha":
[
0.0, // offset
0.5, // midpoint
1.0 // alpha
]
},
// More stops defined the same way...
}
"Stops Size": 2 // Number of stops
},
"Color Stops":
{
"Stops List":
{
"Stop-0":
{
"Stops Color":
[
0.0, // offset
0.5, // midpoint
0.0, // red
0.0, // green
0.5, // blue
1.0 // alpha?
]
},
// More stops defined the same way...
}
"Stops Size": 2 // Number of stops
}
},
"Gradient Colors": "1.0" // Version?
}
Midpoint
You should use the "midpoint" values to add an additional color which is halfway between the other two.
For example given these stops:
"Stop-0":
{
"Stops Color":
[
0.0, // offset
0.5, // midpoint
0.1, // red
0.2, // green
0.3, // blue
1.0 // alpha?
]
},
"Stop-0":
{
"Stops Color":
[
0.6, // offset
0.5, // midpoint
0.3, // red
0.4, // green
0.5, // blue
1.0 // alpha?
]
},
The final gradient will look like this:
[
// stop 0
0.0, // offset_0
0.1, // red_0
0.2, // green_0
0.3, // blue_0
// midpoint stop
0.3, // offset_0 * (1 - midpoint_0) + offset_1 * midpoint_0
0.2, // (red_0 + red_1) / 2
0.3, // (green_0 + green_1) / 2
0.4, // (blue_0 + blue_1) / 2
// stop 1
0.6, // offset_1
0.5, // midpoint_1
0.3, // red_1
0.4, // green_1
0.5, // blue_1
]
Opacity
For some reason in AE gradients alpha is independent from the color, so you have separate stops for color and opacity.
You should treat the midpoint value for opacity stops in a similar way as to the color ones.
Once you have both the color and opacity values, the final lottie array is simply a concatenation of the two.
XMP Metadata
After the RIFX data, an AEP file also contains some XML in the XMP format.
This section contains the version of AfterEffects, when the file has been created and modified, and related info.
XML Project Format
Aftereffects allows you to save the project as XML.
This is basically as the RIFX but with a different container format and binary data encoded as hex.
Conversion notes for elements are provided below
AfterEffectsProject
Root element, same as RIFX
.
ProjectXMPMetadata
In the RIFX file this is dumped at the end without a chunk.
string
Used instead of Utf8
.
numS / ppSn
For some reason they have their value in a <string>
but are not string in the RIFX.
tdsn / fnam / pdnm
These elements contain children but they are not LIST
in RIFX, that's the only thing of note.
Child elements
If an element has children. it's the same as the equivalent LIST
in RIFX.
bdata
Elements with the bdata
attribute have their binary data hex encoded in said attribute.
You can parse their data the same way as you'd do in RIFX.
Resources
- aftereffects-aep-parser A basic AEP parser written in Go.
- Multimedia Programming Interface and Data Specifications 1.0 RIFF specs PDF.
- Floating Point to Hex Converter Float to hex converter.
- bodymovin-extension AE extensions that exports to Lottie
- After Effects Scripting Guide
- Shape Layer Match Names
- Portable document format — Part 1: PDF 1.7 The only COS reference I've found