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 integers.

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

In the chunk data descriptions, the types described below will be used to show how to interpret the raw binary data.

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

The index of the byte here is in file order so a byte of 0 is the most significant byte.

AfterEffects Logic

This section assumes the file has already been parsed into RIFF chunks.

Objects described here will have a nested list showing which chunks are used to represent them, you can click on the link pointing to the chunk details to get the data layout within that chunk.

File Structure

Folder Item

idta will cointain the ID of the item (referenced by layers) and the item type.

The following sections descript each type of item in detail

Folders

idta type 1. These contain additional items inside them.

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).

Structure:

Each layer will show as a LIST Layr in the LIST Item.

The composition will also have other type of layer LISTs:

If the comp uses essential graphics, it will have the appropriate LISTs as well.

Assets

idta type 7. These can have different kinds of contents.

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 alas, parse it as JSON and get fullpath.

the first 4 bytes of opti will change based on the file format.

Layers

When parsing layer transforms, keep in mind the default position is the center of the comp. For shape layers, the default anchor is [0, 0]; for precomp layers the default anchor is the center of the comp (same as position).

Asset Layer

Layer type 0.

(Also known as AVLayer in AE) They have a non-zero Source ID in ldta.

Precomp, image, and similar layers 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

Layer type 1.

For light settings look for the match name ADBE Light Options Group.

Camera Layer

Layer type 2.

For camera settings look for the match name ADBE Camera Options Group.

Text Layer

Layer type 3.

For text contents look for the match name ADBE Text Properties.

Shape Layer

Layer type 4.

For shapes look for the match name ADBE Root Vectors Group.

Property Groups

Most objects are described as a property groups.

These have the following structure:

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
    • tdb4: Tells you the type, number of components, whether it's animated
    • cdat: Value (if not animated)
    • tdsn:
      • Utf8: Human-readable Name
    • Utf8: Optional expression
    • LIST list: Keyframes (if animated)
      • lhd3: Tells you the number of keyframes
      • ldat: Keyframe data and values

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

Orientation

Marker

Text Document

Layer

Follows the usual LIST tdbs, check tdb4 for the "Integer" property type.

Mask Index

Follows the usual LIST tdbs, check tdb4 for the "Integer" property type.

Mask

Layer Overrides

  • LIST OvG2
    • CprC: uint32?

Layer Source Alternate

  • blsv: uint32 Layer index?
  • blsi: uint32

Chunk naming

Most of property related chunks seem to contain the prefix td in their name:

  • tdgp: property group
  • tdsb: property group flags
  • tdsn: property group name
  • tdmn: property match name
  • tdbs: property definition
  • tdb4: property details

I'm not sure what td stands for my best guess would be "Track Data".

For properties with external values, the naming convention generally is XXst for the parent chunk and XXky for the values (where XX changes depending on the type and its meaning is fairly obvious).

