Nodes/ComfyUI-SongScribe/Lyrics Structure (SongScribe)
ComfyUI Node

Lyrics Structure (SongScribe)

The tag janitor your music model silently needs

By TheLocalLab·Created 2 months ago·Updated 20 days ago· 23
Lyrics Structure (SongScribe)
    • lyrics
    • report
    • section_count
    • has_warnings
    ◄lyrics►
    ◄normalise_tagstrue►
    ◄max_duration0►

    The failure mode nobody warns you about

    Here's the thing this node exists for. MiniMax treats the bracketed section tags in your lyrics as the only executable structural instruction it gets - the lyric text itself only conveys mood. A malformed tag therefore doesn't produce a slightly-off song. It silently drops a structural instruction from a render that takes minutes, and you find out by listening to the result and wondering why the chorus showed up twice.

    So: you have lyrics. Maybe you wrote them, maybe they came from a file someone else annotated, maybe the Song Analyzer pulled them out of an embedded tag or an .lrc sidecar. They probably say (chorus) or {hook} or Verse 2:. Lyrics Structure rewrites all of that into the shape the model expects and tells you what it couldn't understand.

    What it does to the text

    Two jobs.

    The normaliser walks the lyrics line by line and maps tags onto the canonical seven: [Intro], [Verse], [Pre-Chorus], [Chorus], [Bridge], [Instrumental], [Outro]. It handles bracketed forms - [Verse], (Chorus), {bridge} - and bare Word: lines, with a real alias table behind it: hook, refrain and chorus all land on Chorus; pre-chorus and build on Pre-Chorus; middle 8 on Bridge; breakdown, solo and interlude on Instrumental; coda, ending and end on Outro. Trailing numbers are ignored, so [Verse 2] becomes [Verse], which is what the model wants and is also the thing people get wrong by hand. Bare Word: lines are only rewritten if the word names a known section - otherwise a lyric line that happens to end in a colon stays exactly as you wrote it, which is the right amount of caution.

    The checker then reports. It counts the syllables (vowel groups, minus a silent trailing e), estimates sung length at roughly 3.2 syllables per second plus four seconds of instrumental air per section, and multiplies out a range - 0.65× to 1.6× around the midpoint. If max_duration is set, it compares that range against it and warns you either way: lyrics that need longer than the target will get cut or rushed, and lyrics filling far less than the target mean long instrumental stretches.

    It also flags structural things worth a look before you burn a render: no section tags at all, a first section that isn't [Intro], a last section that isn't [Outro], and any tag it didn't recognise - left untouched rather than guessed at.

    The inputs that matter

    lyrics is a multiline string; wire it from Song Analyzer's lyrics output or paste it in. normalise_tags (on by default) is the switch between "fix my formatting" and "just tell me what's wrong" - with it off you get the original text back and only the report and warnings.

    max_duration is the one to set deliberately. It's a FLOAT defaulting to 0, which disables the fit check entirely, and it caps at 600 seconds. Wire Song Analyzer's duration output straight into it and the check compares your lyrics against the reference track's real length, which is the honest comparison when you're re-rendering a cover-ish version of something. Note max_duration here is about lyric fit, not the model's own duration cap.

    Outputs are lyrics (normalised, or verbatim if you turned normalisation off), report (human-readable structure and fit summary - send it to a text preview node, it's the useful one), section_count (INT, how many tags were found), and has_warnings (BOOLEAN). has_warnings is the interesting one for big graphs: it's a plain boolean you can wire into a switch or a note, so a graph can refuse to spend fifteen minutes on a song whose lyrics are tagged as four verses and no chorus.

    Install

    Shared with the rest of the pack. ComfyUI Manager → search SongScribe, or:

    cd ComfyUI/custom_nodes
    git clone https://github.com/TheLocalLab/ComfyUI-SongScribe
    python_embeded/python.exe -m pip install librosa mutagen pyyaml
    

    Restart. This node needs no model download at all - the tag rewriting and syllable estimate are pure Python, so it's instant and free to leave in every workflow.

    Traps and honest limits

    The duration estimate is an estimate. Real delivery varies enormously - a slow ballad and a rap verse with the same syllable count are not the same length - which is exactly why the node reports a range and why has_warnings is a flag and not a verdict. Treat it as "you're probably in trouble" for a target that's a third of the estimate, not as a stopwatch.

    Unknown tags are reported, not fixed. If your lyrics use a tag the alias table doesn't know, it stays in the text and shows up in the warning list - which means a render can still quietly ignore it. Scan the report output the first time you run new lyrics through; after that, it's stable.

    And one thing worth internalising about the whole music side of ComfyUI: this layer is bolted on rather than designed in, and the tooling reflects it. Nodes like this one exist because command-line music models don't validate your prompt, they just do something with it. Getting the structure right before the render is cheaper than after.

    CategorySongScribe

    Inputs (3)

    NameTypeDefaultDescription
    lyricsSTRING—
    normalise_tagsBOOLEANtrueRewrite (Chorus), {hook}, 'Verse 2:' etc into the [Chorus] / [Verse] form MiniMax expects.
    max_durationoptFLOAT00–600Target song length to check the lyrics against. 0 disables the fit check.

    Outputs (4)

    NameTypeDescription
    lyricsSTRINGLyrics with section tags normalised.
    reportSTRINGHuman-readable structure and fit report.
    section_countINTNumber of section tags found.
    has_warningsBOOLEANTrue if anything would likely degrade the render.