Nodes/Kinburg-Nodes/Siren Compare (Audio) 🧜
ComfyUI Node

Siren Compare (Audio) 🧜

A/B two takes of the same song by ear, blind if you want

By KinburgΒ·Created 3 months agoΒ·Updated 6 days agoΒ· 1
Siren Compare (Audio) 🧜
  • audios
  • settings_data
  • html_path
  • url
β—„titleSiren comparisonβ–Ί
β—„filename_prefixsiren_compareβ–Ί
β—„audio_formatFLAC (lossless)β–Ί
β—„scope_columns0β–Ί
β—„auto_collecttrueβ–Ί
β—„self_containedfalseβ–Ί
β—„bpm0β–Ί
β—„beats_per_bar4β–Ί
β—„n_fft2048β–Ί
β—„n_mels192β–Ί
β—„labelsβ€”β–Ί
β—„notesβ€”β–Ί
β—„timesβ€”β–Ί
β—„lyricsβ€”β–Ί
β—„output_dirβ–Ί

Comparing two generations of the same song by eye is meaningless - there's no SSIM for audio, and the only honest question is "which one sounds better." Siren Compare builds a comparison page for that: every take is decoded into one Web Audio clock so they play in perfect sync, soloing between them mid-phrase is instant and silent, and there's a blind mode that hides the names and shuffles the takes so the louder one doesn't simply win your attention. It's the audio cousin of the pack's Image Compare node, and it's what you reach for after a Siren A/B sweep.

How it works

audios is the input - wire a Get Accumulator (audio) here and drop a Set Accumulator (audio) on each branch, the same idiom as Image Compare (the Collect button wires them in index order). A single AUDIO works too. The node writes a portable folder - index.html plus audio/ and scopes/ with relative links - served on a token you open with the node's "Open comparison" link. Offline: the default self_contained: off writes the light folder, which is right for opening in-app; turn self_contained on to get one .html with everything inlined as data URIs, the only version a browser will open straight off disk (a browser refuses to fetch local media from a file:// page, so a zipped folder plays nothing).

The page itself does the things you'd want a real A/B tool to do: click a scope to seek, shift-drag to loop a bar, match level trims takes to equal RMS, blind shuffles the names, and the spectrograms ship as data - colours, dB window, channel and an A/B diff are all live on the page, no re-running to change the view. Measurements, Settings and Notes tabs each have a "differences only" mode, and lyrics sit in a side panel.

The inputs worth touching

  • audio_format - FLAC (lossless) is the default and should stay it: you're comparing fine detail, and a lossy codec adds differences of its own. Drop to MP3/Opus only to make a bundle small enough to send someone.
  • labels, notes, times, lyrics, settings_data - the annotation layer. times (one line per take, in track order) turns the Measurements tab into "what did the extra stage cost" via a vs fastest row. settings_data from Generation Info Filter becomes the Settings tab, where a differences-only view shows exactly which setting moved between takes. lyrics split by --- lines handles takes sung from different words.
  • scope_columns - time resolution of the shipped spectrogram data. 0 = auto, which is what you want: 25 columns per second (one per ACE-Step latent frame, 40 ms), clamped to 1200–6000, so a 3-minute track comes to ~1.6 MB.
  • n_fft / n_mels - spectrogram resolution, default 2048/192. The 192 note is the same one as in Siren Scope: at n_fft 2048 there are only 1025 bins, and 256 mel bands would leave two permanently dead rows.

Outputs: html_path and url.

Installing it

Same pack: ComfyUI Manager β†’ "Kinburg-Nodes", or git clone https://github.com/Kinburg/Kinburg-Nodes into ComfyUI/custom_nodes, restart. No extra dependencies. The setup cost is the accumulator idiom - if the page shows "Take 1, Take 2" where names should be, you skipped the Set/Get Accumulator (captions) step on the branches; that's the usual first-run stumble.

CategoryKinburg-Nodes/Bestiary/Siren

Inputs (17)

NameTypeDefaultDescription
audiosAUDIOThe takes to compare. Wire a 'Get Accumulator (audio)' here and drop a 'Set Accumulator (audio)' on each branch β€” same idiom as Image Compare, and the Collect button wires them in index order. A single AUDIO works too.
titleSTRINGSiren comparisonβ€”
filename_prefixSTRINGsiren_compareβ€”
audio_formatCOMBOFLAC (lossless)How the takes are written into the bundle. FLAC is the default and should stay the default: you are comparing fine detail, and a lossy codec would add differences of its own on top of the ones you are trying to hear. MP3/Opus only to make a bundle small enough to send someone.
scope_columnsINT00–12000Time resolution of the shipped spectrogram data, in columns. 0 = auto, which is what you want. Auto gives 25 columns per second β€” one per AceStep latent frame, 40 ms β€” clamped to 1200…6000. That is finer than the screen so there is real detail to find when you zoom in, without making the bundle silly: a 3-minute track comes to about 1.6 MB. This is the only scope setting that has to be decided here, because changing it means recomputing the spectrogram. Colours, dB window, mode, channel, zoom and the diff are all live on the page.
auto_collectBOOLEANtrueRe-wire every Get Accumulator in the graph automatically, right before the workflow is queued β€” so a Set you just added, removed, muted or bypassed is picked up without a click. Off: only the 'πŸ”Œ Collect All' button collects. (Purely an editor convenience; the backend ignores this value.)
self_containedBOOLEANfalseHow the comparison is saved. OFF (default): a portable FOLDER β€” a light index.html plus audio/ and scopes/ with relative links. Small, quick to write, and what you want for opening it in-app. ON: ONE .html with every take and every spectrogram inlined as a data: URI. Bigger (base64 adds a third), but it is the only version that works when somebody OPENS IT STRAIGHT OFF DISK β€” a browser refuses to fetch local media from a file:// page, so a zipped folder plays nothing and draws nothing. Turn this on to send a comparison to someone, and pick MP3 or Opus first unless the point is lossless: a 3-minute FLAC take inlines to about 40 MB.
bpmINT00–300Starting value for the page's bar/beat grid β€” you can change it there without re-running. 0 = a plain time ruler.
beats_per_barINT41–16β€”
n_fftINT2048256–16384FFT window for the shipped spectrogram data. Larger = finer frequency detail, blurrier timing.
n_melsINT19216–1024Mel bands in the shipped data. 192 is the most that stays fully populated at n_fft 2048 β€” ask for 256 and two bands come out empty, i.e. dead rows in the picture.
labelsoptSTRINGOne label per line, in track order β€” wire a 'Get Accumulator (captions)', which already joins with newlines. Missing labels become 'Take N'.
notesoptSTRINGFree text shown per track: a Siren report, a Generation Info dump, your own remarks. Takes either convention β€” blocks split by a '---' line (Get Accumulator (prompts)) or one line per track (captions). A single paragraph is shared by every take.
timesoptSTRINGGeneration time per take, ONE LINE EACH in track order β€” wire Siren (Music Sampler)'s 'time' output through a Set/Get Accumulator (texts) with a newline separator, exactly as Image Compare takes its times. Shown next to each take's name and in the Measurements tab, where a 'vs fastest' row turns it into the question you actually have: what did the extra stage cost. '12.34 s', '1m 30s', '890 ms' and '00:01:30' all parse.
lyricsoptSTRINGSong lyrics for the page's side panel. ONE block (no '---') = the same words for every take, which is the usual case when you are comparing settings. Split it with '---' lines when the takes were sung from different lyrics.
settings_dataoptGEN_SETTINGSStructured per-take settings from Generation Info Filter's 'settings_data' β€” the same output Image Compare takes. Becomes the page's Settings tab, with a 'differences only' view that shows exactly which setting moved between takes.
output_diroptSTRINGWhere the bundle folder is written. Empty = the ComfyUI output folder.

Outputs (2)

NameTypeDescription
html_pathSTRINGβ€”
urlSTRINGβ€”