CineTimeline|关键帧分段裁切
The node that trims H3's scaffolding so your shot ends exactly where it should
- images
- audio
- images
- audio
- crop_summary
Video models are greedy. Ask them for a 120-frame shot and they'll quietly hand you more - a lead-in, some padding, a couple of extra frames they needed for alignment. CineTimelineKeyframeFinalize ("CineTimeline|关键帧分段裁切") is the node that cleans up after that greed: it takes the decoded frame batch your sampler produced and cuts it down to exactly the visible shot, audio re-synced to match.
It's the final step in CineTimeline's keyframe-mode chain, and it's where all the frame math that CineTimelineKeyframePlan did upstream finally gets paid off.
Why there's anything to trim at all
Two sources of over-production, both deliberate. First, continuity: when a shot continues the previous one via motion context, the renderer gives it a 22-frame running start copied from the previous shot's tail, so the model has real context to extend rather than hallucinating a jump cut. Second, grid alignment: H3's native lengths land on a 17k+5 frame pattern, so the actual generation gets rounded up past what your timeline asked for.
Left to themselves, those extra frames become invisible junk at the head of every clip after the first - duplicated motion from the previous shot, or padding that makes your cuts land in the wrong place. Finalize strips them.
How it works
Required inputs are images (the decoded frame batch, in order), plan_json (the same per-shot plan that came out of CineTimelineKeyframePlan - that's where it learns the segment index and true frame count), and fps (default 24). Optional audio comes along for the ride.
The logic is small and worth understanding: if this is segment one, there's no lead-in to remove, so it keeps frames from index 0. Every later segment gets the leading 22 frames dropped. Either way it keeps exactly the plan's frame_count frames - which also silently discards the trailing grid padding - and slices the audio to the matching number of samples (or synthesises silence if you didn't feed audio). Outputs are the trimmed images, the trimmed audio, and a crop_summary string like trim 22 + keep 124 frames that tells you exactly what it did.
Feed images from your VAE decode, plan_json from the plan node, and you're ready to save or assemble. This node is genuinely model-neutral - it's pure tensor slicing - so it doesn't care whether the frames came from H3 or anything else that followed the same convention.
Where people get burned
The trim is unconditional for any shot past the first: the node assumes your renderer followed the motion-context convention and actually prepended the 22-frame lead-in. If you render a middle shot standalone - no continuation context - and still push it through Finalize, you'll silently lose the first ~0.9 seconds of real footage. The renderer and the trimmer have to agree, and only shots rendered the pack's way qualify.
Second gotcha: fps matters for the audio cut. The audio is sliced in samples computed from fps (default 24). If your actual media runs at a different rate, the soundtrack drifts out of sync with the trimmed frames. Set it to the media's real rate, not the default.
Installing
Standard for the pack - no Python dependencies of its own:
# ComfyUI Manager: search "ComfyUI-CineTimeline"
# or:
cd ComfyUI/custom_nodes
git clone https://github.com/bo341805sg/ComfyUI-CineTimeline
Restart ComfyUI. One more honest note: like the whole keyframe-mode family, this node is brand new (Sept 2026), the README hasn't caught up to it yet, and it mostly appears inside workflows the pack itself generates. If you're hand-wiring it, match it to the same plan JSON that drove the render, and you'll be fine.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| images | IMAGE | — | |
| plan_json | STRING | — | |
| fps | FLOAT | 24.001–240 | — |
| audioopt | AUDIO | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| images | IMAGE | — |
| audio | AUDIO | — |
| crop_summary | STRING | — |