Nodes/comfyui-fvmtools/Music · Verlaengern 5 · Anhaengen
ComfyUI Node

Music · Verlaengern 5 · Anhaengen

Finding the seam — where the new part actually joins

By ping1979ping·Created 7 months ago·Updated 2 days ago· 2
Music · Verlaengern 5 · Anhaengen
  • rendered_audio
  • session_json
  • report
◄session_json—►
◄search_seconds30►
◄loudness_matchtrue►
◄part_json—►

Step 5 of 6 (Anhaengen), and the hardest half-second of the whole workflow. You have a render of "the end of the old song plus some new sections". You need it to join the old song at exactly the right sample. Get it wrong and you get a stutter, a doubled beat, or a chorus that starts a fifth of a second early.

This node does the measuring. It is also an output node, which is worth knowing: it always executes, even if nothing downstream consumes its outputs, so it can't be pruned away when you're doing an LLM-only dry run.

How it finds the cut

First it aligns score to audio on both sides. search_seconds - 30 by default, and the tooltip says that's practically always enough - is the maximum offset it will tolerate between where the score says a note starts and where the renderer actually played it. YuE2 has a lead-in, so this offset is normal, not a bug. The fit gives each side an offset, a tempo scale, and a contrast value, which is the confidence that the alignment is unique rather than accidental.

Then it looks for a cut inside the overlap. The candidates are bar lines roughly 8 seconds before the overlap ends - that region is where the previous part is already playing its own "ending", quieter and winding down, and you don't want that in the final song - and it scores them by how similar the two signals sound across the join, picking the best one. It refuses candidates that would leave less than 4 seconds of the previous part's new material, so you never get two cuts bunched together. Finally it refines the cut to the nearest eighth note, because bar-line alignment alone leaves a few milliseconds of phase error.

If the renderer didn't give you enough new material - it clipped early, which happens - the node raises instead of appending: YuE2 hat zu frueh aufgehoert: ... Nichts angehaengt - einfach nochmal queuen (neuer Seed). Nothing is corrupted; the session is untouched and you just run it again.

Loudness, and why it's not a slope

loudness_match is on by default and it's smarter than "normalise everything". It measures the typical level of each section type in the original - verses are usually quieter than choruses - and targets the new sections against the same type. Comparing against the overall song level instead is exactly the mistake the source comments describe measuring: a new verse came out 4.8 dB too loud because the song's median level is dominated by its choruses.

Gain is applied as a ramp: local level at the cut, gliding to the target over the overlap. No step at the seam, no drift over ten appended parts. If the computed gain hits the 0.5×/2.0× clamps you get a HINWEIS telling you to listen to the transition - that's a real warning, not noise.

What it writes, and what it tells you

Outputs are session_json (now pointing at the appended state) and report. Four things in that report are worth reading: the part index with the cut position and gain at the seam; the seam itself - which bar line, how many candidates were considered, the spectral difference at the chosen one; the fine adjustment in milliseconds plus grid-consistency figure; and the alignment for both sides - offset, tempo scale, uniqueness.

If either side's alignment uniqueness is below 3, you get a WARNUNG: Partitur-Ausrichtung unsicher (...) - Uebergang anhoeren. That means the node couldn't confidently line score up with audio - crowded arrangement, or a part that starts with silence - so it did its best guess. Listen to that join. If it's bad, letzten Teil entfernen on the Session node and append again with a different seed.

The optional inputs, and why they're lazy

part_json and rendered_audio are only evaluated when the session action is anhaengen. On an undo, reset or merge-only run the node returns Aktion '...': nichts angehaengt. without touching the renderer - so you can queue an undo without the song model firing up.

Install

ComfyUI Manager, search comfyui-fvmtools, or:

cd ComfyUI/custom_nodes
git clone https://github.com/ping1979ping/comfyui-FVMtools

Restart, find it under Add Node → FVMtools/music/extend. numpy only - plus the soundfile that ships with ComfyUI, since parts are written as 24-bit FLAC.

Common issues

"YuE2 hat zu frueh aufgehoert". The render ended before the new material did. Re-queue with a new seed; this is a renderer quirk, not a settings problem. Adding an extra section so there's slack also helps.

The join clicks or doubles. Check the report's cut candidate count: if it's 1, your overlap was too short to have options. Raise overlap_sections on the Plan node. If the timing warning fired, the seam is a guess.

A part sounds noticeably louder or quieter than its neighbours. Look at the gain values in the report. Once loudness_match has measured the source it stores those per-label levels in the session - good, but it does mean a weird original (a long quiet intro) skews the reference.

CategoryFVMtools/music/extend

Inputs (5)

NameTypeDefaultDescription
session_jsonSTRING—
search_secondsFLOAT302–120Maximaler Versatz zwischen Partitur und Rendering (Vorlauf von YuE2). 30 s reichen praktisch immer.
loudness_matchBOOLEANtrue—
part_jsonoptSTRING—
rendered_audiooptAUDIO—

Outputs (2)

NameTypeDescription
session_jsonSTRING—
reportSTRING—