ComfyUI Node

πŸ“ˆ Beat Curve

Make your animation move to the music

By alt-key-projectΒ·Created 3 years agoΒ·Updated 2 years agoΒ· 114
πŸ“ˆ Beat Curve
  • frame_counter
  • FLOAT
  • INT
β—„bpm100.00β–Ί
β—„time_offset0.00β–Ί
β—„measure_length4β–Ί
β—„low_value0.00β–Ί
β—„high_value1.00β–Ί
β—„invertβ–Ύβ–Ί
β—„power2.00β–Ί
β—„accent_11β–Ί
β—„accent_20β–Ί
β—„accent_30β–Ί
β—„accent_40β–Ί

The author makes music videos, so of course the pack ships a curve that syncs to a beat. Beat Curve [Dream] is a frame-counter-driven node that fires an impulse at each beat of a measure - think kick drum triggering a zoom punch or a flash of motion - instead of the smooth sine/linear waves the rest of the curves family gives you. Every time the beat lands, the output spikes; between beats it falls back to quiet.

How it works

Given the frame_counter, bpm, and a measure_length (beats per measure), the node computes how many frames a beat lasts at your current framerate: frames_per_beat = fps * 60 / bpm. Then for each frame it checks whether that frame falls inside one of your marked beats. If it does, it outputs a value that ramps down linearly across the beat - 1.0 right at the beat, decaying toward 0 by the next one - and that decay gets sharpened by a power exponent. The default power of 2.0 gives a punchy spike; higher makes it snappier, lower makes it mushier. The result is mapped into your low_value/high_value range, so the node sits anywhere between a subtle wobble and an on-off strobe.

The inputs that matter

  • frame_counter - the pack's standard clock; this is how the node knows which beat you're on.
  • bpm - your track's tempo. Get this wrong and the "sync" is just random pulsing, so match it to the actual music.
  • measure_length - beats per measure (4 for standard 4/4). 1 makes every beat hit.
  • accent_1 (required) and accent_2/3/4 (optional) - which beats in the measure get an impulse. Default accent_1 = 1 gives one hit per measure on beat 1; add accent_2 for a backbeat.
  • power - spike sharpness, default 2.0.
  • low_value / high_value - the output range; default 0 to 1.
  • invert - flip the spike into a dip (punch the value down on the beat instead of up).
  • time_offset - shift everything in seconds, for syncing to a track that doesn't start at frame 0.

It outputs both FLOAT and INT versions of the value, so it can drive anything from a zoom amount to a seed or a boolean-ish gate.

Where it wires in

This is the node that makes a zoom feel musical. Wire its FLOAT output into Image Motion [Dream]'s zoom (or x_translation), set the bpm to your track, and every beat triggers a push-in that decays before the next one. The pack's example workflows treat curves like this as first-class animation drivers - a curve per parameter, all ticking off the same frame counter.

Installing it

Ships with Dream Project Animation Nodes - ComfyUI Manager (search Dream Project Animation) or clone https://github.com/alt-key-project/comfyui-dream-project into custom_nodes, pip install -r requirements.txt, restart. No model downloads.

Common issues

The classic gotcha is framerate mismatch: the beat math uses the fps baked into your frame_counter, so if your counter says 30 but the sampler actually renders at 24, the spikes land late and early and nothing feels synced. Keep the counter's fps honest. Also note that with the default settings (accent 1, measure 4) you only get one pulse per measure - for a driving four-on-the-floor feel you want accent_1, 2, 3 and 4 all active. And the decay is linear under the hood, so if beats feel mushy rather than sharp, raise power instead of fiddling with bpm.

Category✨ Dream/πŸŽ₯ animation/πŸ“ˆ curves

Inputs (12)

NameTypeDefaultDescription
frame_counterFRAME_COUNTERβ€”
bpmFLOAT100.00β€”
time_offsetFLOAT0.00β€”
measure_lengthINT4β€”
low_valueFLOAT0.00β€”
high_valueFLOAT1.00β€”
invertCOMBO2 options: no, yes
powerFLOAT2.000.25–4β€”
accent_1INT11–24β€”
accent_2optINT00–24β€”
accent_3optINT00–24β€”
accent_4optINT00–24β€”

Outputs (2)

NameTypeDescription
FLOATFLOATβ€”
INTINTβ€”