Measure layout drift
Give it the still a shot should open on and the renders (or edited stills) to
check; get back, per render, match (correlation after the best zoom about the
centre plus shift; 1.0 is identical), zoom and shift_px. Use it to answer
"did this take open on its still, and if not, by how much did it move?". For
where a render lands on its pinned last frame and how long it runs, use
python-check-pinned-frames; read the two together.
Run it
Write references/layout-drift.md's script into the project folder as
layout_drift.py, as is, and run it with exec python:
exec python layout_drift.py --still <shot>_first.png --video <take_a>.mp4 <take_b>.mp4
exec python layout_drift.py --still <shot>_last.png --video <take_a>.mp4 --frame -1
exec python layout_drift.py --still <source>_first.jpg --image <edited>_first.png
--frame Nmeasures frame N of each video (default 0;-1is the last frame).--imagecompares stills: an edit against its source, a pinned last frame against the first.--widesearches zoom 0.80–1.25 instead of 0.94–1.06, for a still pair with a real push-in between them (a source's first and last frames).
What you get
JSON per input: match, zoom, shift_px ([dx, dy] in 1080p pixels), and the
frame index for videos. zoom > 1 means the render had to be enlarged to fit the
still, so it is framed wider than the still; < 1 means it is framed tighter.
Reading the numbers
match | What it means |
|---|---|
| ≥ 0.98 | Opened on its still. Good i2v openings score 0.98–1.0; pinned stills hold ~0.999. |
| 0.95–0.98 | Kept the layout, slightly zoomed or shifted: ref2vid with the shot's still as a reference landed at 0.96–0.98. Accept, or counter-crop by zoom and shift_px. |
| < 0.95 | Not opening on its still. A ref2vid opening that framed wider (shoes in frame) scored 0.68 at zoom 1.06, shifted 144 px. Re-render with a framing sentence ("from mid-shin up; never pulls back"). |
| ~0.86 | What a shot's own first and last frames score against each other: the scale for "a different moment of the same shot". |
- A last frame under 0.95 against its pinned still means the move hadn't finished at the cut (a hand still dropping): re-render with a new seed.
- On a take pinned at both ends, the framing held at ≥ 0.984 with ≤ 1.5% zoom across the whole take.
- A
zoomat the edge of the search (0.94 or 1.06) means the real zoom may be beyond it: rerun with--wide.
Tips and traps
- Raw SSIM misleads here. SSIM collapses for a frame with the same layout
2% zoomed: a ref2vid take that kept the layout read 0.5 SSIM and 0.96–0.98
match. Some models redraw frame 0 entirely (SSIM 0.40 on a good opening, 0.50 on a bad one); onlymatchseparates them. - Built for 16:9: both frames are centre-cropped to 16:9 and fitted to 1920×1080 before measuring, so a vertical frame is judged on its middle band.
- It measures layout, not content: a face that changed in place still scores high. Look at the frames too (a still | frame 0 | last frame sheet per take).
- Put
matchandzoomin the candidate's note on the review page.
Check it
Run it once with the still against itself (--image the same file): it must
print match 1.0, zoom 1.0, shift_px [0, 0].


