Skip to content

Keep a render's memory flat as the video grows - #12

Merged
davior merged 1 commit into
mainfrom
claude/lucid-archimedes-afkjtn
Oct 22, 2026
Merged

davior merged 1 commit into
mainfrom
claude/lucid-archimedes-afkjtn

Conversation

@davior

@davior davior commented Oct 22, 2026

Copy link
Copy Markdown
Owner

A preview failed with ffmpeg failed (killed by signal 9 (most likely out of memory)). I measured peak memory for each of a render's ffmpeg steps on a 4-core box. Three of them grew with the size of the video.

Step Before After
Blended stitch, 80 preview shots 1.9 GB 147 MB
Overlay pass, 30 layers 561 MB, 140 s 359 MB, 7 s
Preview Ken Burns shot 442 MB 219 MB

Changes

  • Stitch in runs. The blended stitch used to open every shot as an input at once, and each input had a decoder thread per core. It now blends runs of 8 shots, using single-threaded decoders, and remuxes the runs with concat -c copy. A run ends either at a cut or just before a shot blends out, which lands the split in the shot's trailing hold (silence). The picture is still encoded only once. Checked against the single pass: same frame count, frame-for-frame match (min 41.5 dB PSNR), exact total length.
  • Overlay layers exist only for their window. This uses -itsoffset and -t in place of looping each layer for the whole video. The output is bit-identical to before.
  • Previews read Ken Burns stills at 8 MP (still over 4× the 854×480 frame). Full renders keep 24 MP.
  • A failed render's error names the step it was on, e.g. Rendering, shot 12 of 40: ffmpeg failed (…).

Testing

  • pytest -q: 674 passed. New tests cover chunk planning, the trimmed stitch argv, overlay windows, the preview read budget and the error prefix.

Generated by Claude Code

A preview failed with ffmpeg killed by signal 9. Measured on a 4-core box,
three of a render's ffmpeg runs grew with the video:

- The blended stitch opened every shot as an input at once, each with a
  decoder thread per core: 1.9 GB for 80 preview shots. It now stitches
  runs of 8 shots with single-threaded decoders and remuxes the runs (147 MB
  for the same 80). A run ends at a cut, or in a shot's trailing hold just
  before it blends out, so the picture is still encoded once.
- The overlay pass looped every layer for the whole video, decoding each one
  on every frame. Each layer now exists only for its window: the same
  output, 561 -> 359 MB and 140 s -> 7 s for 30 layers.
- A preview Ken Burns shot read stills at the same 24 MP as 4K. Previews
  now read at 8 MP: 442 -> 219 MB a shot. Full renders are unchanged.

A failed render's error now names the step it was on, so the next one says
whether it was a shot, the stitch or the overlays.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WJkfhgbVRktPf2Lg6XXfNs

davior commented Oct 22, 2026

Copy link
Copy Markdown
Owner Author

Backend (pytest) was cancelled before any test ran. The job hit its 10-minute timeout-minutes while the "Ensure ffmpeg is available" step was still downloading ffmpeg from a very slow Ubuntu mirror (several seconds per package). The same job is green on main, and the full suite passes locally on this branch (674 passed).

I don't have permission to re-run jobs (the API returns 403). Clicking Re-run failed jobs on the run should be enough. My next code push to this PR would also re-run it.


Generated by Claude Code

@davior
davior marked this pull request as ready for review October 22, 2026 23:31
@davior
davior merged commit e4e1cd8 into main Oct 22, 2026
5 of 6 checks passed
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.

2 participants