AD_In_VideoSplit
Split a video, fix its frame rate, and keep the audio in sync — all in one node
- video
- VIDEO
- IMAGE
- audio
If you've ever dragged a video into a ComfyUI workflow and then had to fight frame rates, mismatched audio, and a wall of preprocessor nodes just to get usable frames, this node is the cleanup crew. AD_In_VideoSplit takes one VIDEO in and hands you three things: a normalized VIDEO, the frames as an IMAGE batch, and the audio track - with everything still in sync after you've resampled, cropped, decimated, or capped it. It's the front door to the pack's video generation stack, and the node you'd reach for before feeding frames to AD_sam_Crop or audio to an H3 reference.
What the inputs actually do
force_rate(FLOAT, default 0) - target FPS. 0 means "keep the source rate." Set it to 24 and a 30fps clip gets resampled to 24fps. This matters because the pack's H3 video nodes run on a 24fps frame grid, and feeding them 30fps footage is asking for drift.custom_width/custom_height(INT, default 0) - resize the frames, keeping aspect ratio if you only set one side. 0 = keep source. Uses Lanczos, so it's decent quality for a first pass.frame_load_cap(INT, default 0) - load only the first N frames. 0 = everything.skip_first_frames(INT, default 0) - trim N frames off the front.select_every_nth(INT, default 1) - keep every Nth frame. This is your frame-decimation dial: 2 halves the frame count, which changes the effective output fps toforce_rate / N.
The three outputs
VIDEO- the processed clip, rebuilt with the new frame rate. Wire this to anything downstream that wants a video.IMAGE- the frames as a tensor batch. This is what you feed to a SAM3 tracker likeAD_sam_Crop, or to any image-based node.audio- the soundtrack, trimmed to match the frame range you actually loaded. This is the sneaky valuable output: when you skip frames or cap the load, the node cuts the audio to the same window, so if you later re-attach it to generated video, lips and sound line up.
How it works
It reads the video's components, resamples the frame index to hit force_rate if you set one, applies your skip/decimate/cap, resizes if asked, and re-derives the output FPS from what actually survived. The audio gets sliced using the same timeline math in sample-space, which is exactly why it stays in sync even after frame decimation - a lot of "why is my audio 0.4s off" posts trace back to nodes that cut frames without cutting the audio.
Where people get burned
The obvious one: if you set frame_load_cap/skip_first_frames so aggressively that zero frames survive, it raises RuntimeError("No frames generated"). No silent black output - it just refuses. Also remember the fps math: after select_every_nth, the output rate is divided by N. If you decimate a 24fps clip by 2 and then feed the audio back as if it's still 24fps, your generated video will run fast. Keep force_rate at your target and let the node do the arithmetic.
Installing it
It's part of cardenluo/ComfyUI-Apt_Preset. Through ComfyUI Manager: search "Apt_Preset" → Install → restart. Or manually:
cd ComfyUI/custom_nodes
git clone https://github.com/cardenluo/ComfyUI-Apt_Preset
# then install deps - double-click install.bat, or:
pip install -r requirements.txt
Restart ComfyUI after. The pack pulls in a real requirements list (opencv, scipy, soundfile, scenedetect, matplotlib and friends), but you don't need any of the optional model packs (GGUF, nunchaku, segmentation models) for this node alone.
Inputs (7)
| Name | Type | Default | Description |
|---|---|---|---|
| video | VIDEO | — | |
| force_rate | FLOAT | 00–60 | — |
| custom_width | INT | 00–8192 | — |
| custom_height | INT | 00–8192 | — |
| frame_load_cap | INT | 00–9007199254740991 | — |
| skip_first_frames | INT | 00–9007199254740991 | — |
| select_every_nth | INT | 11–9007199254740991 | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| VIDEO | VIDEO | — |
| IMAGE | IMAGE | — |
| audio | AUDIO | — |