Parsing Boolean Flags (1-bit attributes)¶
This guide walks you through the process of adding support for a new boolean attribute from an After Effects project file. Boolean flags are typically stored as individual bits within a byte, so we need to identify which bit corresponds to which attribute.
Overview¶
The workflow for adding a new boolean flag:
- Compare files - Create two .aep files that differ only in the target attribute
- Find the byte - Locate the byte that changes between the two files
- Identify the bit - Determine which bit within that byte represents the flag
- Update Kaitai schema - Add the bit field to
aep.ksy - Regenerate parser - Compile the updated schema to Python
- Update model - Add the attribute to the appropriate dataclass
- Update parser logic - Wire the parsed data to the model
- Add tests - Validate your changes with test cases
Detailed Steps¶
1. Create Test Files¶
Create two minimal .aep files that differ only in the boolean attribute you want to parse:
- Open After Effects
- Create a minimal project (e.g., a single composition with one layer)
- Save as
test_false.aep - Change only the boolean attribute you want to parse (e.g., toggle "Motion Blur" on a layer)
- Save as
test_true.aep
Tip: Also save as .aepx format - it's XML-based and easier to read when debugging.
2. Compare Files and Find the Byte¶
Use the aep-compare CLI tool to find differences:
# Compare the two files
aep-compare test_false.aep test_true.aep
# Filter by specific chunk type if you know it
aep-compare test_false.aep test_true.aep --filter ldta
Look for bytes that change. For example, you might see:
- cdta chunk, byte at position 42: 10 → 14
3. Identify the Bit Position¶
Convert the byte values to binary to identify which bit changed:
Bit numbering convention (right to left):
In this example, bit 2 represents our boolean flag.
Tip: Use the Kaitai Struct Web IDE to visualize the binary structure and confirm the bit position.
4. Update the Kaitai Schema¶
Open src/aep_parser/kaitai/aep.ksy and find the chunk definition (e.g., cdta). Add bit fields for the byte:
# Before (reading whole byte)
- id: flags
type: u1 # 8-bit unsigned integer
# After (reading individual bits)
- id: preserve_nested_resolution
type: b1 # bit 7
- type: b1 # skip bit 6
- id: preserve_nested_frame_rate
type: b1 # bit 5
- id: frame_blending
type: b1 # bit 4
- id: some_existing_flag
type: b1 # bit 3
- id: motion_blur # <-- Add this (matches bit 2 from example above)
type: b1 # bit 2
- type: b2 # skip bits 1-0
Important notes:
- Bits are read from most significant to least significant (left to right: 7→0)
- Use b1 for single bits, b2 for two bits, etc.
- Skip unknown bits with type: b1 (no id)
- All bits in a byte must be accounted for (they must sum to 8)
5. Regenerate the Kaitai Parser¶
Compile the updated schema to Python:
kaitai-struct-compiler --target python \
--outdir src/aep_parser/kaitai \
src/aep_parser/kaitai/aep.ksy
The compiler generates src/aep_parser/kaitai/aep.py automatically. Do not edit this file manually.
6. Update the Model Dataclass¶
Add the attribute to the appropriate model class. Check the After Effects Scripting Guide to find:
- The correct attribute name (e.g., motionBlur)
- Which class it belongs to (e.g., AVLayer)
- The description for your docstring
Example in src/aep_parser/models/layers/av_layer.py:
@dataclass
class AVLayer(Layer):
"""AV Layer with visual and audio properties.
Corresponds to After Effects' AVLayer object.
"""
# ... other fields ...
motion_blur: bool
"""Whether motion blur is enabled for this layer.
Corresponds to AVLayer.motionBlur in ExtendScript.
"""
Naming convention: Use snake_case for Python attributes, even if the AE scripting API uses camelCase.
7. Update the Parser Logic¶
Wire the parsed bit to the model in the corresponding parser (e.g., src/aep_parser/parsers/layer.py):
def parse_av_layer(chunk: Aep.Chunk, context: Context) -> AVLayer:
"""Parse an AV layer from layer chunks."""
# ... existing parsing code ...
# Get the flags chunk
flags_chunk = find_by_type(chunks=child_chunks, chunk_type="cdta")
return AVLayer(
# ... other arguments ...
motion_blur=flags_chunk.data.motion_blur, # <-- Add this
)
8. Add Tests¶
Create a test case to validate your new attribute:
- Create a minimal .aep file with the attribute enabled (
samples/models/layers/motion_blur_enabled.aep) - Optional: Use the JSX scripts to generate test samples and validation data:
- Run
scripts/jsx/export_project_json.jsxin After Effects to export the project as JSON for validation - Update
scripts/jsx/generate_model_samples.jsxif you're adding a new attribute that should be systematically tested - Add a test in
tests/test_models_layer.py:
def test_layer_motion_blur():
"""Test parsing motion blur flag from layer."""
project = parse_project("samples/models/layers/motion_blur_enabled.aep")
comp = project.items[0]
layer = comp.layers[0]
assert layer.motion_blur is True
Run the test:
Tips and Best Practices¶
- Start simple: Test with minimal .aep files to reduce complexity
- Use .aepx format: XML is easier to read than binary when debugging
- Compare one change at a time: Only toggle one attribute between test files
- Check the scripting guide: Always reference the After Effects Scripting Guide for correct naming and types
- Use the Web IDE: The Kaitai Struct Web IDE is invaluable for visualizing binary structures
- Test thoroughly: Add test cases for both
trueandfalsevalues
Common Pitfalls¶
- Wrong bit order: Remember that bits are numbered right-to-left (7→0), but in the Kaitai schema you define them top-to-bottom (bit 7 first, then bit 6, etc.)
- Missing bits: Every bit in a byte must be accounted for - use
type: b1to skip unknown bits - Wrong chunk: Make sure you're looking at the correct parent chunk (use
aep-compareto verify) - Forgetting to regenerate: Always regenerate
aep.pyafter editingaep.ksy
See Also¶
- Contributing Guide - General guide for adding features and debugging
- After Effects Scripting Guide - Official AE scripting reference
- Kaitai Struct Documentation - Kaitai syntax and best practices