Nodes/ComfyUI-FPSFrameDrop/Force FPS (Keep Speed, VHS-style)
ComfyUI Node

Force FPS (Keep Speed, VHS-style)

Forcing a Lower FPS on Frames You Already Made

By dailydoseofaiart·Created 4 months ago·Updated 4 months ago· 0
Force FPS (Keep Speed, VHS-style)
  • images
  • images
  • frame_count
  • output_fps
  • dropped_frames
source_fps24.000
force_fps12.000

Your video model just handed you 121 frames, and you want the final clip at 12fps instead of 24. If you just tell the Video Combine node to play at 12fps, congratulations - you've made a slow-motion clip that's twice as long. That is not the same thing as a 12fps video, and this node exists because the distinction is embarrassingly easy to miss.

The mental model that un-sticks this: frames are duration. A 121-frame clip at 24fps runs about 5 seconds. Drop the label to 12fps and it's still 5 seconds of content, but you've doubled playback time. The only way to actually change the frame rate without changing the speed of motion is to remove frames. That's the whole job of Force FPS (Keep Speed, VHS-style) - it takes an IMAGE batch you already generated, subsamples it down to a lower frame rate, and preserves the clip's duration and playback speed. The "VHS-style" in the name is literal: it applies the same frame-time selection trick Video Helper Suite uses when you force FPS in its video loader, except it works on a frame batch already sitting in your graph instead of at load time.

Where it sits in a workflow

Video models all have a native output rate - Wan generation lands around 16fps, LTX and Hunyuan near 24 - and sometimes you want the delivered clip slower, for a deliberate, stop-motion-ish feel, for file size, or just to match a reference video's cadence. Drop this node between your VAE-decode/upres stage and the final encoder:

... -> (IMAGE frames) -> Force FPS (Keep Speed, VHS-style) -> Video Combine

Generation cost doesn't change - you already rendered every frame - but the encode and the final playback do.

How it actually works

The node walks your frames with a running time accumulator. It computes 1/source_fps as the frame time of what you have and 1/force_fps as the interval it wants, then steps through the batch keeping a frame each time the accumulated time crosses the target interval and resetting the counter. No blending, no interpolation - just index_select pulling the frames at the right time positions. Pure torch op: runs in milliseconds, costs zero VRAM.

One behavior you'll trip on if nobody warns you: it only forces down. If force_fps >= source_fps it passes your batch through untouched and reports source_fps as the output. If you want a higher rate than what you generated, that's frame interpolation (RIFE or your model's own frame-interpolation node), not this node. Different tool.

The inputs and outputs that matter

You set exactly three inputs: images (the frame batch), source_fps (default 24 - the FPS the frames were actually generated at; get this right or the drop math is off), and force_fps (default 12 - your target).

The outputs are where the wiring payoff is:

  • images - the reduced batch, straight into your Video Combine
  • output_fps - the FPS your encoder should use; feed this into Video Combine's fps input
  • frame_count / dropped_frames - the before/after, useful as a sanity check that the node did what you expected

Install

Zero dependencies - no requirements.txt, no model files, just the node. Install via ComfyUI Manager (search "ComfyUI-FPSFrameDrop" or the node's display name, "Force FPS (Keep Speed, VHS-style)"), or the old-fashioned way:

cd ComfyUI/custom_nodes
git clone https://github.com/dailydoseofaiart/ComfyUI-FPSFrameDrop

then restart ComfyUI. The README's install section still says to "copy the vhs_force_fps_keep_speed folder" into custom_nodes - that's stale; the repo's a normal __init__.py + nodes.py layout, so the plain clone works fine.

Common gotchas

  • You forgot to change Video Combine's fps. The node drops frames, but if your encoder still runs at the source FPS, the clip plays too fast. Wire output_fps into Video Combine and the timing just works - this is the README's own recommended wiring.
  • source_fps is wrong. If your frames are actually 16fps (Wan's default) and you tell the node 24, it drops the wrong count and your timing drifts. Feed it the real rate.
  • Choppy motion at aggressive drops. Going 24 → 6 means keeping roughly one frame in four; motion will stutter. That's physics, not a bug. If you want smooth slow motion, generate at your target FPS from the start or interpolate up afterward.
  • Forcing up does nothing - see above. It's a pass-through, by design, not a silent failure.

It's a small, honest utility node: it does one thing, does it the way VHS does, and doesn't pretend to do more. If you've ever stared at a video that came out "sped up" or "double length" and couldn't figure out why, this is the fix for the frame-rate side of that confusion.

Categoryvideo/custom

Inputs (3)

NameTypeDefaultDescription
imagesIMAGE
source_fpsFLOAT24.0000.001–1000
force_fpsFLOAT12.0000.001–1000

Outputs (4)

NameTypeDescription
imagesIMAGE
frame_countINT
output_fpsFLOAT
dropped_framesINT