-
Notifications
You must be signed in to change notification settings - Fork 3
Home
Welcome to the comprehensive documentation for the Cutlass FCPXML generation framework. This wiki provides detailed guidance for working with Final Cut Pro XML files programmatically.
Before diving into development, you must read these essential documents:
- FCPXML Generation Best Practices - Core rules and patterns
- Images vs Videos Architecture - Media type handling (prevents #1 crash cause)
- Testing and Debugging - Validation and troubleshooting
- Architecture Overview - System design and patterns
- FCPXML Generation Best Practices - Critical rules and patterns
- Images vs Videos Architecture - Media type handling
- Animation and Effects - Keyframes, animations, and effects
- Testing and Debugging - Validation and troubleshooting
- API Reference - Complete function and type reference
NEVER EVER generate XML from hardcoded string templates:
β BAD: xml := "<video ref=\"" + videoRef + "\">" + content + "</video>"
β BAD: fmt.Sprintf("<asset-clip ref=\"%s\" name=\"%s\"/>", ref, name)
β
GOOD: xml.MarshalIndent(&fcp.Video{Ref: videoRef, Name: name}, "", " ")
All FCPXML generation MUST use the fcp. structs in the fcp package.*
NEVER EVER only change problem xml in an xml file, always change the code that generates it too
Media Type | Asset Duration | Format frameDuration | Spine Element | Effects Support |
---|---|---|---|---|
Images |
"0s" (timeless) |
NONE | <video> |
Simple only |
Videos | Actual duration | Required | <asset-clip> |
Full support |
-
AssetClip for images β
addAssetClip:toObject:parentFormatID
crash -
frameDuration on image formats β
performAudioPreflightCheckForObject
crash - Complex effects on images β Various import crashes
- Fictional effect UIDs β "invalid effect ID" crashes
- Non-frame-aligned durations β "not on edit frame boundary" errors
All IDs must be unique within the document:
// β
GOOD: Use ResourceRegistry pattern
registry := fcp.NewResourceRegistry(fcpxml)
tx := fcp.NewTransaction(registry)
defer tx.Rollback()
ids := tx.ReserveIDs(3)
assetID := ids[0] // "r2"
formatID := ids[1] // "r3"
effectID := ids[2] // "r4"
// β BAD: Hardcoded IDs cause collisions
assetID := "r1" // Will conflict with other generators
All durations MUST use fcp.ConvertSecondsToFCPDuration()
:
// β
GOOD: Frame-aligned duration
duration := fcp.ConvertSecondsToFCPDuration(5.5) // "132132/24000s"
// β BAD: Decimal seconds cause drift
duration := "5.5s" // Not frame-aligned
FCP uses 24000/1001 β 23.976 fps timebase for frame alignment.
ONLY use verified effect UIDs:
-
Gaussian Blur:
FFGaussianBlur
-
Color Correction:
FFColorCorrection
-
Text Title:
.../Titles.localized/Basic Text.localized/Text.localized/Text.moti
-
Shape Mask:
FFSuperEllipseMask
// Spatial transformations - always safe
video.AdjustTransform = &fcp.AdjustTransform{
Position: "100 50",
Scale: "1.5 1.5",
}
// Cropping - always safe
assetClip.AdjustCrop = &fcp.AdjustCrop{
Mode: "trim",
TrimRect: &fcp.TrimRect{Left: "0.1", Right: "0.9"},
}
ALWAYS follow this pattern:
func GenerateMyFeature(inputFile, outputFile string) error {
// 1. Use existing infrastructure
fcpxml, err := fcp.GenerateEmpty("")
if err != nil {
return fmt.Errorf("failed to create base FCPXML: %v", err)
}
// 2. Use proper resource management
registry := fcp.NewResourceRegistry(fcpxml)
tx := fcp.NewTransaction(registry)
defer tx.Rollback()
// 3. Add content using existing functions
if err := fcp.AddImage(fcpxml, imagePath, duration); err != nil {
return err
}
// 4. Apply animations (simple transforms only for images)
imageVideo := &fcpxml.Library.Events[0].Projects[0].Sequences[0].Spine.Videos[0]
imageVideo.AdjustTransform = createAnimation(duration, startTime)
// 5. Commit and write
if err := tx.Commit(); err != nil {
return err
}
return fcp.WriteToFile(fcpxml, outputFile)
}
fcp/
βββ types.go # All FCPXML struct definitions
βββ generator.go # Core generation functions
βββ registry.go # Resource ID management
βββ transaction.go # Transaction-based operations
βββ ids.go # ID generation utilities
βββ *_test.go # Comprehensive test patterns
- Read FCPXML Generation Best Practices
-
Study the test files in
fcp/*_test.go
for proven patterns -
Validate your code with
fcp.ValidateClaudeCompliance()
- Test imports in actual Final Cut Pro
Key Principle: Follow existing patterns in fcp/ package. If FCPXML generation requires more than 1 iteration to work, you're doing it wrong.