Nodes/LF Nodes/Select settled image frame
ComfyUI Node

Select settled image frame

Grab the last frame before the camera stops

By lucafoscili·Created 2 years ago·Updated 22 days ago· 36
Select settled image frame
  • image
  • ui_widget
  • image
  • image_list
  • selected_index
  • receipt
◄tail_fraction0.25►
◄analysis_max_edge96►

Video models end a camera move by settling - the last second or so drifts into the final pose and stops. Every frame in that tail looks like the destination, and most of them are slightly worse: mid-decay, motion-blurred, half-way through a micro-pan. Picking the right one by scrubbing is tedious and inconsistent.

LF_SelectSettledImageFrame picks it by measurement. It looks only at the final fraction of the sequence, scores each candidate by how little the picture is changing around it, and hands you back that exact source frame.

Common use: take a generated camera move, yank the settled frame out, and feed it onward as the keyframe for a turnaround, a reframe, or an identity reference. The pack's own MiniMax H3 workflows use it on the settled tail for exactly this - generate a requested view, then extract a clean still.

How it works

It resizes copies of the tail down to analysis_max_edge (96px by default) and computes the mean absolute difference between adjacent frames. Each candidate frame's score is the mean of its available adjacent differences - so a frame sitting in a quiet patch scores low, and a frame in the middle of a pan scores high. Lowest score wins.

Ties resolve to the latest frame, which is the right tiebreak: among equally still frames, the last one is the most settled.

Two things worth knowing about the implementation. First, RGBA frames are scored after premultiplying by alpha, so transparent regions don't count as motion - sensible when you've cut a subject out. Second, the frame it returns is the original frame, full resolution, pixels untouched. The 96px analysis copies never leave the node. And the whole thing runs on CPU in chunks, so it doesn't fight your sampler for VRAM.

The tooltip says the important part out loud: it measures image change only. It does not recognise the correct angle, pose, anatomy or identity. It's a stillness detector, not a critic.

The inputs and outputs that matter

  • image - an ordered, coherent sequence: every frame must share height, width, channels, dtype and device. Mixed sizes raise an error rather than quietly doing something odd. NaN or infinite pixels in the tail are rejected too.
  • tail_fraction - default 0.25, range 0.01–1. The final fraction of the sequence eligible. 0.25 searches the last quarter; 1.0 searches everything.
  • analysis_max_edge - default 96, range 8–1024, step 8. Bigger notices smaller pixel changes and costs more time. Output resolution is unaffected.

Outputs: image (the chosen frame as a one-image batch), image_list (a one-item list), selected_index (the zero-based source index - handy for logging which frame you used, and for reproducing a run), and receipt - every candidate's score, the analysis window, the metric, the tiebreak policy, and semanticValidation: "none".

How to install it

ComfyUI Manager → search LF Nodes → install → restart, or:

cd ComfyUI/custom_nodes
git clone https://github.com/lucafoscili/lf-nodes
python -m pip install -r lf-nodes/requirements.txt

Pip with ComfyUI's interpreter. This node needs torch and nothing exotic, but it ships inside a 154-node suite with a heavy requirements list. And the usual pack caveat: lucafoscili/comfyui-lf is the archived repo - lf-nodes is the current one.

Common issues & troubleshooting

"image must be one coherent sequence." Frames of differing size or dtype got concatenated. Usually a batch from one resolution is being mixed with a batch from another - decode your video once, don't stitch two sources.

It picked a blurry frame. Stillness is not sharpness. A motion-blurred smear that barely changes between frames scores better than a crisp frame mid-pan. Raise analysis_max_edge so small differences register, and consider a narrower tail_fraction so the search stays in the part you know is settled.

It picked frame 0. You set tail_fraction to 1, or your "tail" is the whole clip and the opening frame is the calmest thing in it. Lower it.

The chosen frame is the very last one. Often correct - the end of a move is the most settled place, and ties go to the latest frame. If you specifically want a mid-settle frame, look at the receipt's candidate scores and feed a trimmed sequence in instead.

It ignored the identity / picked a frame with a wrong-looking face. Expected, and this is the honest limitation: it has no idea what's in the picture. Do the semantic check yourself - that's what the receipt scores are for, so you can compare a handful of candidates by eye rather than all sixty.

Category✨ LF Nodes/Image

Inputs (4)

NameTypeDefaultDescription
imageIMAGEOrdered coherent RGB or RGBA frames. The selector measures image change only; it does not recognize the correct angle, pose, anatomy, or identity.
tail_fractionFLOAT0.250.01–1Final fraction of the sequence eligible for selection. For example, 0.25 searches only the last quarter.
analysis_max_edgeINT968–1024Longest edge used only for motion analysis. Higher values notice smaller pixel changes but require more work; the selected output keeps its original pixels.
ui_widgetoptLF_MASONRY[object Object]—

Outputs (4)

NameTypeDescription
imageIMAGEExact selected source frame as a one-image batch; RGB/RGBA pixels are unchanged.
image_listIMAGEAuthoritative one-item list containing the exact selected source frame.
selected_indexINTZero-based selected source-frame index.
receiptJSONDeterministic motion scores and selection policy; no semantic validation is performed.