H3 Joint Conditioning (obvpm)
Keeping several prompts several prompts, across one shared latent
- layout
- conditioning
Here's a problem the joint refine creates for itself. You laid five clips onto one latent so the whole sequence could be sampled in one pass. But those five clips were generated with five different prompts, five different reference sets, and H3 conditions on references through VAE-encoded latents, not on a friendly string. One CONDITIONING for the whole timeline would throw all of that away - and the moment you flatten it, the refine starts "improving" a shot into something that was never asked for.
H3 Joint Conditioning fixes that by loading the conditioning each clip was actually generated with, from its saved .cond file, and handing them to the sampler as one CONDITIONING. H3 Context Windowing then samples every window under the conditioning of the clip that owns most of it. A timeline of several prompts stays several prompts.
The one input, and why the .cond exists
layout comes from H3 Join Latents - it's the map of which clip sits where on the joint latent. That's all this node needs, because everything else is on disk.
The .cond.safetensors files are what make it possible, and the pack's reasoning for storing them is one of the better engineering arguments in the whole project. You could rebuild conditioning by re-running the prompt graph - the workflow JSON is in the sidecar. But that subgraph can silently differ: an input file overwritten, a crop node whose behaviour moved, a swapped CLIP checkpoint. And silently-different conditioning is not detectable until a seam looks wrong. An artifact fails loudly; a recipe fails quietly. So they store the artifact.
The refusal behaviour follows from that: anything in the conditioning that isn't a tensor or JSON-able is refused by name rather than dropped, because a conditioning that loads without the piece that shaped it is precisely the failure the file exists to prevent.
The practical consequence for you: no .cond on a clip means no refine for that clip. The save nodes ask whether to write it (save_conditioning, on by default), and it's a real amount of disk - comparable to the latents and dominated by the reference images' share of the prompt. Turn it off on throwaway takes; leave it on for anything you might upscale.
What comes out, and where it goes
conditioning is a single CONDITIONING for the sampler's conditioning input. It carries a table of every source clip's conditioning plus its span, and it rides to the sampler's window handler inside the conditioning itself - core copies every key of an entry's extras into the cond dict and passes only model_conds to the model, so the table travels on the wire the sampler already has and never reaches the model as tokens.
One subtlety worth knowing about, because it's the difference between a refine being a one-off and a workflow: the rendered cut is saved with a .cond of its own when this node is wired to the render node. Put that rendered cut on a timeline by itself and it can be refined again - 4x from the sources - because this node splices a nested table back in with its spans offset. The second pass still samples each stretch under the prompt and references it was made with.
Install
cd ComfyUI/custom_nodes
git clone https://github.com/chanon/comfyui-obvpm-timeline
Restart ComfyUI. The pack installs no Python packages of its own - its pyproject declares an empty dependency list on purpose, because torch, safetensors and av already come with ComfyUI. Requires ComfyUI 2026-08-13 or later. Manager users: search the pack title comfyui-obvpm-timeline; every node ends in (obvpm), so obvpm also finds them all in the node menu.
Troubleshooting
- Refine complains about missing conditioning. One or more clips in the sequence have no
.condbeside them. Either they were saved withsave_conditioningoff, or theconditioninginput to the save node was never wired - it does nothing when unconnected. - A clip refines into the wrong look. Check which clip owns each window: a clip that most of a window crosses into will pull that window's conditioning. Windows that straddle a cut are inherently a compromise; the overlap blending is what smooths it, not the conditioning.
- Disk pressure. References make
.condfiles big. Pruning them costs you the ability to refine those takes later - that's the whole tradeoff, so prune deliberately. - A wrong
.condrefused with a name. That's the loud failure working as intended. Fix the graph that produced it rather than renaming files. - Second refine pass loses the prompts. The render node only writes the
.condfor the rendered take when this node is wired to it. Wire it.
If you're doing single-clip work, you'll never need this node. If your timeline has more than one prompt in it, it's the difference between an upscale pass and an upscale pass that quietly rewrites your shots.
Inputs (1)
| Name | Type | Default | Description |
|---|---|---|---|
| layout | OBVPM_H3_JOINT | From H3 Join Latents. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| conditioning | CONDITIONING | For the sampler's conditioning input. |