Nodes/comfyui-obvpm-timeline/H3 MCtx Trim and Save Video (obvpm)
ComfyUI Node

H3 MCtx Trim and Save Video (obvpm)

Trim the scaffolding and save the pair, in one node

By chanon·Created 21 days ago·Updated 2 days ago· 33
H3 MCtx Trim and Save Video (obvpm)
  • samples
  • images
  • audio
  • pins
  • conditioning
  • path
  • images
  • audio
base_folderproject1
filename_prefixclip
crf19
save_conditioningtrue
metadata

This is the node to use if you don't want to think about trimming. H3 MCtx Trim and Save Video takes the untrimmed decode straight from your VAE decode nodes, removes the pinned scaffolding itself using the pins wire, and writes the clip pair: MP4 plus .mctx.safetensors sidecar, one transaction.

Compare that with the alternative, which is H3 MCtx Trim Pinned feeding H3 MCtx Save Video - same result, two nodes, and two places where you can wire the wrong frames in. The pack's own advice is this one, unless you have a reason to take the parts.

Why there's any trimming at all

A continuation doesn't sample a clip in isolation. The model is handed the context it continues from as pinned material, re-renders it and continues past it - so the raw latent is longer than the clip you want. The pinned head or tail is scaffolding: it exists so the join happens at a known frame, and it gets removed before delivery.

pins is the authoritative description of what was actually pinned, and that's why this node wants the same wire you fed to H3 MCtx Apply Pins. It isn't re-deriving anything from a setting; it trims what the run really did. A before pin comes off the head, an after pin comes off the tail, and if you pinned nothing (a root clip) it saves as-is.

Audio gets trimmed in lock step with picture, and then tail-matched to exactly frames/fps. That last part sounds pedantic and isn't: H3 delivers about 8 ms more audio than video per clip, and across a chain of ten clips that error compounds into lip sync drift nobody can unsee. The trim nodes exist partly to stop that accumulation.

Inputs and outputs

Required: samples (the sampler's raw output latent - stored whole in the sidecar), images (the untrimmed decode output), base_folder and filename_prefix for where it lands, crf (default 19), and save_conditioning (default on).

crf is worth a moment, because it's the one people undervalue. The assembly path stream-copies these frames and matches this crf for the few it re-encodes, so the take's own setting decides what your finished cut looks like. The MP4 is the delivery copy; the sidecar keeps the lossless latents regardless, which is why a re-encode later doesn't cost you quality on the master.

save_conditioning writes a .cond.safetensors beside the clip. Disk-heavy, and unrecoverable later - the conditioning only exists while the graph that built it is still wired up. Leave it on for anything you might refine.

Optional: audio (also untrimmed - trimmed here in lock step), pins, metadata (provenance JSON; prompt, seed, steps and refs_note are the well-known keys), and conditioning.

Outputs: path, plus the delivered images and audio for previewing. Handy - you can wire those into a preview node without re-decoding.

Install

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

Restart ComfyUI. The pack installs no Python packages; its pyproject declares an empty dependency list on purpose, since torch, torchaudio, numpy, safetensors and av all come with ComfyUI. You need ComfyUI 2026-08-13 or later. In Manager, search comfyui-obvpm-timeline, or just type obvpm in the node menu - every node in the pack carries that suffix.

Troubleshooting

  • First or last frames look like the previous clip. The pins wire isn't connected, so nothing got trimmed. That's the whole failure mode: wired right, the arithmetic is done for you; unwired, it assumes a root clip and saves the scaffolding into your delivery.
  • VHS or another saver downstream complains about frame counts. You're feeding it untrimmed frames. Either use this node's images output, or put H3 MCtx Trim Pinned in front.
  • Audio drifts against picture across a long chain. Something in the chain bypassed the trim. Tail-matching to exactly frames/fps is the guard, and it only works where it runs.
  • Missing .cond, can't refine the take. save_conditioning was off, or the conditioning input was left unconnected - it does nothing when unwired.
  • Metadata refused. The metadata field needs valid JSON. A trailing comma is enough to fail it, deliberately loudly rather than storing nonsense.

Do the trim and the save in one node, wire the same pins to both Apply and Save, and the two halves of the take can't disagree about where the clip starts.

Categoryobvpm/h3

Inputs (10)

NameTypeDefaultDescription
samplesLATENTThe sampler's RAW output latent for this take (the same one you decode). Stored whole in the sidecar; the pinned head/tail stay in it and are mapped out via the header.
imagesIMAGEThe decode output, UNTRIMMED -- this node removes the pinned scaffolding itself using the pins wire.
base_folderSTRINGproject1Output-relative folder to save into. Same meaning as the Timeline's base_folder, so one value can drive both. Empty = the output root.
filename_prefixSTRINGclipFilename prefix within base_folder, like core save nodes. Numbering is appended automatically.
crfINT190–51H.264 quality (lower = better, bigger). THE one that matters: assembly stream-copies these frames and matches this crf for the few it re-encodes, so the take's own setting is what the delivered cut looks like. The MP4 is the delivery copy; the sidecar keeps the lossless latents regardless.
save_conditioningBOOLEANtrueWrite the wired conditioning beside the clip. It is a real amount of disk -- comparable to the latents, and dominated by the reference images' share of the prompt -- so turn this off for throwaway takes and leave it on for anything you may want to upscale later. Off costs nothing now and cannot be recovered afterwards: the conditioning only exists while the graph that built it is still wired up. Does nothing when the conditioning input is unconnected.
audiooptAUDIOThe decoded audio, untrimmed. Trimmed here in lock step with the frames and tail-matched to exactly frames/fps.
pinsoptOBVPM_H3_PINSThe resolved pins from H3MCtxApplyPins. Carries the authoritative generation recipe for the sidecar and derives the lineage edge. Unconnected = root clip.
metadataoptSTRINGOptional provenance as JSON, stored verbatim in the sidecar header (user_meta). Well-known keys browser UI looks for: prompt, seed, steps, refs_note (nothing can fingerprint reference images automatically -- a refs_note is the mitigation). Any other keys are yours. Empty is fine; invalid JSON is refused.
conditioningoptCONDITIONINGOptional: the CONDITIONING this take was sampled with, stored beside the clip as .cond.safetensors. An upscale/refine pass has to sample the same clip again at a larger size, and it needs the same conditioning to do it -- text, reference images and audio, and any refmods applied on top. Rebuilding that from the prompt graph would mean re-running everything that made it, which can silently differ. Unwired = the take saves normally and simply cannot be refined later.

Outputs (3)

NameTypeDescription
pathSTRINGPath of the written MP4; the sidecar sits next to it.
imagesIMAGEThe delivered (trimmed) frames, for preview.
audioAUDIOThe delivered (trimmed) audio, for preview.