Keyframe Part
Tell exactly one frame how hard to redraw
- image
- part
- part
Keyframe Part is the atomic building block of this pack. Where Keyframe Interpolation Part gives you a whole denoise ramp at once, this node is one point on the timeline: "at batch index N, use this image, and redraw it this hard." Chain a few together and you've got a per-frame denoise map for your video batch - no chained KSamplers, no repeated full-batch passes.
What it's actually for
You usually don't want a ramp; you want one specific frame to behave differently. A common one: the very first frame of your clip should stay glued to your real footage (low denoise) so the video starts recognizable, while everything else follows your normal sampling. Or you want a single mid-clip frame to get a style punch. That's this node - set the batch_index, set how hard to redraw, move on.
How it works
A keyframe here is just three values bundled together: a batch_index, an image, and a denoise. The node drops that into a LATENT_KEYFRAME_PART group - creating the group automatically if nothing is connected, or merging into an existing part if you chain one in. When two keyframes land on the same batch index, the later one overwrites the earlier; the group keeps one entry per index. You then feed the finished group to Keyframe Apply, which is what actually does something with it (VAE-encoding the images into your latent batch and injecting the denoise schedule into the sampler).
The inputs that matter
image(IMAGE) - the source frame. Keep this to a single frame; the reported batch-slice bug in this pack bites when you feed it a multi-frame batch.batch_index(INT, default 0) - which slot in your latent batch this keyframe targets. It has to exist in your batch, so keep it below your batch size.denoise(FLOAT, default 0.1) - the redraw strength. 0.1 means "keep almost everything from the source"; 1.0 means "ignore it, redraw fully" (prompt and ControlNet still guide). The default is the gentle end on purpose.part(LATENT_KEYFRAME_PART, optional) - chain an existing group to append to it.
That's the whole node. Three settings, one output.
A typical chain
Keyframe Part (index 0, denoise 0.05) ─┐
Keyframe Part (index 8, denoise 0.5) ─┼─► KeyframeApply ──► KSampler (k_euler)
Keyframe Part (index 16, denoise 1.0) ─┘
Each later node's part input takes the previous node's part output, building one group that lands on Keyframe Apply. Remember the pack-wide rule: your KSampler has to be on k_euler, k_euler_a, or k_lcm, or the per-frame denoise never takes effect.
Installing it
ComfyUI Manager (search "ComfyUI-Keyframe", listed as SComfyUI-Keyframe), or manually:
cd ComfyUI/custom_nodes
git clone https://github.com/Scholar01/ComfyUI-Keyframe
Restart and it's live. There's no requirements.txt and nothing to download - numpy and tqdm are already in ComfyUI. It's a tiny, unmaintained pack (last touched January 2025) from the AnimateDiff era by Scholar01, the author of the sd-webui-mov2mov A1111 extension, so treat its import-time patching as fragile on a modern ComfyUI. But if you need per-frame denoise control and this works on your install, it's one of the few places the idea exists in plain node form.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| batch_index | INT | 00–9999 | — |
| denoise | FLOAT | 0.100.001–1 | — |
| partopt | LATENT_KEYFRAME_PART | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| part | LATENT_KEYFRAME_PART | — |