Skip to content

fix: FCPXML honors embedded source timecode (DJI import, follow-up to #34) - #35

Merged
DozaVisuals merged 2 commits into
mainfrom
fix/fcpxml-source-timecode
May 29, 2026
Merged

DozaVisuals merged 2 commits into
mainfrom
fix/fcpxml-source-timecode

Conversation

@DozaVisuals

Copy link
Copy Markdown
Owner

Summary

Follow-up to #34 / v3.5.6. A user on DJI footage reported the same "Invalid edit with no respective media" error after updating. Their exported FCPXML (29.97, 4K) was structurally clean and frame-aligned — so 3.5.6's grid fix was working — but the asset still declared start="0/1s".

Root cause

Per the FCPXML spec, an <asset>'s start is its source timecode, and every <asset-clip start> must fall within [asset.start, asset.start+duration]. DJI/Sony cameras stamp time-of-day timecode (the user's clip: 2026-04-10 14:09:42). Doza hard-coded start="0/1s" with 0-based clip starts, so when FCP resolved the real media (TC ≈ 14:09:42), every edit landed outside the asset's timecode range → rejected. This also explains why importing into a project that already had the media failed.

Fix

  • exporters/media_probe.py: get_video_start_timecode_frames() reads the timecode tag (format or tmcd stream) via ffprobe; timecode_to_frames() parses HH:MM:SS:FF (+ ; drop-frame) to a whole-frame count.
  • fcpxml_export.py: both generators take start_tc_frames; asset.start = TC and every source-side start (asset-clip + keyword + chapter-marker) = TC + in-point. Timeline offsets stay 0-based. TC=0 media is byte-identical to before — non-timecoded footage is unaffected.
  • Threaded start_tc_frames through the exporter interface and probed it at both app.py export routes. (Premiere/EDL accept the kwarg for parity; source-TC handling there is a follow-up.)

Tests

tests/test_fcpxml_timecode.py — timecode parsing (NDF/DF/invalid), asset.start == embedded TC, every clip within the asset's TC range, story export, and TC=0 back-compat. 182 FCPXML/exporter tests pass.

Version → 3.5.7.

🤖 Generated with Claude Code

DozaVisuals and others added 2 commits May 29, 2026 14:59
The 3.5.6 fix corrected the frame grid but still hard-coded asset
start="0/1s" with 0-based asset-clip starts. Final Cut keys an asset's
source timecode off the media's *real* timecode, so for footage that
carries time-of-day timecode (DJI, Sony, etc.) every exported edit fell
outside the asset's [start, start+duration] range and FCP rejected it
with "Invalid edit with no respective media" — the same symptom 3.5.6
was meant to fix, reproduced on a real DJI 29.97 clip.

Per the FCPXML spec, asset.start must equal the media's embedded source
timecode and each asset-clip.start must fall within the asset's range.

Fix:
- exporters/media_probe.py: get_video_start_timecode_frames() reads the
  `timecode` tag (format or stream / tmcd) via ffprobe; timecode_to_frames()
  parses HH:MM:SS:FF (and ;FF drop-frame) to a whole-frame count on the
  nominal grid.
- fcpxml_export.py: both generators take start_tc_frames; asset.start =
  TC, and every source-side start (asset-clip + keyword + chapter-marker)
  = TC + in-point. Timeline offsets stay 0-based. TC=0 media is unchanged
  (asset start="0/1s"), so non-timecoded footage is byte-identical.
- Threaded start_tc_frames through the exporter interface (base + FCPXML;
  Premiere/EDL accept it for parity, source-TC handling there is a TODO)
  and probed it at both app.py export routes.

Tests: tests/test_fcpxml_timecode.py — timecode parsing (NDF/DF), asset
start == embedded TC, every clip within the asset's TC range, story
export, and TC=0 back-compat.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@DozaVisuals
DozaVisuals merged commit 8dbfbd1 into main May 29, 2026
@DozaVisuals
DozaVisuals deleted the fix/fcpxml-source-timecode branch May 29, 2026 19:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant