Nodes/ꘇ Genereti/ꘇ chop.time
ComfyUI Node

ꘇ chop.time

Every way you'll ever want to ask 'what time is it'

By languel·Created about a month ago·Updated 3 days ago· 1
ꘇ chop.time
  • clock
  • value
  • channels
  • json
  • clock
◄unit▾►
◄performance{}►

Most ComfyUI time is implicit and awful: you wire nothing, you get a different random seed, and nothing on screen changes in a way you can reason about. Genereti gives its workflows a real transport - a clock that keeps running whether or not you queue - and chop.time is the node that hands you a reading off it. One unit, one number, plus the whole snapshot and a clock reference if you want them.

This is the Performance family of ꘇ Genereti (languel/genereti, Liuboto, MIT, loudly labelled super-alpha). The premise of the pack is that ComfyUI's queue is a snapshot engine - press Queue, get one frame - and live work needs a second, continuous time source living in the browser. chop.time is the read-out for that second clock.

The units

unit is a COMBO and it's the only required input. Ten options, and they're worth reading as a list because they define what "musical time" means in this pack:

  • seconds - score seconds, which hold still when you pause
  • quarterNotes, beat, bar - musical position; bar is a zero-based elapsed bar index, beat counts meter beats (so in 6/8 a bar is six of them)
  • ticks - 480 ticks per quarter note, the pack's PPQ
  • phase - the quarter-note fraction, useful as an LFO
  • bpm, playing, iteration - tempo, whether the transport is running, and the loop counter
  • wallTime - Unix seconds, deliberately separate from pausable score time

The node picks one field out of the clock snapshot and returns it as value.

The optional clock input takes a GENERETI_AUDIO_CLOCK - that's the type mod.transport emits - and if you leave it unconnected the node reads project time from the performance snapshot. The optional performance STRING is the raw JSON snapshot itself; default is {}, which then falls back to the defaults (120 bpm, 4/4, zero seconds). In other words: wire a clock for an independent sequence, leave it empty to follow the timeline dock.

Outputs

Four, and they're more useful than they look:

  • value (FLOAT) - the selected unit. This is the one you convert to an input and wire into any ordinary Comfy parameter: a translate amount, a noise speed, a rotation.
  • channels (GENERETI_CHOP) - the whole clock as named channels: seconds, quarterNotes, beat, bar, beatInBar, ticks, phase, bpm, playing, iteration, at a 25 Hz sample rate. Feed it to chop.select to pick a channel by name, or to chop.math to scale one.
  • json (STRING) - the full snapshot printed as JSON. ꘇ dat.inspect displays it readably.
  • clock (GENERETI_AUDIO_CLOCK) - a pass-through/reference, so one clock can fan out to several readers.

The clock snapshot itself is stricter than you'd think: the pack validates it, rejects non-finite values and a non-positive BPM, and raises on a malformed meter. If you hand-write a performance string and get an error, it's telling you the truth.

Live versus Queue

This is the node where the pack's central design decision becomes visible. Live, chop.time reads the browser clock and updates continuously. On Queue, the snapshot is captured once per prompt and every linked consumer uses that frozen value - the docs put it as "Queue is a render checkpoint, not a real-time tick source." So a queued render at beat 12 gets beat 12 everywhere. The nice part is that the same wiring works for both; you're not maintaining two graphs.

Install

Manager → search "Genereti" → install ꘇ Genereti → restart → refresh the browser. Manual:

git clone https://github.com/languel/genereti.git custom_nodes/genereti
./.venv/bin/python -m pip install -r custom_nodes/genereti/requirements.txt

One pinned dependency (comfyui-frontend-package>=1.53.6). Needs ComfyUI 0.38.2+, Python 3.11+, and a current browser. Then open Workflows → Genereti → ꘇ-Performance-Timeline and hit Alt+Shift+T to bring up the dock.

Gotchas

A bare chop.time with default settings reads project time, not node time. If you expected an independent per-node clock, you want mod.transport with its naming options. The fix is a wire, not a setting.

Time values are control data, not audio and not frames. The channels block is a 25 Hz snapshot; the pack is explicit that this is not an audio-rate stream. If you feed it into something expecting sample-accurate timing, you'll get stepping.

playing is 0 or 1 here, not a boolean. Converted to a FLOAT output it's numeric by design, so don't compare it to true.

CategoryGenereti / Performance

Inputs (3)

NameTypeDefaultDescription
unitCOMBO10 options: seconds, quarterNotes, beat, bar, ticks, phase, +4
clockoptGENERETI_AUDIO_CLOCK—
performanceoptSTRING{}—

Outputs (4)

NameTypeDescription
valueFLOAT—
channelsGENERETI_CHOP—
jsonSTRING—
clockGENERETI_AUDIO_CLOCK—