--- name: finalcut description: Conform an approved edit into Final Cut Pro — emit a clean, correct FCPXML that opens the cut as an editable 4K timeline so TJ can do final touches (stabilization, end cards, graphics, color, an extra L-cut). Use when TJ says "finalcut", "/finalcut", "make the XML", "make the FCPXML", "get this into Final Cut", "conform this", or after an /edit cut is approved and he wants to finish it in FCP. Handles BOTH landscape (full/flagship) AND vertical (reel) cuts. Pure emit — it does NOT make creative cut decisions (that's /edit) or write copy/thumbnails (that's /distribute), and it stops at the XML (no finishing/export hand-holding). --- You are conforming an approved edit into Final Cut Pro. The job: emit a **clean, correct FCPXML** that opens the cut as an editable timeline, relinking the original 4K, with the rendered mix riding as reference audio. That's it — TJ finishes in FCP himself. This is the **middle of the trio**: `/edit` (make the cut) → **`/finalcut` (conform to FCP)** → `/distribute` (package + post). Pipeline layout (restructured 2026-06-22, was `vision-experiment/`): the macro `Entrepreneurship Projects/YouTube TJSMind/` holds `pipeline/` (engine, incl. the emitters `emit_film_fcpxml.py` [single-source landscape], `emit_cinematic_fcpxml.py` [multi-source cinematic — segments], and `wrap_fcpxml.py` [wrap a finished render as one clip — vertical reels / overlay-only]) and `projects//` as siblings. Inputs per cut now live IN the project: the EDL in `projects//edl/_edl.json` + the rendered mp4 in `projects//render/` (from `/edit`). [Path-only update; deeper `/finalcut` rework deferred per TJ — one thing at a time.] ## What it emits (and the hard-won mechanics — don't deviate) - **Video on the spine, frame-aligned + contiguous.** Offsets are ABSOLUTE accumulated-frame positions in `/30000s` (29.97 DF, frameDuration 1001/30000s). Do NOT chain accumulated durations as you go — rounding drifts. Compute each clip's offset from the running absolute frame total. - **Relink the original 4K by path** (`file:///Volumes//.../footage/Cxxxx.MP4`, percent-encoded, no bookmarks). The drive MUST be mounted or FCP imports offline clips. - **Mute camera scratch** with `srcEnable="video"` on every asset-clip — the rendered mix carries all audio. - **STANDARD (TJ, 2026-06-23): ride SEPARATE audio stems as TWO connected lanes, not one baked mix.** Deliver `music` on `lane="-1"` (`role="music"`) and `voice` on `lane="-2"` (`role="dialogue"`) — so TJ can level/mute/trim/slide the VO independently of music in FCP without a re-render. The assembler writes the stems (`assemble_cinematic.py --audio` → `render/_voice.m4a` + `_music.m4a`; the hype reel's equivalent is music + nat-sound); the emitter detects the stems beside the render and rides both lanes, falling back to a single bounced `final mix` (`_mix.m4a`) ONLY if stems are absent. Apply to EVERY conform (landscape AND reel) — make new assemblers export stems so this always holds. Reproducing the per-segment envelope/ducking natively isn't worth it — the duck is baked into the music stem, aligned to where VO sits. - Format `r1` = 3840×2160 (land) or **1080×1920 (port)**, Rec.709. ## Landscape vs vertical — two strategies, pick by what FINISHING needs Landscape always opens as PER-CLIP segments (never a wrap — TJ finishes per-clip: isolated stabilization + audio splices). The real choice is HOW the segments are sourced, decided by whether the footage is UNIFORM or MIXED: - **Landscape, MIXED-format or has STILLS — DEFAULT: PRE-CUT UNIFORM SEGMENTS.** `python3 pipeline/emit_land_segments_fcpxml.py `. Pre-cuts EVERY shot to its own 3840×2160@29.97 segment (video cover-crop; **stills get Ken Burns motion BAKED in** — same zoompan as `assemble_cinematic.py`), contiguous actual-dur spine, mix on the `final mix` lane. **Because every segment IS the sequence format, FCP never conforms an odd source in-timeline → the entire black-clip class is structurally impossible.** Same proven technique as the vertical reel. Use for any [cinematic-review](cinematic-review) cut (multi-folder, mixed frame rate, stock, stills). Built + proven 2026-06-23 (`7Lakes_Cinematic`, 52 segments incl. 15 Ken Burns stills, passed all 7 audit checks first try). **LESSON (2026-06-23):** the relink approach (below) fought a black/format bug across ~6 imports; pre-cut segments make that class impossible — when a representation keeps producing the same class of failure, switch the representation, don't keep patching (POSTMORTEMS 2026-06-23 ×2). - **Landscape, UNIFORM footage (single folder, all 4K@29.97) — relink originals by path.** `emit_film_fcpxml.py ` (e.g. `Huacachina_flagship`). Cheaper (no segment render), keeps camera originals, but ONLY safe when every source is already the sequence format. Relinks by path → **drive MUST be mounted + sources present** (the 🇵🇪 emoji folder name percent-encodes fine). (`emit_cinematic_fcpxml.py` is the older mixed-format relink emitter with per-source `` — superseded by pre-cut segments for mixed/stills cuts; use only if camera-original relink is explicitly required AND all sources are 16:9 standard-rate.) - **⚠️ NEVER wrap a landscape cut as one clip** (`wrap_fcpxml.py` is vertical-reel / overlay-only) — it opens as one massive clip and blocks isolated stabilization/splices (2026-06-23). - **Vertical (reel) — DEFAULT: PRE-CUT 9:16 SEGMENTS** via `python3 pipeline/emit_vert_segments_fcpxml.py `. Pre-crops each shot to its own 1080×1920 clip (exact render crop incl. per-shot `px`), per-clip editable (color/stabilization), and **rides separate `music` + `nat sound` lanes** (needs `assemble_hype_port.py --audio` stems beside the render). This is the default because separate audio lanes (the TJ standard) require segments, not a wrap. `7Lakes_Hype_Reel` rebuilt this way 2026-06-23. - **Vertical — wrap the finished render** via `python3 pipeline/wrap_fcpxml.py [name]` (single asset-clip, baked-in audio, pixel-exact, no drive mount). Use ONLY when the finishing is a simple OVERLAY (end card/title/graphic) AND separate audio lanes aren't needed — it CANNOT split music/voice. How `Huacachina_reel.fcpxml` was made (2026-06-21). - **Vertical — ONLY if per-clip 4K editing is genuinely needed:** the 4K-relinked conform requires baking each clip's 9:16 crop (`crop=1215:2160:x:0 → 1080×1920`, `x=(3840-1215)/2*(1+px)`; the 1215×2160 slice is exactly 9:16 so `` + `spatialConform="fill"`, honoring per-clip `px`). **CAUTION — verification gap:** FCP transform/crop UNITS can't be confirmed without opening Final Cut (no headless render of an FCPXML), so a 4K vertical conform CANNOT be self-verified. Don't ship it blind (a mis-framed FCPXML is worse than none, per below). Build it only WITH TJ watching FCP: have him import and eyeball clip 1's framing against `reel_*_port.mp4`, then adjust the transform values until it matches ([[feedback_verify_visuals_not_metadata]] — look, don't trust the math). Until that loop is done once and the unit recipe is proven, prefer the wrap-the-render default. ## Gotchas baked in - **"Invalid edit with no respective media" on EVERY asset-clip (timeline imports EMPTY) = a SOURCE/ASSET-DECLARATION mismatch, diagnose by DIFFING a working sibling's actual MEDIA, not just the XML.** Two distinct root causes hit Koh Samui (2026-06-25), both invisible in the XML — found only by `ffprobe`-ing the referenced files vs a known-good project's files: - **Sony `.mov` carries a `tmcd` timecode track.** Pre-cut SEGMENTS made from `.mov` come out with TWO streams (video + `tmcd` data) → FCP rejects every segment. `-map 0:v:0 -dn` is NOT enough — the mov/mp4 MUXER auto-writes a tmcd track from the input's timecode metadata. Fix: **`-write_tmcd 0`** on the segment ffmpeg → pure single-video-stream segment. (`.MP4` sources like 7lakes didn't hit this; `.mov` does. Verify segments are single-stream: `ffprobe -show_entries stream=index`.) - **Sony `.mov` originals CANNOT be relinked raw** — the `tmcd` timecode stream makes FCP reject every relinked clip ("no respective media"), and declaring `hasAudio` did NOT fix it (Koh Samui flagship, 2026-06-25; `.MP4` originals with an `rtmd` data stream relinked FINE on Huacachina — `.mov` tmcd is the difference). Fix that WORKED: relink **clean video-only stream-COPIES** of each unique source — `ffmpeg -i src.mov -map 0:v:0 -c:v copy -an -dn -sn -write_tmcd 0 clean.mp4` (FAST, no re-encode), declared video-only (no `hasAudio`, no `srcEnable`), spine `start=sin` as normal. Makes the relink structurally identical to the working pre-cut segments. `koh-samui/emit_finalcut.py` does this in its `land` branch (`*_clean/` dir). - **`srcEnable="video"`**: keep it on relinked ORIGINALS (mute camera scratch); harmless but unnecessary on video-only pre-cut segments. (Not the cause of the 2026-06-25 bug despite first appearances — the tmcd stream was.) - **When you update a stem `.wav`, REGENERATE its `.m4a` — a stale `.m4a` silently rides OLD audio.** FCP plays the `.m4a` (AAC) version; if the emitter only converts `wav→m4a` when the m4a is *missing*, an updated `.wav` won't propagate and the FCPXML imports with the previous cut's audio (Koh Samui hybrid: new "My name is Hamid" intro in the `.wav` + preview mp4, but FCP played the old stutter open from the stale `.m4a` — looked unfixable until transcribing the `.m4a` itself). Fix in `emit_finalcut.py` `as_m4a()`: regenerate if `.m4a` missing OR `getmtime(wav) > getmtime(m4a)`. **Verify the actual `.m4a` (not the `.wav`/mp4) when audio "won't update."** - **Connected audio stems MUST be ``, NOT `