Smart Video Chunker
Silence-based video+audio chunking for LTX 2.3 and Wan 2.2
- video
- audio
- num_chunks
- chunkOImages
- chunkOfAudio
- numberFrames
- actual_end_time
- actual_start_time
- chunk_duration
- numGenerationFrames
This is the node this pack is built around. Smart Video Chunker takes a long video with audio and slices it into segments for LTX 2.3 or Wan 2.2, putting the cuts on silence so a speaker never gets chopped mid-word, resampling to the target model's FPS, and snapping every chunk to the model's valid frame-count grid so the sampler doesn't reject it. In one node: chunk on speech boundaries, resample, and satisfy LTX's exacting 8n+1 (or Wan's 4n+1) frame rules - the three things that otherwise take a wall of math and switch nodes.
Why chunk at all? The README is blunt: chunking is required to get around VRAM issues. You generate long content as a series of smaller passes. And the frame-snapping matters because LTX 2.3's constraints are hard - off-grid frame counts fail rather than round, per the model card. If you've ever hit "invalid frame count" errors on LTX, this is the node that makes them stop.
How it works
Internally it calls the pack's TKSmartAudioChunker to find silence-based timing, then does the video work in steps:
- Slice at native FPS. Using
source_fps(the true fps of your incoming video tensor), it computes the frame window for the chunk and pads it slightly so resampling never comes up short. - Resample to
target_fps(25 for LTX, 16 for Wan - the tooltip's defaults) via frame-index sampling. - Snap to the model's grid -
model_typeof LTX rounds to8n+1, WAN to4n+1, always rounding up so the model never gets fewer frames than the true duration. - Slice the audio to match, sample-accurately - padding with silence if the audio runs out.
- Carry
actual_end_timeforward via thestart_time_overrideinput, so chunk N+1 starts exactly where chunk N ended, even after snapping trimmed or padded a boundary.
The index input (zero-based, from your loop) picks which chunk this pass produces; leave start_time_override at -1 for index 0.
The inputs that matter
video+audio- the sources, anIMAGEtensor andAUDIO.index- loop driver.chunk_secs(target segment size) andvariation(how far to search for silence). Lowerchunk_secsfor low VRAM.source_fpsvstarget_fps- the single most error-prone pair.source_fpsmust be your video's real rate (from a metadata node),target_fpswhat your model wants.model_type- LTX or WAN; it decides the frame grid.
Outputs
Eight sockets, but you mainly care about four: chunkOImages (the sliced IMAGE), chunkOfAudio (the matched AUDIO), numberFrames (frames after snapping - what the sampler actually generates), and num_chunks (total, for loop bounds). The timing outputs (actual_end_time, actual_start_time, chunk_duration) exist to be fed back into start_time_override for the next iteration so boundaries stay contiguous.
Common issues
Wrong source_fps is the classic: tell it 30 when the video is really 24 and every chunk's timing and frame count drift off. Pull the fps from your video loader, don't type from memory. And remember chunking is a compromise - Wan degrades past ~5s of content and LTX holds longer, so let your target model guide chunk_secs, not a round number. If you see generation_frames vs numberFrames differences in the log, that's the snap-vs-trim design working as intended, not an error.
Installing it
Part of trashkollector/TKNodes ("ComfyUI Handy Nodes"). Install via ComfyUI Manager (search "Handy Nodes") or:
cd ComfyUI/custom_nodes
git clone https://github.com/trashkollector/TKNodes
Restart. Needs the pack's stack - pydub + FFmpeg on PATH for audio, torch/torchaudio - but no model downloads beyond your usual video model.
Inputs (9)
| Name | Type | Default | Description |
|---|---|---|---|
| video | IMAGE | Source video | |
| audio | AUDIO | Source audio | |
| index | INT | 00–9999 | Index from Loop - zero based |
| chunk_secs | INT | 10 | Size of each video segment in seconds |
| variation | INT | 2 | Num seconds variation. chunks_secs +/- variation adds flexiblity to find silence |
| source_fps | FLOAT | 30.001–240 | TRUE fps of incoming video tensor |
| target_fps | FLOAT | 25.001–240 | fps required by target model - 25 for LTX, 16 for WAN (typical) |
| start_time_overrideopt | FLOAT | -1.000-1–999999 | Use -1 for index 0, used to maintain exact timing of chunks. |
| model_typeopt | COMBO | LTX | Target model frame-count boundary: LTX=8n+1, WAN=4n+1 |
Outputs (8)
| Name | Type | Description |
|---|---|---|
| num_chunks | INT | Number Chunks Calculated for the Video. |
| chunkOImages | IMAGE | Video |
| chunkOfAudio | AUDIO | Audio |
| numberFrames | INT | # Frames after Snapping |
| actual_end_time | FLOAT | end time in video of chunk |
| actual_start_time | FLOAT | start time of chunk in video |
| chunk_duration | FLOAT | length of chunk |
| numGenerationFrames | INT | num Frames requested by user w/o snapping |