I'm not sure what st stands for, ky most likely stands for "keyframes"

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
    • EfDC: Effect definition count (number of definitions)
    • LIST EfDf: Effect definition (one per effect type used in the document)
      • tdmn: Effect match name
      • LIST sspc
        • fnam > Utf8: Effect name
        • LIST parT: Effect parameters
          • parn: Number of parameters
          • tdmn: Parameter match name
          • pard: Parameter definition
          • pdnm: (optional) Parameter control strings
          • You get tdmn and pard (optionally followed by pdnm for each parameter
        • LIST tdgp: Contains the values of the first instance of this effect, can be ignored

Note that the first paramter in an effect should be ignored.

The effects in a later are listed under ADBE Effect Parade:

  • tdmn: Effect match name, you'll need to find the matching definition
  • LIST sspc
    • fnam > Utf8: Effect name
    • LIST parT: You might find this here as well but it isn't consistent. Refer to LIST EfdG for the definition
    • LIST tdgp: Parameter values, works like any other property list

Essential Graphics

Definition

Essential graphics are defined in the following chunks inside the comp's LIST Item:

They seem to have the same structure and (almost) identical values. But only CIF3 has data about groups:

  • LIST CIF3
    • LIST CpS2
      • CsCt: seems to always have the value 0x1000000.
      • Utf8: Name (Defaults to Untitled)
      • Utf8: Locale? (en_US)
    • CapS
      • CsCt: seems to always have the value 0x1000000.
      • CapL: seems to always have the value 0.
      • Utf8: Name (again, same value as before)
    • LIST CCtl: Item (repeated)

Items have the following common structure

Comment
Group
Property
  • CVal: Value
  • CDef: Default Value
  • Smin: Slider min value (only for scalar properties)
  • Smax: Slider max value (only for scalar properties)
  • CDim: Number of dimenstions (only for vector properties)
  • LIST StVc: Enum values (only for enum properties)
    • StVS: Count
    • Utf8: Value name (repeated)
  • CprC: 1
  • LIST CPrp
    • CCId: Composition ID (same as the one in idta).
    • CLId: Layer ID (same as the one in ldta).
    • Utf8: JSON-ecoded path.

The JSON is a dict where the key is a string containing a number and the values are dicts like this:

  • index: Index for like shape groups and such, or the value 4294967295 (0xffffffff) is used when there is no index
  • matchName: Match name as per usual

To find the property, something like this might work:

CCId = 15
CLId = 18
json_data = {
    "0": {
        "index":4294967295,
        "matchName":"ADBE Root Vectors Group"
    },
    "1": {
        "index":0,
        "matchName":"ADBE Vector Group"
    },
    "2": {
        "index":4294967295,
        "matchName":"ADBE Vectors Group"
    },
    "3": {
        "index":2,
        "matchName":"ADBE Vector Graphic - Fill"
    },
    "4": {
        "index":4294967295,
        "matchName":"ADBE Vector Fill Opacity"
    }
}

property = get_layer(CCId, CLId)

for item in json_data.values():
    if item["index"] == 0xffffffff:
        property = property.property(item["matchName"])
    else:
        property = property.properties[item["index"]]

The values in Smin, Smax, CVal, CDef depends on the type, refer to CTyp for their representation.

Overrides

Defined in the precomp layer under match name ADBE Layer Overrides

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
ADBE Mask Parade masksProperties
ADBE Plane Options Group
ADBE Data Group
ADBE Layer Overrides Essential graphincs values
ADBE Source Options Group
Match Name Description Default
ADBE Camera Options Group Camera Layer Marks a layer as a camera layer
ADBE Camera Aperture pe
ADBE Camera Zoom
ADBE Camera Focus Distance
Match Name Description Default
ADBE Mask Atom Mask
ADBE Mask Shape pt
ADBE Mask Offset x 0
ADBE Mask Feather [0, 0]
ADBE Mask Opacity 0 100
Match Name Description Default
ADBE Extrsn Options Group
ADBE Bevel Direction
Match Name Description Default
ADBE Material Options Group
ADBE Appears in Reflections
ADBE Reflection Coefficient
ADBE Glossiness Coefficient
ADBE Fresnel Coefficient
ADBE Transparency Coefficient
ADBE Transp Rolloff
ADBE Index of Refraction
Match Name Description Default
ADBE Source Options Group
ADBE Layer Source Alternate
Match Name Description Default
ADBE Layer Styles
ADBE Blend Options Group
Match Name Description Default
ADBE Blend Options Group
ADBE Adv Blend Group

Shapes

Match Name Description Default
ADBE Vector Group Group
ADBE Vector Blend Mode bm12
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 d1
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 d1
ADBE Vector Ellipse Position p
ADBE Vector Ellipse Size s
Match Name Description Default
ADBE Vector Shape - Star PolyStar
ADBE Vector Shape Direction d1
ADBE Vector Star Type sy1
ADBE Vector Star Points pt3
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 d1
ADBE Vector Shape ks4

Shape Styles

Match Name Description Default
ADBE Vector Graphic - Fill Fill
ADBE Vector Blend Mode bm12
ADBE Vector Fill Color c5 [255, 255, 0, 0]
ADBE Vector Fill Opacity o 100
ADBE Vector Fill Rule r1 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 bm12
ADBE Vector Stroke Color c5 [255, 255, 255, 255, ]
ADBE Vector Stroke Opacity o 100
ADBE Vector Stroke Width w 2
ADBE Vector Stroke Line Cap lc1 1
ADBE Vector Stroke Line Join lj1 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 Stroke Dashes
ADBE Vector Stroke Offset
ADBE Vector Stroke Gap #
ADBE Vector Stroke Dash #
Match Name Description Default
ADBE Vector Graphic - G-Fill Gradient Fill
ADBE Vector Blend Mode bm12
ADBE Vector Grad Type t1
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 g6
ADBE Vector Fill Opacity o 100
ADBE Vector Fill Rule r1 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 bm12
ADBE Vector Grad Type t1
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 g6
ADBE Vector Stroke Opacity o 100
ADBE Vector Stroke Width w 2
ADBE Vector Stroke Line Cap lc1 1
ADBE Vector Stroke Line Join lj1 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 lj1
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 c3
ADBE Vector Repeater Offset o
ADBE Vector Repeater Order m1
Match Name Description Default
ADBE Vector Filter - RC Rounded Corners
ADBE Vector RoundCorner Radius r 10
Match Name Description Default
ADBE Vector Filter - Trim Trim
ADBE Vector Trim Start s
ADBE Vector Trim End e
ADBE Vector Trim Offset o
ADBE Vector Trim Type m1
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 10
ADBE Vector Zigzag Detail r 5
ADBE Vector Zigzag Points pt1

Transforms

Match Name Description Default
ADBE Transform Group Transform
ADBE Anchor Point a8 [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 s7 [1, 1]
ADBE Orientation or
ADBE Rotate X rx
ADBE Rotate Y ry
ADBE Rotate Z rzor just normal rotation 0
ADBE Opacity o7 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 [100, 100]
ADBE Vector Rotate X rx
ADBE Vector Rotate Y ry
ADBE Vector Rotate Z rzor just normal rotation
ADBE Vector Rotation r
ADBE Vector Skew sk
ADBE Vector Skew Axis sa
ADBE Vector Group Opacity o 100
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 s7
ADBE Vector Repeater Rotation r
ADBE Vector Repeater Start Opacity so7 1
ADBE Vector Repeater End Opacity so7 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

Text

Match Name Description Default
ADBE Text Properties Text Data
ADBE Text Document d
ADBE Text Path Options p
ADBE Text More Options m
ADBE Text Animators a
Match Name Description Default
ADBE Text Animator Text Range
ADBE Text Selectors s(list)
ADBE Text Animator Properties a
Match Name Description Default
ADBE Text Selector Text Range Selector
ADBE Text Percent Start s 0
ADBE Text Percent End e 100
ADBE Text Percent Offset o 0
ADBE Text Index Start s
ADBE Text Index End e
ADBE Text Index Offset o
ADBE Text Range Advanced
ADBE Text Selector Max Amount a
ADBE Text Selector Smoothness sm
ADBE Text Levels Max Ease xe
ADBE Text Levels Min Ease ne
ADBE Text Random Seed rn
Match Name Description Default
ADBE Text Animator Properties Text Style
ADBE Text Anchor Point 3D a
ADBE Text Position 3D p
ADBE Text Scale 3D s
ADBE Text Skew sk
ADBE Text Skew Axis sa
ADBE Text Rotation X rx
ADBE Text Rotation Y ry
ADBE Text Rotation r
ADBE Text Opacity o
ADBE Text Fill Color fc
ADBE Text Fill Opacity fo
ADBE Text Fill Hue fh
ADBE Text Fill Saturation fs
ADBE Text Fill Brightness fb
ADBE Text Stroke Color sc
ADBE Text Stroke Opacity so
ADBE Text Stroke Hue sh
ADBE Text Stroke Saturation ss
ADBE Text Stroke Brightness sb
ADBE Text Stroke Width sw
ADBE Text Line Spacing ls
ADBE Text Line Anchor
ADBE Text Track Type
ADBE Text Tracking Amount
ADBE Text Character Replace
ADBE Text Character Offset
ADBE Text Blur
Match Name Description Default
ADBE Text Path Options Text Follow Path
ADBE Text Path m
ADBE Text Reverse Path r
ADBE Text Perpendicular To Path p
ADBE Text Force Align Path a
ADBE Text First Margin f
ADBE Text Last Margin l
Match Name Description Default
ADBE Text More Options Text Alignment Options
ADBE Text Anchor Point Option g 1
ADBE Text Anchor Point Align a [0, 0]
ADBE Text Render Order 1
ADBE Text Character Blend Mode 1

Misc

Match Name Description Default
ADBE Group End Indicates the end of a LIST tdgp

Notes


  1. Enumerations needs to be converted from floats, but the values match. 

  2. Blend mode has different values than Lottie, see the section below for details. 

  3. Needs to be converted from float to int

  4. How to parse this? 

  5. Colors are defined as 4 floats (ARGB) in [0, 255]. 

  6. Colors defined as XML

  7. You need to multiply by 100 to get the lottie value. 

  8. For asset layers, the anchor point is relative to the size of the asset (eg: (0.5, 0.5) would be the center). 

Enumerations

Most enumerated values are the same in Lottie and AEP, this section lists the exceptions to this and enums not in lottie

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

Label Colors

Value Name Default Color
0 None (shows as grey)
1 Red #b4393b
2 Yellow #e2d759
3 Aqua #abcbc8
4 Pink #e5bcca
5 Lavender #a9aac9
6 Peach #e5c19f
7 Sea Foam #b4c7b4
8 Blue #687fdd
9 Green #4ea350
10 Purple #8d3299
11 Orange #e79228
12 Brown #7e442c
13 Fuchsia #f371d5
14 Cyan #43a2a4
15 Sandstone #a7967a
16 Dark Green #203f1f

Text Render Oder

  1. Per character palette
  2. Fills over strokes
  3. Strokes over fills

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.

cmta

Comment, NUL-terminated string. The size seems to be variable but rounded to 4 bytes.

fdta

Folder data.

cdta

Composition data.

Field Name Size Type Description
X Resolution 2 uint16
Y Resolution 2 uint16
1
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
84
Attributes 1 Flags
Width 2 uint16 Same as w in Lottie
Height 2 uint16 Same as h in Lottie
Pixel Ratio Width 4 uint32
Pixel Ratio Height 4 uint32
12
Framerate 2 uint16 Same as fr in Lottie
16
Shutter Angle 2 uint16
Shutter Phase 4 sint16
16
Samples Limit 4 sint16
Samples per frame 4 sint16

Note that End Time might have a value of FFFF, if that's the case assume it to be the same as Comp Duration.

The X/Y resolution represent a divisor of the size in that direction used for rendering. For example a X Resolution of 5, with a width of 500 will yield an output of 100px.

The pixel ratio is represented as a fraction of width/height, if both values are 1 you get square pixels.

Attributes:

  • Shy: (0, 0): Hides Shy layers from the timeline
  • Motion Blur: (0, 3): Allows layers to enable motion blur
  • Frame Blending: (0, 4): Allows layers to enable frame blending
  • Preserve Framerate: (0, 5): Something about nested render queues
  • Preserve Resolution: (0, 7): Something about nested render queues

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
4
Stretch Numerator 2 uint16
1
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 Label Colors
2
Layer Name 32 string0 It's repeated in the Utf8 chunk right after
11
Matte Mode 1 uint8
2
Stretch Denominator 2 uint16
19
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 (only for AE >= 23)

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

Matte Modes:

  1. No Matte
  2. Alpha
  3. Inverted Alpha
  4. Luma
  5. Inverted Luma

Time streching is defined as a fraction of Stretch Numerator / Stretch Denominator

idta

Item data.

Field Name Size Type Description
Type 2 uint16
14
ID 4 uint32 ID used to reference this item
38
Label Color 1 uint8 Label Colors

The Type field above can have the following values:

  • 1: Folder
  • 4: Composition
  • 7: 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 a cdat.

Types:

  • No Value: (1, 0). Used for properties like shapes, gradients, etc, where the values are not in the keyframe.
  • Integer: (3, 2).
  • Vector?: (3, 3).
  • Color: (3, 0). Set for color properties (they have a different keyframe format).

For Integer type, you might have indexed values: For layers, the value will be in tdpi / tdps, for masks it will be in tdli.

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
Ease Mode 1 uint8
Label Color 1 uint8 Label Colors
Attributes 1 Flags

Ease Mode: 1. Linear 2. Ease 3. Hold

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.

fiac

Folder item active, uint8 if it's 1 the previous List Item is the active item.

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.

Field Name Type Description
ascendcount_base number
ascendcount_target number
fullpath string The absolute path to the file
platform number Operating system (see below)
server_name string Hostname (?)
server_volume_name string
target_is_folder boolean Whether the file is a folder

platform values: 1 is Windows, other values are for Unix and MacOS, but the values are to be discovered

Field Name Size Type Description
AE Version? 6
12
File Revision? 2 uint16 Increases by 2 every time you save

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

It's possible the 3rd to the 5th bytes encode some kind of internal build number that gets mapped to AE versions somehow...

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
8

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 18 3 Effect Value Point

After the data above, there is more data that depends on the type

Layer

Doesn't seem to have much data

Scalar / Angle

Field Name Size Type Description
Last value 4 sint32
4
64
4
Min Value 2 sint16
2
Max Value 2 sint16

To get the last value, you need to divide the raw value by 0x10000.

Boolean

Field Name Size Type Description
Last used value 4 uint32
Default 1 uint8
3
64
4 float32
4
4 float32

Color

Field Name Size Type Description
Last used value 4 uint8[4] ARGB
Default 4 uint8[4] ARGB
64
Max Value 4 uint8[4] ARGB

2D

Field Name Size Type Description
Last value X 4 sint32
Last value Y 4 sint32

Last value x/y are multiplied by 0x80, so divide them to get the right value.

Enum

Field Name Size Type Description
Last used value 4 uint32
Option count 2 uint16
Default 2 uint16

Slider

Field Name Size Type Description
Last used value 8 float64
44
4 float32
4
Max Value 4 float32

3D Point

Field Name Size Type Description
Last value X 8 float64
Last value Y 8 float64
Last value Z 8 float64

You need to multiply the "Last value" components by 512 to get the actual values.

pdnm

Effect parameter definition name / strings.

This will contain strings used by the widget in the effect controls of the preceding pard.

For example if the type in the pard is 4 (Boolean) the name of the parameter might be empty and it will be in pdnm as that's how AE displays it.

For Enum (type 7), you get the drop down strings separated by |.

tdpi

Layer index for index properties (uint32).

tdps

Layer source for index properties (sint32).

  • 0: Layer
  • -1: Effects & Masks
  • -2: Masks

tdli

Mask index for index properties (uint32).

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 Label Colors

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.

  • 0x00'00'00'01 - object is visible
  • 0x00'00'00'02 - split position
  • 0x00'00'20'00 - locked x/y ratio

mkif

Mask properties.

Name Size Type
Inverted 1 uint8
Locked 1 uint8
4
Mode 2 uint16

Mask Modes:

  • 0: None
  • 1: Add
  • 2: Subtract
  • 3: Intersect
  • 4: Darken
  • 5: Lighten
  • 6: Difference

CCId

Composition ID for essential graphics properties (uint32)

CLId

Layer ID for essential graphics properties (uint32)

Smin

Essential graphics slider minimum value.

Representation depends on the value of the previous CTyp.

Smax

Essential graphics slider maximum value.

Representation depends on the value of the previous CTyp.

CVal

Essential graphics property current value.

Representation depends on the value of the previous CTyp.

CDef

Essential graphics property default value.

Representation depends on the value of the previous CTyp.

CTyp

uint32 with the essential graphics item type

Name Type Value Format
Scalar 2 float64
Color 4 float32[4] RGBA
Position 5 float64[2]
Comment 8
Vector 9 float64[4]
Group 10
Enum 13 uint32

CprC

Essential graphics flags (4bytes)

  • Is property (3, 0)

StVS

Essential graphics group item count

Name Size Type
Count 1 uint8
3

CDim

uint32 number of dimensions for an essential vector property.

fips

Contained in LIST Fold contains preview settings. The chunk is repeated multiple times but only the first one seems to be relevant.

Name Size Type
15
Flags 1 uint8

Flags

  • Show alpha grid (0, 7)

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 layer
  • ADBE Transform Group: Layer transform
  • ADBE Layer Styles: Layer styles

LIST tdgp

Defines an object / property group.

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 LISTs).

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 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 or 1?
  • 1.1: Array of text documents (one for each keyframe) in this format:
    • 0.0: Text
    • 0.5.0: Array of paragraph styles
      • 0.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 fonts
        • 1: Font size
        • 2: Faux Bold
        • 3: Faux Italic
        • 12: 0: Normal, 1: Small caps, 2: All caps
        • 13: 0: Normal, 1: Superscript, 2: Subscript
        • 53.0.1: Fill color in ARGB [0, 1]
        • 54.0.1: Stroke color in ARGB [0, 1]
        • 57: Stroke enabled
        • 58: Stroke over fill
        • 63: 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:

  • sspc with some common properties
  • Utf8 with the name (except for solids)
  • opti with asset data

LIST CIF0

See LIST CIF3.

LIST CIF2

See LIST CIF3.

LIST CIF3

Essential Graphics Definition.

LIST CCtl

Essential graphics item.

LIST CpS2

Essential graphics header.

LIST StVc

Essential graphics group items

LIST CPrp

Essential graphics property definition

LIST OvG2

Essential graphics override property identifiers

LIST CPrp

Essential graphics override property identifier

LIST LRdr

Render queue data. this is a top-level chunk. Items are stored in LIST LItm.

LIST LItm

Render Queue items, contains a sequence of LIST list and LIST LOm, the latter having information on the render item (one per job).

LIST LOm

Render list item, contains the following chunks:

  • Roou Output options?
  • Ropt Render options?
  • LIST Als2 Selected output file
  • Utf8 Name of the template applied to the item
  • Utf8 File name template

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