Claude/loving lamport 5 st6 m#43
Conversation
Landscape sources are scaled to height 1920 then centre-cropped to 1080 wide (crop=1080:1920). Portrait sources are left as-is. Draft mode uses 720:1280. Clips land in clips_graded_vertical/ so horizontal and vertical renders coexist in the same edit dir without collision. Also documents the flag in SKILL.md so Claude picks it up on cold start. https://claude.ai/code/session_01Fs3KvN642x87jQKujA9bLu
There was a problem hiding this comment.
2 issues found across 3 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="helpers/render.py">
<violation number="1" location="helpers/render.py:180">
P1: Vertical mode does not enforce fixed 9:16 dimensions for portrait inputs, which can cause downstream concat-copy failures due to mixed segment resolutions.</violation>
</file>
<file name="SKILL.md">
<violation number="1" location="SKILL.md:78">
P2: Documentation inconsistency: `clips_graded_vertical/` output directory introduced in `render.py` description but missing from canonical 'Directory layout' section.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Fix all with cubic | Re-trigger cubic
| if draft: | ||
| scale = "scale=-2:1280" if portrait else "scale=1280:-2" | ||
|
|
||
| if vertical and not portrait: |
There was a problem hiding this comment.
P1: Vertical mode does not enforce fixed 9:16 dimensions for portrait inputs, which can cause downstream concat-copy failures due to mixed segment resolutions.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At helpers/render.py, line 180:
<comment>Vertical mode does not enforce fixed 9:16 dimensions for portrait inputs, which can cause downstream concat-copy failures due to mixed segment resolutions.</comment>
<file context>
@@ -171,15 +176,30 @@ def extract_segment(
- if draft:
- scale = "scale=-2:1280" if portrait else "scale=1280:-2"
+
+ if vertical and not portrait:
+ # Landscape → 9:16: scale to target height (making it wider than needed),
+ # then centre-crop to the target width. Default crop x centres automatically.
</file context>
| - **`pack_transcripts.py --edit-dir <dir>`** — `transcripts/*.json` → `takes_packed.md` (phrase-level, break on silence ≥ 0.5s). | ||
| - **`timeline_view.py <video> <start> <end>`** — filmstrip + waveform PNG. On-demand visual drill-down. **Not a scan tool** — use it at decision points, not constantly. | ||
| - **`render.py <edl.json> -o <out>`** — per-segment extract → concat → overlays (PTS-shifted) → subtitles LAST. `--preview` for 720p fast. `--build-subtitles` to generate master.srt inline. | ||
| - **`render.py <edl.json> -o <out>`** — per-segment extract → concat → overlays (PTS-shifted) → subtitles LAST. `--preview` for 720p fast. `--build-subtitles` to generate master.srt inline. `--vertical` for 9:16 1080×1920 output (landscape sources centre-cropped; clips land in `clips_graded_vertical/` so both cuts coexist). |
There was a problem hiding this comment.
P2: Documentation inconsistency: clips_graded_vertical/ output directory introduced in render.py description but missing from canonical 'Directory layout' section.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At SKILL.md, line 78:
<comment>Documentation inconsistency: `clips_graded_vertical/` output directory introduced in `render.py` description but missing from canonical 'Directory layout' section.</comment>
<file context>
@@ -75,7 +75,7 @@ Helpers (`helpers/transcribe.py`, `helpers/render.py`, etc.) live alongside this
- **`pack_transcripts.py --edit-dir <dir>`** — `transcripts/*.json` → `takes_packed.md` (phrase-level, break on silence ≥ 0.5s).
- **`timeline_view.py <video> <start> <end>`** — filmstrip + waveform PNG. On-demand visual drill-down. **Not a scan tool** — use it at decision points, not constantly.
-- **`render.py <edl.json> -o <out>`** — per-segment extract → concat → overlays (PTS-shifted) → subtitles LAST. `--preview` for 720p fast. `--build-subtitles` to generate master.srt inline.
+- **`render.py <edl.json> -o <out>`** — per-segment extract → concat → overlays (PTS-shifted) → subtitles LAST. `--preview` for 720p fast. `--build-subtitles` to generate master.srt inline. `--vertical` for 9:16 1080×1920 output (landscape sources centre-cropped; clips land in `clips_graded_vertical/` so both cuts coexist).
- **`grade.py <in> -o <out>`** — ffmpeg filter chain grade. Presets + `--filter '<raw>'` for custom.
</file context>
render.py: upgrade --vertical crop from centre-fixed to subject-tracking. Samples N frames per segment, computes horizontal gradient-energy centroid via PIL+numpy, maps to post-scale crop x. Falls back to centre on failure. Also refactors is_portrait_source() to use new get_video_dimensions() helper. export_resolve.py: new standalone helper that builds a resolve_package.zip from any edl.json. Extracts shots with configurable handles (default 2s), writes FCPXML 1.9 (primary) and CMX 3600 EDL (fallback), plus a README. Uses stdlib only (xml.etree.ElementTree, zipfile). No new dependencies. SKILL.md: updated render.py bullet and added export_resolve.py bullet. https://claude.ai/code/session_01Fs3KvN642x87jQKujA9bLu
There was a problem hiding this comment.
2 issues found across 3 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="helpers/export_resolve.py">
<violation number="1" location="helpers/export_resolve.py:267">
P1: Missing validation of temporal inputs can silently produce wrong clips or cause opaque ffmpeg failures</violation>
<violation number="2" location="helpers/export_resolve.py:272">
P1: Unsanitized EDL source name used in output path construction, enabling path traversal/out-of-directory writes.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Fix all with cubic | Re-trigger cubic
| src_name = r["source"] | ||
| src_path = resolve_path(sources[src_name], edit_dir) | ||
| meta = src_meta[str(src_path)] | ||
| seg_start = float(r["start"]) |
There was a problem hiding this comment.
P1: Missing validation of temporal inputs can silently produce wrong clips or cause opaque ffmpeg failures
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At helpers/export_resolve.py, line 267:
<comment>Missing validation of temporal inputs can silently produce wrong clips or cause opaque ffmpeg failures</comment>
<file context>
@@ -0,0 +1,344 @@
+ src_name = r["source"]
+ src_path = resolve_path(sources[src_name], edit_dir)
+ meta = src_meta[str(src_path)]
+ seg_start = float(r["start"])
+ seg_end = float(r["end"])
+ cut_dur = seg_end - seg_start
</file context>
| cut_dur = seg_end - seg_start | ||
| beat = r.get("beat") or r.get("note") or "" | ||
|
|
||
| out_name = f"shot_{i + 1:02d}_{src_name}.mp4" |
There was a problem hiding this comment.
P1: Unsanitized EDL source name used in output path construction, enabling path traversal/out-of-directory writes.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At helpers/export_resolve.py, line 272:
<comment>Unsanitized EDL source name used in output path construction, enabling path traversal/out-of-directory writes.</comment>
<file context>
@@ -0,0 +1,344 @@
+ cut_dur = seg_end - seg_start
+ beat = r.get("beat") or r.get("note") or ""
+
+ out_name = f"shot_{i + 1:02d}_{src_name}.mp4"
+ out_path = shots_dir / out_name
+ print(f" [{i + 1:02d}] {src_name} {seg_start:.2f}-{seg_end:.2f} ({cut_dur:.2f}s) {beat}")
</file context>
…utput - Encoding: prores_ks profile 3 (422 HQ), yuv422p10le, PCM s24le audio, .mov - Handles: frame count instead of seconds (default 25 frames), converted to seconds per-source using detected fps for frame-accurate extraction - Output: resolve_shots/ folder is the primary deliverable; zip is opt-in via --zip flag rather than always-on - README updated to show frame count and fps alongside handle duration https://claude.ai/code/session_01Fs3KvN642x87jQKujA9bLu
Adding Vertical output + face detect (for pan and scan help).
Summary by cubic
Adds subject-tracked 9:16 vertical render mode and a Resolve export that outputs ProRes 422 HQ shots with frame-based handles for easy timeline handoff.
New Features
--vertical: landscape scales to 1920 height with subject-tracked crop to 1080; portrait scales normally; draft uses 720×1280.clips_*_vertical/; base files arebase*_vertical.mp4.export_resolve.py: createsresolve_shots/with ProRes 422 HQ.movshot clips trimmed with--handlesframes (default 25), plustimeline.fcpxml(1.9),timeline.edl, andREADME.txt. Add--zipto also produceresolve_package.zip.Dependencies
uv.lockto pin dependencies.Written for commit c7637a8. Summary will update on new commits. Review in cubic