- clip
- abc
- report
- seconds
- seed_used
Song generators don't do deadlines. Ask YuE2 for a three-minute sea shanty and you'll get four minutes and twelve seconds of it, and there's no length field to argue with - length falls out of how many bars the model decided to write. SC YuE2 ABC Length Search is a drop-in replacement for the built-in YuE2 Generate ABC node that re-rolls until a score actually fits the length you wanted.
It's the one node in this pack I'd call genuinely clever, and the one with the best chance of eating your afternoon if you set it up wrong.
Why length is a search problem
YuE2 in ComfyUI is two stages: Generate ABC writes a text score in ABC notation, Generate Music renders audio from it. Length is determined at the score stage - bars times meter over tempo - so the only way to hit a target without editing the score is to try another seed and hope. That's a loop, and loops are what computers are for. The community's own framing of local music gen is that it's fast, cheap and slightly uncontrollable; this node is the control. Remember that the score stage is an LLM pass over your lyrics, so every attempt costs real tokens.
What it does under the hood
It calls ComfyUI's own YuE2GenerateABC node directly, once per attempt, incrementing the seed each time. Each returned score is parsed and measured with the same arithmetic the Song Length node uses, then compared against an acceptance window: your target plus upper_t_seconds above and lower_t_seconds below. Default target 3:30 with 10 seconds either side accepts 3:20 to 3:40.
Generated scores are cached for the session - keyed on everything that affects generation, up to 256 of them - so re-trying a seed you already tried is instant rather than a second full generation. Cancel is respected between attempts. If nothing fits and on_failure is set to stop workflow, it hands downstream nodes an execution blocker, so Generate Music never runs and you don't burn GPU rendering a song you've already rejected.
The inputs you'll actually touch
clip- the YuE2 model, from aCheckpointLoaderSimpleonyue2_3b_bf16.safetensors. Same as what Generate ABC takes.styleandlyrics- identical to the built-in node.styleis where genre, instrumentation, key and bpm go.target_minutes/target_seconds- the two-part target. That's it, no seconds-per-bar math required.upper_t_seconds/lower_t_seconds- tolerance. Setupper_t_secondsto 0 and the target becomes a hard ceiling, which is what you want for anything with a fixed slot.max_attempts- how many rolls. 0 means keep going until one fits, which is honest but can run a long time.max_tempo_change_percent- the interesting one. Instead of throwing away a near miss, it nudges the score's global tempo to pull it into range. Direction is automatic and the sign doesn't matter; 0 (the default) never touches tempo.on_failure-stop workfloworuse closest.mode,seed,new_seed_each_run-new_seed_each_rungives you a different song every queue; leave it off and re-queueing reuses the winning seed, because the node writes the winning seed back into the seed box.
The advanced knobs (max_abc_tokens, temperature, top_p, top_k, repetition_penalty, penalty_window) are the same sampling settings as the built-in node. max_abc_tokens at its default 8192 is effectively your hard length ceiling - very long songs need it raised.
Four outputs: abc (into Fix Meter, Song Length, or Generate Music), report (attempt-by-attempt log plus a section table), seconds, and seed_used.
Install
Recent ComfyUI required - this pack needs the V3 node API and the built-in YuE2 nodes, and the node will raise a clear "YuE2GenerateABC was not found" error if yours predates them. No Python packages.
cd ComfyUI/custom_nodes
git clone https://github.com/ShantyCircuit/ComfyUI-SC-YuE2-ABC-Helpers
Restart, then Ctrl+Shift+R. Manager search: SC YuE2 ABC Helpers. Everything lands under ShantyCircuit/YuE2.
Reading the node while it works
It has its own run button, so you can search for a score without rendering any audio - do that first, always. The log updates after every attempt, the node goes green on a fit and red on a miss (it resets to normal on the next run), and the "new search (random seed)" button picks a fresh starting seed. After a failed run the seed box advances past the seeds already tried, so the next queue continues the search instead of repeating it.
Where people get burned
Every attempt is a full score generation. A 5-attempt search means five songs' worth of tokens before a single second of audio exists, and with max_attempts at 0 plus a tight window you can spin for a long while on a wordy lyric. Start with a loose window, tighten once you know what the model tends to produce.
Two smaller things: if the text box and colours don't appear, the js folder didn't come along with __init__.py and/or the browser is serving cached scripts - hard refresh, then check the console. And if the chosen score has a meter glitch, the report will say so; that's a job for SC YuE2 ABC Fix Meter, not another search.
Inputs (19)
| Name | Type | Default | Description |
|---|---|---|---|
| clip | CLIP | — | |
| style | STRING | — | |
| lyrics | STRING | — | |
| seed | INT | 00–9007199254740991 | Seed the search starts from. After each run it is set to the seed of the chosen score, so queueing again reuses that score. Use the 'new search' button to start from a fresh seed. |
| new_seed_each_run | BOOLEAN | false | Pick a random starting seed every time the workflow is queued. Turn off to reuse the last winning score. |
| mode | COMBO | full | 2 options: full, melody |
| target_minutes | INT | 30–15 | Target length (minutes part). |
| target_seconds | INT | 300–59 | Target length (seconds part). |
| upper_t_seconds | FLOAT | 100–120 | How far over the target is still acceptable. 0 = the target is a hard ceiling. |
| lower_t_seconds | FLOAT | 100–120 | How far under the target is still acceptable. |
| max_attempts | INT | 50–1000 | Each attempt generates a new score with the next seed. 0 = keep trying until a score fits (press Cancel to stop). |
| max_tempo_change_percent | FLOAT | 0-30–30 | How much the tempo may change to bring a near miss toward the target. The direction is automatic: scores that are too long are sped up, too short ones are slowed down. The sign doesn't matter (10 and -10 both allow up to 10% either way). 0 = never change the tempo. |
| on_failure | COMBO | stop workflow | If no attempt fits: 'stop workflow' skips the nodes that use the abc output (no render); 'use closest' passes on the closest score anyway. |
| max_abc_tokens | INT | 81921–20000 | — |
| temperature | FLOAT | 0.700–5 | — |
| top_p | FLOAT | 0.900.01–1 | — |
| top_k | INT | 301–32768 | — |
| repetition_penalty | FLOAT | 1.0050.01–10 | — |
| penalty_window | INT | 1001–20000 | — |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| abc | STRING | — |
| report | STRING | — |
| seconds | FLOAT | — |
| seed_used | INT | — |