Nodes/ComfyUI-AudioReactive/Predominant_Pulse (Audio Op)
ComfyUI Node

Predominant_Pulse (Audio Op)

Predominant_Pulse — the tempo-locked curve that tracks the beat, not the hits

By dmarx·Created 3 years ago·Updated 2 years ago· 11
Predominant_Pulse (Audio Op)
  • signal
  • SIGNAL

OpPredominant_pulse (display name "Predominant_Pulse (Audio Op)") computes what librosa calls the pulse: a smooth, tempo-locked curve that oscillates in time with the beat. Where Novelty fires spikes on individual onsets, this one produces a continuous wave that peaks on the perceived pulse - the steady "1-2-3-4" of the track even when no drum is actually hitting. It's the driver you want when you want animation to groove rather than jolt.

It's a direct port from dmarx's video-killed-the-radio-star notebook (the "vktrs" pipeline this whole pack is built from), where it was the second-most-reached-for beat feature after RMS. Same lineage, same name.

How it works

The implementation is a single call: librosa.beat.plp(y, sr). "PLP" stands for predominant local pulse - a 2015-ish approach (Grosche & Müller) that estimates the pulse using a bank of comb filters matched to plausible tempi and picks the strongest one. The result is a per-frame curve, a few hundred values long, where the peaks sit on the beat that a human tapping along would feel. It's fundamentally different from onset strength: instead of measuring "how much changed," it measures "where does the steady pulse live," so it holds up even on tracks with no sharp transients.

Two practical notes from having run this stuff: it works best on music with a clear tempo (surprise), and it will happily lock onto the dominant pulse - on a half-time or swung track, don't be shocked if its peaks sit on the backbeat rather than the downbeat. It's telling you the truth about the pulse, not the one you'd prefer.

Inputs and outputs

  • signal (SIGNAL) - from ARReadAudio or upstream of another operator.
  • SIGNAL - y replaced by the normalized pulse curve. Check it with ARDrawSignal, then feed SignalToCurve to get a KEYFRAMED_CURVE that drives keyframe transitions, ControlNet strength, or motion amount on the beat.

When do you pick this over Novelty? If your targets are on a steady grid and you want them to pulse with the tempo, pulse wins. If you want to react to every transient hit, novelty wins. They complement each other; using both (pulse for the backbone, novelty for accents) is a legit setup.

Installing it

Manager (search "AudioReactive") or:

cd ComfyUI/custom_nodes
git clone https://github.com/dmarx/ComfyUI-AudioReactive

Restart, and sit through the first-load auto-install of scipy, scikit-learn, librosa, loguru - librosa drags in numba, so that first start is slow. And if the pack fails to load with ModuleNotFoundError: No module named 'keyframed', pip install keyframed; it's imported at startup but not in the auto-install list.

Common issues

  • Curve length is frame-based, not sample-based - normal for this pack's feature ops; don't treat it as a waveform.
  • Peaks look "off" from the kick drum you hear - you're probably hearing the kick, and the node is locking to the pulse. Check with ARDrawSignal before you assume it's broken.
  • Mislabeled time axis in Draw Audio Signal - the shared cosmetic quirk: frame-based features inherit the is_raw flag, so x-axis scaling is wrong but the curve shape is right.
  • The pack is an early port - the core feature ops work; the parameterized ops are unwired stubs. This node is one of the working ones, so it's safe to build on.
CategoryAudioReactive/Operators

Inputs (1)

NameTypeDefaultDescription
signalSIGNAL

Outputs (1)

NameTypeDescription
SIGNALSIGNAL