Nodes/Plenio Music Production System/Compose Sung Check (retired)
ComfyUI Node

Compose Sung Check (retired)

Compose Sung Check Builds the Question — It Doesn't Answer It

By jplenio·Created 2 months ago·Updated 4 days ago· 113
Compose Sung Check (retired)
    • prompt
    • schema
    ◄record—►
    ◄language►

    Music models don't sing your lyrics. They sing something near your lyrics: a repeated line, a swapped word, a phrase smeared into different words altogether. Plenio keeps both versions - the lyrics you wrote and, from the ASR listening to the finished song, the lyrics as sung. Compose Sung Check is the node that turns the gap between those two into a question for a language model.

    It calls nothing itself. If you're looking for a node that fixes the words, that's its sibling, Apply Sung Check. This one just writes the prompt.

    Why the gap needs a writer at all

    The ASR hears phonemes, not intentions. If the singer slurs "A detour" and the model hears "ready to", the lyrics as sung now contain a word your lyrics don't have at that position. That's not a transcription error you can fix with a better ASR - it's ambiguity that needs the rest of the line as context. A local language model is good at exactly this: given the written line and what was heard, guess which word was actually sung.

    So Compose Sung Check does the bookkeeping. It walks the sung lines against the written lyrics and brackets every word - or run of words - the lyrics don't have at that spot. Where the ASR heard a similar word instead of the lyric's one, it shows both: [doun | written: down]. Then it wraps the lyrics, the sung lines and the bracket marks into a prompt, in the song's language.

    The inputs

    record is the only required one, and it's a string, not a file object - the path to the .plenio.json release record that Export Release wrote. Wire Export Release's record output straight in. It's a forced input, so you can't type a path into a widget; it has to come from a node.

    language is optional and empty by default. Leave it empty and Plenio takes the language from the brief, and failing that guesses it from the lyrics. Set it when the song is in a language the guess would get wrong, because it matters later: the syllable counting that vets corrections is language-dependent.

    The outputs

    Two, and they're a pair.

    prompt is the question text - the lyrics, every sung line, the brackets. schema is the JSON schema of the expected answer, as a string. Feed prompt to Generate Text (Plenio's templates use the native text-generation node with Gemma 4) or to Local LLM, which also accepts schema and holds the model to it exactly. A GGUF writer that's told the shape of {"fixes": [{line, heard, word, sure}]} behaves a lot better than one that's asked to be creative about it.

    Here's the bit people miss: when there's nothing to check, prompt comes out empty - and Apply Sung Check then asks for no answer, so no writer runs at all. That's by design. A song with no sung lyrics (instrumental, subtitles off, or exported by an older Plenio that didn't keep them) produces an empty prompt in about a millisecond. If your check "does nothing", that's usually why, and it isn't broken.

    Installing it

    It ships with the pack:

    cd ComfyUI/custom_nodes
    git clone https://github.com/jplenio/Plenio-Music-Production-System
    

    Or Manager → Plenio Music Production System, then restart. Plenio pulls in no Python packages of its own - the whole pack's dependency list is empty. If you want a non-native writer, put a GGUF in ComfyUI's models/LLM folder and use the pack's Local LLM node, which spins up a llama.cpp server for the draft and shuts it down afterwards.

    In the templates you don't build this graph by hand: the block Plenio · Check Sung Words in the FINISH group already contains Compose, the writer branches and Apply, wired after Export Release, using the template's writer model. Open it only when you want to swap the writer.

    Where people get burned

    • Reaching for it before exporting. There's no record yet at that point in the grid, so there's nothing to read.
    • Expecting it to catch everything. It only examines words the lyrics don't already have at that position. A take that sings your lyrics perfectly produces nothing to fix - the ASR and the model have nothing to argue about.
    • A writer that ignores the schema. Local LLM respects it; a plain Generate Text run can wander. The answer is validated downstream anyway - Apply Sung Check throws away anything malformed or unsure - but a schema-aware writer wastes fewer tokens.
    CategoryPlenio/Lyrics

    Inputs (2)

    NameTypeDefaultDescription
    recordSTRINGThe release record Export Release wrote (its 'record' output).
    languageoptSTRINGNot used.

    Outputs (2)

    NameTypeDescription
    promptSTRINGEmpty: nothing is asked.
    schemaSTRINGThe answer's JSON schema, for Local LLM.