ComfyUI Node

AP Loop Open (Latent)

A feedback loop that never leaves latent space — history for iterative latent workflows

By adampolczynski·Created 6 months ago·Updated 6 months ago· 1
AP Loop Open (Latent)
  • source_latents
  • source_masks
  • custom_latents
  • additional_data
  • loop_token
  • original_current_latent
  • original_current_mask
  • original_first_latent
  • original_previous_latent
  • original_previous_mask
  • processed_previous_latent_1
  • processed_previous_latent_2
  • processed_previous_latent_3
  • processed_previous_latent_4
  • processed_previous_latent_5
  • processed_previous_mask_1
  • processed_previous_mask_2
  • processed_previous_mask_3
  • processed_previous_mask_4
  • processed_previous_mask_5
  • custom_current_latent
  • additional_data_current
  • iteration_index
history_count3
return_first_when_no_previous_availablefalse
apply_custom_replacementfalse
custom_frame_index_map

The image loop nodes give you a per-frame feedback loop in pixel space. This is the same machinery running in latent space, and the reason that matters is the same one that motivates APApplyRAFTOpticalFlowLatent: if your loop body works on latents, going back to pixels every iteration means a VAE decode and encode per frame. The latent loop keeps the whole recursion in latent space, which is faster, uses less VRAM, and avoids the drift that repeated VAE round-trips introduce.

Same shape as APImageLoopOpen - it takes a batch of source_latents, and on each iteration hands you the current latent, the first latent, the previous source latent, and up to five processed_previous_latent_1..5 entries (plus matching masks) that came back from your loop body. The loop_token output carries the iteration state, exactly like the image version.

The mechanism

Identical hidden-iteration recursion, latent-flavored. APLatentLoopOpen reads the internal iteration index and accumulated processed-latent history, slices the source batch at the current index, and exposes it alongside the processed history. The token it emits carries iteration index, total count, and history_count; its counterpart APLatentLoopClose consumes it. The two nodes are a matched pair - you don't wire iteration counters or history depth manually between them, which is the pack's "clean API" selling point.

The latent dict's metadata (shape, noise masks, anything the sampler needs) is carried through, so the latents you get back are valid inputs to a KSampler. If you're combining this with latent-space flow warping (APApplyRAFTOpticalFlowLatent or the masked variant), the whole loop body - warp, blend, sample - can stay in latent space until the very end.

Inputs to actually set

  • source_latents - the batch to iterate (e.g. the VAE-encoded frames of your sequence, or an empty-latent sequence).
  • history_count - processed-history depth exposed (0–5, default 3). This is the "up to 5 previous latents" the author advertises - the temporal context for your loop body.
  • source_masks (optional) - per-frame masks in lockstep.
  • custom_latents + custom_frame_index_map + apply_custom_replacement - replace specific iterations' latent with one from a custom source, same feature as the image loop.
  • additional_data (optional, *) - a parallel payload iterated at the same index (e.g. an IMAGE payload alongside a LATENT loop).

return_first_when_no_previous_available=true makes missing history slots fall back to the first latent rather than zeros, which keeps early iterations clean.

Outputs

loop_token, original_current_latent, original_current_mask, original_first_latent, original_previous_latent, original_previous_mask, processed_previous_latent_1..5, processed_previous_mask_1..5, custom_current_latent, additional_data_current, and iteration_index.

Installing it

Pack-wide install: ComfyUI Manager (search "AP_OpticalFlow"), or

cd ComfyUI/custom_nodes
git clone https://github.com/adampolczynski/ComfyUI_AP_OpticalFlow
python -m pip install -r custom_nodes/ComfyUI_AP_OpticalFlow/requirements.txt

Restart. Dependency: torchvision>=0.15.

When to use it over the image loop

If your per-frame processing is fundamentally pixel work - compositing against the original, pixel-space inpaint, saving intermediate frames - the image loop is the natural fit and this adds a pointless encode. If your per-frame work is warp-in-latent + sample, this node removes the two VAE hops per iteration that the image loop would force you to pay. The README frames it as the way to "avoid repeated VAE encode/decode in iterative latent workflows." It pairs cleanly with the latent apply nodes and APTemporalBlendLatents - the whole temporal-consistency toolbox exists in both spaces, and this is the loop for the latent side.

CategoryAP_OpticalFlow

Inputs (8)

NameTypeDefaultDescription
source_latentsLATENT
history_countINT30–5
return_first_when_no_previous_availableBOOLEANfalse
apply_custom_replacementBOOLEANfalse
custom_frame_index_mapSTRING
source_masksoptMASK
custom_latentsoptLATENT
additional_dataopt*

Outputs (19)

NameTypeDescription
loop_tokenFLOW_CONTROL
original_current_latentLATENT
original_current_maskMASK
original_first_latentLATENT
original_previous_latentLATENT
original_previous_maskMASK
processed_previous_latent_1LATENT
processed_previous_latent_2LATENT
processed_previous_latent_3LATENT
processed_previous_latent_4LATENT
processed_previous_latent_5LATENT
processed_previous_mask_1MASK
processed_previous_mask_2MASK
processed_previous_mask_3MASK
processed_previous_mask_4MASK
processed_previous_mask_5MASK
custom_current_latentLATENT
additional_data_current*
iteration_indexINT