Nodes/comfyui-obvpm-timeline/H3 MCtx Apply Pins (obvpm)
ComfyUI Node

H3 MCtx Apply Pins (obvpm)

The node that turns a spec into a working join

By chanon·Created 21 days ago·Updated 2 days ago· 33
H3 MCtx Apply Pins (obvpm)
  • conditioning
  • latent
  • video_vae
  • audio_vae
  • pin_specs
  • conditioning
  • latent
  • pins
snap_window_down_to_availablefalse
freeze_audiofalse
masked_audio_feather8
audio_denoise0.00

Every other node in this pack either produces a spec or consumes a result. This one does the work: it slices the pinned windows out of the sources - the pack's sole frame/latent math site - and attaches each pinned run to the conditioning as native H3 keyframe anchors.

If you're reading one article about pins, read this one. Almost every "my extend didn't connect" story ends here.

What it needs

conditioning is the prompt/reference conditioning the sampler will use. latent is the target clip's empty AV latent - authoritative for frame count and resolution - and it must be the same latent you wire to the sampler. snap_window_down_to_available (default off) decides what happens when a source can't supply the requested window: the ladder is 56/39/22/5, and with this off the node refuses loudly instead of snapping. Snapping silently weakens continuity, which is why it's opt-in, but the shipped workflow runs it on.

freeze_audio (default off) re-renders picture only, holding the whole audio mask at 0 so the soundtrack comes out exactly as it went in. Use it for a refine pass, where the sound is already finished - the sampler denoises the nested AV pair together, so without this a refine re-renders audio nobody asked it to touch. It works with no pins at all, which is exactly what the first clip of a timeline needs.

Optional and occasionally essential: video_vae and audio_vae. They're needed only for pins from clips with no usable sidecar, which have to be encoded from pixels (the Timeline emits those for imported footage). Pins from a sidecar never touch a VAE. Both are required together even for silent footage.

masked_audio_feather (default 8, i.e. 0.2 s) applies to masked pins only: a half-cosine release of the preserved audio across its final ticks toward the generated region. 0 gives you a hard mask edge, which is a click waiting to happen.

audio_denoise matters when freeze_audio is on. Holding the audio mask at 0 is the exact freeze; raising this re-samples the sound alongside the picture. At high sigma a refine needs roughly 0.5 here for the model to re-derive lip sync - a frozen audio track gives a near-noise video nothing to move the mouth for. If you do re-sample, the resampled audio must be discarded at save time: wire the save node's source_audio from a decode of the source audio latent instead. Junction-pinned windows stay frozen regardless.

What comes out

Three outputs, and the wiring is not optional in either direction.

conditioning carries the pinned runs as keyframe rows - feed the guider/sampler. latent is the target latent, and you must wire the sampler's latent image from here, not from the empty-latent node: masked pins write their preserved windows and denoise mask into it, while guide-only runs pass it through untouched. pins is the resolved pins - feed it to H3 MCtx Trim Pinned or directly to the Save nodes, because they read what was actually pinned rather than what you asked for.

The pin_specs input is optional on purpose: unconnected or empty means pass-through, so the conditioning comes back untouched and pins comes out empty. A plain root generation. That means the node can sit in the graph permanently and not be bypassed every time you're not pinning.

Install

cd ComfyUI/custom_nodes
git clone https://github.com/chanon/comfyui-obvpm-timeline

Restart ComfyUI. No Python dependencies - the pack declares none, because torch, safetensors and av already ship with ComfyUI. Core H3 needs ComfyUI 2026-08-13 or later; masked pins additionally need a build from 2026-08-18 on. In Manager, search the pack title comfyui-obvpm-timeline; every node in it ends in (obvpm), so obvpm finds the whole set in the node menu.

Troubleshooting

  • You wired the empty latent to the sampler. The classic. Masked pins silently do nothing useful, because the preserved windows live on the latent output here.
  • Loud refusal about a window. A source couldn't supply what you asked. Turn on snap_window_down_to_available to step down the 56/39/22/5 ladder, knowing you're trading continuity for a run that happens.
  • Refine re-rendered your finished audio. freeze_audio was off. Turn it on for refine passes.
  • Lip sync went to mush after a high-denoise refine. Set audio_denoise around 0.5 and remember to render the source audio at save time, or you'll deliver the re-sampled track.
  • Pins from imported footage error. That route needs video_vae and audio_vae connected; the Timeline emits pixel-route pins for footage with no sidecar.
  • A take that can't be crossfaded later. The pins output wasn't also wired to the Save node, so lineage wasn't recorded. Wire it both places.

Get the two wires right - sampler from this node's latent, Save from this node's pins - and the rest of the pin system behaves like it was designed to.

Categoryobvpm/h3

Inputs (9)

NameTypeDefaultDescription
conditioningCONDITIONING
latentLATENTThe TARGET clip's empty AV latent -- authoritative for frame count and resolution. Wire the same latent to the sampler.
snap_window_down_to_availableBOOLEANfalseWhen a source cannot supply the requested window, snap down the ladder (56/39/22/5) instead of refusing. Off = refuse loudly; snapping silently weakens continuity.
freeze_audioBOOLEANfalseRe-render PICTURE ONLY: hold the whole audio mask at 0 so the soundtrack comes out exactly as it went in. For an upscale/refine pass, where the sound is already finished -- the sampler denoises the nested AV pair together, so without this a refine re-renders audio nobody asked it to touch. Works with no pins at all, which is what the first clip of a timeline needs.
video_vaeoptVAEVideo VAE. Needed ONLY for pins from clips with no usable mctx sidecar, which have to be encoded from their pixels (the Timeline emits those for imported footage). Pins from a sidecar never touch a VAE.
audio_vaeoptVAEAudio VAE, for the same pixel-encoded pins as video_vae -- required alongside it even when the footage is silent.
pin_specsoptOBVPM_H3_PINSPECSThe spec stack from H3MCtxPinSpec or a loader's create_pins output. Unconnected or empty = pass-through: the conditioning is returned untouched and pins is empty (a plain root generation), so the node can stay in the graph when not pinning.
masked_audio_featheroptINT80–256Masked pins only: half-cosine release of the preserved audio across its final ticks toward the generated region (8 = 0.2 s). 0 = hard mask edge.
audio_denoiseoptFLOAT0.000–1With freeze_audio: hold the audio mask at this value instead of 0, so the sound re-samples alongside the picture. A refine at high sigma needs ~0.5 here for the model to re-derive LIP SYNC (frozen audio gives a near-noise video nothing to move the mouth for). The resampled audio must then be DISCARDED at save time: wire the save node's audio from a decode of the SOURCE audio latent. Junction-pinned windows stay frozen regardless. 0 = today's exact freeze.

Outputs (3)

NameTypeDescription
conditioningCONDITIONINGConditioning with the pinned runs attached. Feed the guider/sampler.
latentLATENTThe target latent. ALWAYS wire the sampler from here, not from the empty-latent node: masked pins write their preserved windows and denoise mask into it (guide-only runs pass it through untouched).
pinsOBVPM_H3_PINSThe resolved pins. Feed H3TrimPinned / the Save nodes.