GIF Prepare / Blink Schedule
The small node that trims your clip and plans the blinking
- images
- video_info
- images
- text_on_indexes
- fps
- frame_count
- duration_seconds
There are three "Prepare" nodes in GIF Toolkit, which is confusing, so let's be precise about which one this is. GIF Prepare / Blink Schedule is the minimal one: it trims the batch to a maximum duration and works out which frame indexes should have text visible. No resizing, no fps conversion, no aspect cropping.
If you're building a new workflow, you almost certainly want GIF Prepare / Preset instead - this node is the older, simpler half of what that one does.
How it works
It reads the fps out of the VHS_VIDEOINFO dictionary - trying loaded_fps, then source_fps, and falling back to 8 if neither is present. Then it does two calculations.
Trimming: max_duration_seconds × fps, rounded, capped at however many frames you actually delivered. Everything past that is dropped.
Blinking: the on and off timings get converted into frame counts (round(seconds × fps), minimum one frame each), added into a cycle, and every frame whose index mod cycle lands in the "on" part gets recorded. The result is emitted as a comma-separated string of indexes - 0, 1, 2, 3, 8, 9, 10, 11, ... for half-second blinks at 8 fps. It always starts on, frame 0.
That's a modest amount of arithmetic, but it's the honest kind: because it's index-based, the blink rhythm is exactly periodic in the output GIF regardless of how the source was sampled.
The inputs and outputs that matter
images(IMAGE) andvideo_info(VHS_VIDEOINFO, required) - the frames and the info dictionary fromVHS_LoadVideo. No VideoHelperSuite, no run.max_duration_seconds(FLOAT, default6.0, up to 60) - your trim length. Set it to0and it keeps everything.blink_on_seconds/blink_off_seconds(FLOAT, default0.5each) - the visible and hidden halves of the cycle.
Out comes images (the trimmed batch), text_on_indexes (STRING), fps (FLOAT), frame_count (INT) and duration_seconds (FLOAT).
Now the gotcha, and it's a real one: text_on_indexes is not what drives the blinking in the finished GIF. GIF Text Overlay computes its own on/off schedule from the blink_on_seconds / blink_off_seconds widgets on its node and the fps you wire into it. The string output is informational - it's a comma-joined string, so you can't wire it into an integer input anyway. Don't spend an evening trying to figure out why editing this node's blink values doesn't change the animation; set them on the Overlay node.
Install
Manager → search GIF Toolkit → Install, or:
cd ComfyUI/custom_nodes
git clone https://github.com/oekobudde/ComfyUI-GIFToolkit.git
Restart ComfyUI completely. The pack ships no pip dependencies; its only hard requirement is ComfyUI itself plus ComfyUI-VideoHelperSuite for the video loading and VHS_VIDEOINFO type.
Common issues
The output is not resized or converted. Correct - this node doesn't do that. Frames come out at exactly the resolution and fps the loader produced. Use GIF Prepare / Preset if you want 320-pixel output, or you'll hand a 1080p batch to the text designer and wonder why the preview is enormous.
Duration comes out shorter than max_duration_seconds. The trim can only cut, never extend. Whatever VHS_LoadVideo delivered - watch its frame_load_cap, 144 by default - is the ceiling.
Blink is faster or slower than the seconds you typed. Check the fps: the conversion is round(seconds × fps), and at 8 fps a 0.5 s on-phase is 4 frames. Change the source fps and the same numbers give you a different rhythm. It's also the reason the older preset node in this pack carries blink values - same math, one fewer node.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| images | IMAGE | — | |
| video_info | VHS_VIDEOINFO | — | |
| max_duration_seconds | FLOAT | 6.00–60 | — |
| blink_on_seconds | FLOAT | 0.500.05–10 | — |
| blink_off_seconds | FLOAT | 0.500.05–10 | — |
Outputs (5)
| Name | Type | Description |
|---|---|---|
| images | IMAGE | — |
| text_on_indexes | STRING | — |
| fps | FLOAT | — |
| frame_count | INT | — |
| duration_seconds | FLOAT | — |