CS Video Timeline Edit
Cut, trim and re-layer a video without opening Resolve
- video
- VIDEO
- IMAGE
- frame_count
- audio
- video_info
- fps
What it is, and why you'd want it
Every video workflow ends the same way. You generated a dozen 3–5 second clips, or extended one with VACE, and now there's a real edit to make: trim the dead frames off the top, drop the take with six fingers, put the good bits in order, lay a music bed under it. The bottleneck stopped being clip length and became assembly - people generate dozens of short clips and cut them together, because 3–5 seconds per scene is what films do anyway. Before this node, your options were slice/concat spaghetti, an ffmpeg command, or an export to Resolve.
CS Video Timeline Edit puts a two-video-track, two-audio-track editor inside the node, with a timeline UI, a shot detector, and non-destructive edits that persist in the workflow.
How it actually works
Get one thing straight first: there's a single video input, and both tracks are cut from that one source. This is a re-cut and re-layer tool, not a two-source NLE. If you have four separate generations, concatenate them first and load the result. Same footage on both tracks is still genuinely useful - that's a PIP inset or split screen without a second source.
Clips are ranges: source start frame, timeline position, track (Video1 covers Video2), an A/V link, and optional scale/rotate/translate/mirror. All of it lives in the timeline_json string the Edit Timeline UI writes back - you can see it, don't hand-edit it.
Editing runs on a proxy, rendered at up to 640px so scrubbing stays responsive. Full resolution, fit mode and letterbox fill only happen when the node executes. What you watch while editing is not what you ship, by design.
Transforms use the pack's usual machinery: an affine per clip, inverted, sampled with grid_sample, composited premultiplied-alpha over the lower track. Later clips win within a track; gaps get fill_color. Audio on the two tracks is summed, so overlapping sound plays at once - no ducking, no crossfades.
Shot detection is the other useful half. Detect Shots prefers TransNetV2 if you've wired that runtime up externally - it deliberately keeps TensorFlow out of the ComfyUI process. Without it you get a deterministic fallback: mean absolute RGB difference between adjacent frames, normalised against the clip's own median-to-peak range so Threshold still means something (higher = stricter, fewer cuts). Detected shots land on Video2/Audio2 as clips you can rearrange, and Min scene seconds merges anything shorter into its neighbour.
The inputs and outputs you'll touch
video- any standard ComfyUIVIDEO.CS Load Videois the happy path, since the timeline can trace back to the file.width/height--1keeps the source size; positive values round up tomultiple(default 32).fit_mode-letterbox(default; keeps aspect, bars infill_color),crop, orfill(stretch).in_frame/out_frame- the output range.out_frameis exclusive, so your last frame isout_frame - 1. That trips people up constantly.shot_detect_threshold,shot_detect_min_scene_sec- the two numbers behindDetect Shots.wait_for_input_cache- the preview-cache switch, below.
Six outputs, easy to mix up. VIDEO is the finished composite - to CS Save Video or an official video node. IMAGE is the same content as a frame batch. audio is the mixed audio, empty when no track has sound. frame_count is the real length after In/Out, fps the output rate, and video_info a dictionary of dimensions, source window and timeline flags.
Install
Nothing here downloads a model:
# ComfyUI Manager: search "ComfyUI_CineStyle", install, restart
# or manually:
cd ComfyUI/custom_nodes
git clone https://github.com/chflame163/ComfyUI_CineStyle
python -m pip install -r ComfyUI_CineStyle/requirements.txt
Nodes appear under 😺dzNodes/CineStyle/Video, or double-click the canvas and search cinestyle. Same two caveats as the rest of this pack: it registers through the V3 node API, so a stale ComfyUI won't list it, and its loader logs a failure per module and keeps going - if a node is missing, grep your console for Failed to load CineStyle node module. Dependencies are heavy (PyAV, opencv, transformers, peft, accelerate, timm, hydra-core, iopath, soundfile) but torch isn't pinned, which is what you want.
Troubleshooting
VFR VIDEO input is not supported; provide a CFR video. Phone and screen recordings are usually variable frame rate, and the node refuses them outright rather than quietly miscounting frames. Re-encode:
ffmpeg -i in.mp4 -vsync cfr -r 30 out_cfr.mp4
wait_for_input_cache kills the run mid-execution. Intentional. The node renders a low-res proxy, writes it to the shared preview cache, and raises an interrupt so the timeline window has something to scrub. Turn it on, run once, edit, apply - then turn it off, or you'll never get output.
Your edits vanished after swapping the source video. The node fingerprints its input (content hash, file identity, frame count, fps). If that doesn't match what the timeline recorded, it discards the clip layout and starts from default placement rather than clamping old frame indices onto different footage. Right call - the alternative is a plausible-looking, completely wrong edit - so: new source, re-run Detect Shots. video_info reports timeline_source_mismatch.
The render doesn't match your edit. You closed the window with Cancel, or forgot Apply to node. Undo history lives per node id under ComfyUI/temp, so copying a node into another workflow (or renaming it) falls back to defaults. Apply, then save.
Merge Clip to Next refuses. It only merges clips that are adjacent on the timeline, source-frame continuous, and share the same transform. Split, nudge, merge.
Inputs (12)
| Name | Type | Default | Description |
|---|---|---|---|
| video | VIDEO | Connect any standard ComfyUI VIDEO. | |
| width | INT | -1-1–1048576 | Output canvas width; -1 uses the input source width. Positive values are rounded up to the selected multiple. |
| height | INT | -1-1–1048576 | Output canvas height; -1 uses the input source height. Positive values are rounded up to the selected multiple. |
| multiple | INT | 321–65536 | Round each output side up to this integer multiple. |
| fit_mode | COMBO | letterbox | Fit each clip to the output canvas. |
| fill_color | STRING | #000000 | Hex color for letterbox bars and empty timeline regions. |
| in_frame | INT | 00–10000000 | Timeline In frame; also trims final output. |
| out_frame | INT | -1-1–10000000 | Timeline Out frame (exclusive); -1 uses the timeline end. |
| shot_detect_threshold | FLOAT | 0.500–1 | Shot detection threshold. |
| shot_detect_min_scene_sec | FLOAT | 0.000–60 | Minimum shot duration used by automatic detection. |
| wait_for_input_cache | BOOLEAN | false | Build the timeline preview cache and pause execution. |
| timeline_jsonopt | STRING | Persisted timeline JSON written by Edit Timeline. |
Outputs (6)
| Name | Type | Description |
|---|---|---|
| VIDEO | VIDEO | — |
| IMAGE | IMAGE | — |
| frame_count | INT | — |
| audio | AUDIO | — |
| video_info | DICT | — |
| fps | FLOAT | — |