Nodes/FizzNodes/Prompt Schedule πŸ“…πŸ…•πŸ…
ComfyUI Node Runs on cloud

Prompt Schedule πŸ“…πŸ…•πŸ…

Animate your prompts frame by frame, without writing a line of Python

By FizzleDorfΒ·Created 3 years agoΒ·Updated 2 years agoΒ· 479
Prompt Schedule πŸ“…πŸ…•πŸ…
  • clip
  • POS
  • NEG
β—„text"0" :"", "11" :"", "23" :"", "35" :"", "47" :"", "59" :"", "71" :"", "83" :"", "95" :"", "107" :"", "119" :"" β–Ί
β—„max_frames120β–Ί
β—„current_frame0β–Ί
β—„print_outputfalseβ–Ί
β—„pre_textβ€”β–Ί
β—„app_textβ€”β–Ί
β—„pw_a0.0β–Ί
β—„pw_b0.0β–Ί
β—„pw_c0.0β–Ί
β—„pw_d0.0β–Ί

The moment a static image stops being enough, this is the node you reach for. Prompt Schedule is the flagship of the FizzNodes pack (FizzleDorf/ComfyUI_FizzNodes) and the tool that made prompt-driven animation in ComfyUI practical for normal people. You write a prompt at key frames - frame 0, frame 30, frame 60 - and the node encodes each one, then morphs the conditioning smoothly from prompt to prompt across every frame in between. The output is two CONDITIONING tensors (POS and NEG) that plug straight into your KSampler, exactly like a normal CLIP Text Encode.

It comes from Deforum, one of the first big animation tools, and it shows: the schedule format, the --neg splitting, the whole mental model are Deforum's. If you've ever built a Deforum prompt animation, this is home.

How it works

The text input is a schedule of keyframes, one per line, in a JSON-ish format:

"0" : "a woman walking through a forest, cinematic lighting",
"30" : "the same woman walking through a neon city at night, cyberpunk",
"60" : "the same woman on a beach at sunset"

That's it. Between keyframes the node linearly ramps a blend weight between the current prompt's conditioning and the next one's, using composable diffusion (ConditioningAverage under the hood). On a keyframe frame it encodes just that prompt; in between, it encodes both and mixes them. Because the weight is interpolated rather than the text, transitions are smooth instead of snapping.

A few things make it genuinely powerful:

  • Math in your prompts. The whole thing runs through numexpr, so values like (1 + 0.5 * sin(2*pi*t/120)) work inside a prompt. t is the current frame, and pw_a through pw_d are four float inputs you can wire from other nodes. This is how you do things like a prompt weight that breathes in and out.
  • --neg splits positive from negative. Anything after --neg in a keyframe goes to the NEG output. pre_text and app_text are prepended/appended to every frame, so you can keep a stable style prefix or character description out of the keyframes entirely.
  • The rollover. current_frame is taken modulo max_frames, so if your animation loops past the end it wraps cleanly back to frame 0.

The inputs you'll actually touch: text, clip, max_frames (how long the animation is), and current_frame - which is a forced input in the source, meaning it's meant to be wired from a frame counter rather than typed. print_output dumps the evaluated prompt and blend weight for every frame to your console; leave it off until something looks wrong, then flip it on and it's a free debugger.

Installing it

This is the easy part. Open ComfyUI Manager, search FizzNodes, install, restart. Manual path if you hate buttons:

cd ComfyUI/custom_nodes
git clone https://github.com/FizzleDorf/ComfyUI_FizzNodes
cd ComfyUI_FizzNodes
pip install -r requirements.txt   # numpy, pandas, numexpr

That's the whole dependency list - no models to download, nothing heavy. Restart ComfyUI and the nodes live under FizzNodes πŸ“…πŸ…•πŸ… in the menu.

Where people get burned

The schedule is parsed as JSON, so a trailing comma or a missing quote kills the whole thing. Keep the "frame" : "prompt" shape exact. If you get an error about malformed text, it's almost always this.

Second, leave current_frame static and you'll render the same frame's prompt the entire run. In a batch workflow (AnimateDiff, VHS) it should be wired to the per-frame counter. Third: smooth animation wants a deterministic sampler. The README's example uses Euler and notes the whole thing fits in ~4.7 GB - it's a genuinely light way to make motion.

This is the node the rest of the pack orbits. If you're animating, learn it first.

CategoryFizzNodes πŸ“…πŸ…•πŸ…/ScheduleNodes

Inputs (11)

NameTypeDefaultDescription
textSTRING"0" :"", "11" :"", "23" :"", "35" :"", "47" :"", "59" :"", "71" :"", "83" :"", "95" :"", "107" :"", "119" :"" β€”
clipCLIPβ€”
max_framesINT1201–999999β€”
current_frameINT00–999999β€”
print_outputBOOLEANfalseβ€”
pre_textoptSTRINGβ€”
app_textoptSTRINGβ€”
pw_aoptFLOAT0.0-9999–9999β€”
pw_boptFLOAT0.0-9999–9999β€”
pw_coptFLOAT0.0-9999–9999β€”
pw_doptFLOAT0.0-9999–9999β€”

Outputs (2)

NameTypeDescription
POSCONDITIONINGβ€”
NEGCONDITIONINGβ€”