LTX Keyframer
Drop keyframes into any video latent, without the guesswork
- vae
- latent
- multi_input
- latent
LTX Keyframer is the pack's overhaul of the older LTXVImgToVideoInplaceKJ node, and it exists to solve one thing: getting your images into the right frames of a video latent without doing manual math. LTX video is a first-frame/last-frame conditioning model at heart - you tell it where a still must appear and it fills in the motion around it. This node is how you place those stills.
It belongs to the WhatDreamsCost-ComfyUI collection, the same free LTX-focused pack that grew into LTX Director. And here's the honest part before we go any further: the author recommends you use LTX Sequencer instead of this node. His own words - "after further testing it seems superior in at pretty much everything." Keyframer is still in the pack because people were already using it and it does one job slightly differently. Knowing that up front saves you a migration later.
How it works
The mechanism is straightforward and worth understanding because it's the same idea that powers the bigger LTX nodes: you feed it a video latent, a batch of images, and a set of (frame, strength) pairs, and it VAE-encodes each image and writes it into the latent at the specified position. Where it differs from the Sequencer is how it inserts: Keyframer replaces the latent frames at that location with the encoded image, and marks those frames in the noise mask with 1 - strength. Frames at strength 1.0 are frozen solid - the model regenerates nothing there, which is exactly what you want for a hard first/last frame. Lower the strength and the model gets room to reinterpret.
A couple of details in the source are worth knowing:
- Negative frame values work.
insert_frameis in pixel space, and negatives index from the end of the video - so-1reliably means "the very last frame," which is the classic last-frame trick without computing frame counts. - It upscales your images to match the latent's resolution (bilinear) before encoding, so mismatched input sizes don't crash it.
num_imagesdynamically configures how manyinsert_frame_*/strength_*widget pairs you see - up to 50. You don't have to scroll through all of them.
The inputs that matter
vae- the video VAE (LTX's), used to encode your images.latent- the video latent you're inserting into.multi_input- the batched images, typically from the pack's own Multi Image Loader, which feeds every image down one wire and auto-updates the widget count.num_images- how many insert slots to configure.- For each image:
insert_frame_N(pixel-space position, negatives = from the end) andstrength_N(0–1, how frozen that frame is).
Outputs
Just one: latent, with the images baked in and the noise mask updated. That goes straight into the sampler. The conditioning side - telling the model what each keyframe is - is handled by pairing this with a guide/conditioning node, which is exactly why the Sequencer's extra outputs (positive/negative conditioning) make it the better all-round choice.
Install
Standard for the pack:
cd ComfyUI/custom_nodes
git clone https://github.com/WhatDreamsCost/WhatDreamsCost-ComfyUI
Or search WhatDreamsCost in ComfyUI Manager, install, restart. No model downloads; it uses ComfyUI's own VAE and tensor utilities. Keep ComfyUI-LTXVideo current if you're pairing it with LTX 2.3 workflows.
Gotchas
The insertion model (replace + mask) means ordering matters: if two images land on the same frame, the later one wins. And remember it's frame positions in pixel space - if your latent was downscaled, the frame index you type needs to be the pixel-space frame (multiplied by the VAE's temporal scale factor), which is exactly the kind of arithmetic the Sequencer and Director were built to spare you. Use those, honestly.
Inputs (104)
| Name | Type | Default | Description |
|---|---|---|---|
| vae | VAE | Video VAE used to encode the images | |
| latent | LATENT | Video latent to insert images into | |
| multi_input | IMAGE | Batched images from MultiImageLoader | |
| num_images | INT | 10–50 | Select how many index/strength widgets to configure. |
| insert_frame_1opt | INT | 0-9999–9999 | Frame insert_frame for image 1 (in pixel space). |
| strength_1opt | FLOAT | 1.000–1 | Strength for image 1. |
| insert_frame_2opt | INT | 0-9999–9999 | Frame insert_frame for image 2 (in pixel space). |
| strength_2opt | FLOAT | 1.000–1 | Strength for image 2. |
| insert_frame_3opt | INT | 0-9999–9999 | Frame insert_frame for image 3 (in pixel space). |
| strength_3opt | FLOAT | 1.000–1 | Strength for image 3. |
| insert_frame_4opt | INT | 0-9999–9999 | Frame insert_frame for image 4 (in pixel space). |
| strength_4opt | FLOAT | 1.000–1 | Strength for image 4. |
| insert_frame_5opt | INT | 0-9999–9999 | Frame insert_frame for image 5 (in pixel space). |
| strength_5opt | FLOAT | 1.000–1 | Strength for image 5. |
| insert_frame_6opt | INT | 0-9999–9999 | Frame insert_frame for image 6 (in pixel space). |
| strength_6opt | FLOAT | 1.000–1 | Strength for image 6. |
| insert_frame_7opt | INT | 0-9999–9999 | Frame insert_frame for image 7 (in pixel space). |
| strength_7opt | FLOAT | 1.000–1 | Strength for image 7. |
| insert_frame_8opt | INT | 0-9999–9999 | Frame insert_frame for image 8 (in pixel space). |
| strength_8opt | FLOAT | 1.000–1 | Strength for image 8. |
| insert_frame_9opt | INT | 0-9999–9999 | Frame insert_frame for image 9 (in pixel space). |
| strength_9opt | FLOAT | 1.000–1 | Strength for image 9. |
| insert_frame_10opt | INT | 0-9999–9999 | Frame insert_frame for image 10 (in pixel space). |
| strength_10opt | FLOAT | 1.000–1 | Strength for image 10. |
| insert_frame_11opt | INT | 0-9999–9999 | Frame insert_frame for image 11 (in pixel space). |
| strength_11opt | FLOAT | 1.000–1 | Strength for image 11. |
| insert_frame_12opt | INT | 0-9999–9999 | Frame insert_frame for image 12 (in pixel space). |
| strength_12opt | FLOAT | 1.000–1 | Strength for image 12. |
| insert_frame_13opt | INT | 0-9999–9999 | Frame insert_frame for image 13 (in pixel space). |
| strength_13opt | FLOAT | 1.000–1 | Strength for image 13. |
| insert_frame_14opt | INT | 0-9999–9999 | Frame insert_frame for image 14 (in pixel space). |
| strength_14opt | FLOAT | 1.000–1 | Strength for image 14. |
| insert_frame_15opt | INT | 0-9999–9999 | Frame insert_frame for image 15 (in pixel space). |
| strength_15opt | FLOAT | 1.000–1 | Strength for image 15. |
| insert_frame_16opt | INT | 0-9999–9999 | Frame insert_frame for image 16 (in pixel space). |
| strength_16opt | FLOAT | 1.000–1 | Strength for image 16. |
| insert_frame_17opt | INT | 0-9999–9999 | Frame insert_frame for image 17 (in pixel space). |
| strength_17opt | FLOAT | 1.000–1 | Strength for image 17. |
| insert_frame_18opt | INT | 0-9999–9999 | Frame insert_frame for image 18 (in pixel space). |
| strength_18opt | FLOAT | 1.000–1 | Strength for image 18. |
| insert_frame_19opt | INT | 0-9999–9999 | Frame insert_frame for image 19 (in pixel space). |
| strength_19opt | FLOAT | 1.000–1 | Strength for image 19. |
| insert_frame_20opt | INT | 0-9999–9999 | Frame insert_frame for image 20 (in pixel space). |
| strength_20opt | FLOAT | 1.000–1 | Strength for image 20. |
| insert_frame_21opt | INT | 0-9999–9999 | Frame insert_frame for image 21 (in pixel space). |
| strength_21opt | FLOAT | 1.000–1 | Strength for image 21. |
| insert_frame_22opt | INT | 0-9999–9999 | Frame insert_frame for image 22 (in pixel space). |
| strength_22opt | FLOAT | 1.000–1 | Strength for image 22. |
| insert_frame_23opt | INT | 0-9999–9999 | Frame insert_frame for image 23 (in pixel space). |
| strength_23opt | FLOAT | 1.000–1 | Strength for image 23. |
| insert_frame_24opt | INT | 0-9999–9999 | Frame insert_frame for image 24 (in pixel space). |
| strength_24opt | FLOAT | 1.000–1 | Strength for image 24. |
| insert_frame_25opt | INT | 0-9999–9999 | Frame insert_frame for image 25 (in pixel space). |
| strength_25opt | FLOAT | 1.000–1 | Strength for image 25. |
| insert_frame_26opt | INT | 0-9999–9999 | Frame insert_frame for image 26 (in pixel space). |
| strength_26opt | FLOAT | 1.000–1 | Strength for image 26. |
| insert_frame_27opt | INT | 0-9999–9999 | Frame insert_frame for image 27 (in pixel space). |
| strength_27opt | FLOAT | 1.000–1 | Strength for image 27. |
| insert_frame_28opt | INT | 0-9999–9999 | Frame insert_frame for image 28 (in pixel space). |
| strength_28opt | FLOAT | 1.000–1 | Strength for image 28. |
| insert_frame_29opt | INT | 0-9999–9999 | Frame insert_frame for image 29 (in pixel space). |
| strength_29opt | FLOAT | 1.000–1 | Strength for image 29. |
| insert_frame_30opt | INT | 0-9999–9999 | Frame insert_frame for image 30 (in pixel space). |
| strength_30opt | FLOAT | 1.000–1 | Strength for image 30. |
| insert_frame_31opt | INT | 0-9999–9999 | Frame insert_frame for image 31 (in pixel space). |
| strength_31opt | FLOAT | 1.000–1 | Strength for image 31. |
| insert_frame_32opt | INT | 0-9999–9999 | Frame insert_frame for image 32 (in pixel space). |
| strength_32opt | FLOAT | 1.000–1 | Strength for image 32. |
| insert_frame_33opt | INT | 0-9999–9999 | Frame insert_frame for image 33 (in pixel space). |
| strength_33opt | FLOAT | 1.000–1 | Strength for image 33. |
| insert_frame_34opt | INT | 0-9999–9999 | Frame insert_frame for image 34 (in pixel space). |
| strength_34opt | FLOAT | 1.000–1 | Strength for image 34. |
| insert_frame_35opt | INT | 0-9999–9999 | Frame insert_frame for image 35 (in pixel space). |
| strength_35opt | FLOAT | 1.000–1 | Strength for image 35. |
| insert_frame_36opt | INT | 0-9999–9999 | Frame insert_frame for image 36 (in pixel space). |
| strength_36opt | FLOAT | 1.000–1 | Strength for image 36. |
| insert_frame_37opt | INT | 0-9999–9999 | Frame insert_frame for image 37 (in pixel space). |
| strength_37opt | FLOAT | 1.000–1 | Strength for image 37. |
| insert_frame_38opt | INT | 0-9999–9999 | Frame insert_frame for image 38 (in pixel space). |
| strength_38opt | FLOAT | 1.000–1 | Strength for image 38. |
| insert_frame_39opt | INT | 0-9999–9999 | Frame insert_frame for image 39 (in pixel space). |
| strength_39opt | FLOAT | 1.000–1 | Strength for image 39. |
| insert_frame_40opt | INT | 0-9999–9999 | Frame insert_frame for image 40 (in pixel space). |
| strength_40opt | FLOAT | 1.000–1 | Strength for image 40. |
| insert_frame_41opt | INT | 0-9999–9999 | Frame insert_frame for image 41 (in pixel space). |
| strength_41opt | FLOAT | 1.000–1 | Strength for image 41. |
| insert_frame_42opt | INT | 0-9999–9999 | Frame insert_frame for image 42 (in pixel space). |
| strength_42opt | FLOAT | 1.000–1 | Strength for image 42. |
| insert_frame_43opt | INT | 0-9999–9999 | Frame insert_frame for image 43 (in pixel space). |
| strength_43opt | FLOAT | 1.000–1 | Strength for image 43. |
| insert_frame_44opt | INT | 0-9999–9999 | Frame insert_frame for image 44 (in pixel space). |
| strength_44opt | FLOAT | 1.000–1 | Strength for image 44. |
| insert_frame_45opt | INT | 0-9999–9999 | Frame insert_frame for image 45 (in pixel space). |
| strength_45opt | FLOAT | 1.000–1 | Strength for image 45. |
| insert_frame_46opt | INT | 0-9999–9999 | Frame insert_frame for image 46 (in pixel space). |
| strength_46opt | FLOAT | 1.000–1 | Strength for image 46. |
| insert_frame_47opt | INT | 0-9999–9999 | Frame insert_frame for image 47 (in pixel space). |
| strength_47opt | FLOAT | 1.000–1 | Strength for image 47. |
| insert_frame_48opt | INT | 0-9999–9999 | Frame insert_frame for image 48 (in pixel space). |
| strength_48opt | FLOAT | 1.000–1 | Strength for image 48. |
| insert_frame_49opt | INT | 0-9999–9999 | Frame insert_frame for image 49 (in pixel space). |
| strength_49opt | FLOAT | 1.000–1 | Strength for image 49. |
| insert_frame_50opt | INT | 0-9999–9999 | Frame insert_frame for image 50 (in pixel space). |
| strength_50opt | FLOAT | 1.000–1 | Strength for image 50. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| latent | LATENT | The video latent with the images inserted and latent noise mask updated. |