Fit Lyrics
The syllable bouncer between your words and the melody
- brief
- state
- lyrics
- prompt
- schema
- state
- report
Making a cover with new lyrics has one job that the music model can't do for you: the new words have to be singable on the notes that already exist. A writer model will happily hand you a lovely line with eleven syllables that has to land on four notes, and then everything downstream is a mess. Fit Lyrics is the node that measures the line against its phrase and sends it back.
You only need it on the new-lyrics cover path. A new song, a cover that keeps the original words, and an instrumental all pass through this node untouched - so if you see it in a template and you're not covering anything with fresh words, it's doing nothing, on purpose.
How it works
The node reads the score's Vocal phrases and treats each phrase's notes as a syllable budget: roughly one syllable per note, with one or two fewer than the notes being fine, since those get sung as a melisma (one syllable stretched across several notes - normal singing, not an error). Every line is checked against the notes of the phrase it sits on.
Lines that don't fit go back to the writer with their targets spelled out, and only those lines - the ones that already work aren't touched. That's capped at two rounds, which is why the pack chains three of these nodes with a writer between them: the first checks and complains, a writer answers, the second merges and re-checks, the third has last on and asks nobody anything - it just shortens what's still one or two syllables too long, mechanically (I am → I'm).
The lazy wiring is the part that earns its keep. When the lyrics already fit, the answer input is never resolved, so no writer call happens at all. Same story for reference_lyrics: it's only requested when the brief tells the cover to stay close to the original words, because meaning-matching is pointless otherwise.
Inputs and outputs
- lyrics - the words to fit: Parse Song Draft's output, or the previous Fit Lyrics round's.
- brief - Song Brief or Cover Brief. Only new cover lyrics get fitted; everything else skips.
- last - the switch that makes this node the final round: no more writer, just shorten.
- score - optional but essential in practice; its Vocal phrases are the targets.
- reference_lyrics - the source's transcribed words, when the brief keeps close to them.
- state and answer - the round-to-round handoff: what the previous node asked the writer, and the writer's reply.
Outputs: lyrics into the next round (or into the Song Sheet), prompt as the repair request for the writer - empty when the lyrics fit or when it's the last round - and schema to hold a Local LLM to the answer's exact format. state carries forward, and report gives you the honest ledger: which lines fit, what was asked, what changed.
Installing it
Same pack, same nothing-else-to-install. Plenio's requirements.txt is empty by design; the only optional pip line anywhere in it is faster-whisper, and that's for transcribing a cover's source vocals, not for this node.
cd ComfyUI/custom_nodes
git clone https://github.com/jplenio/Plenio-Music-Production-System
Or ComfyUI Manager → Custom Nodes Manager → Plenio Music Production System, or comfy node install comfyui-plenio-music. Restart ComfyUI and run 0 · System Check once. ComfyUI 0.37.0 or newer is required - this pack is built on the native YuE2, SheetSage2 and MiniMax nodes rather than reimplementing them.
When it misbehaves
If nothing gets fitted, check the cheap things first: it's a Cover Brief, it writes new lyrics, it isn't marked instrumental, and a score is connected. Any of those missing is a clean pass-through, not a failure.
The answer was cut off class of problem in a covering workflow usually comes from the transcription side rather than here - if the source's words weren't found, the brief's lyrics closeness and phrasing reference are asking for something that doesn't exist. Set lyrics closeness to 0 and the phrasing reference off, or trim the source to its sung part.
And don't expect this node to fail loudly. If the fitting code itself throws, the lyrics are used exactly as written - you'd get a melisma or a squeezed syllable where a line doesn't fit - with the reason in the report and the traceback in the console. The run keeps going, which is the right call for a graph that's already half an hour into rendering a song.
Inputs (7)
| Name | Type | Default | Description |
|---|---|---|---|
| lyrics | STRING | The lyrics: Parse Song Draft's, or the previous Fit Lyrics'. | |
| brief | PLENIO_BRIEF | Song Brief or Cover Brief: only new cover lyrics are fitted. | |
| last | BOOLEAN | false | The last round: asks the writer nothing more; shortens lines one or two syllables too long. |
| scoreopt | STRING | The final score: its Vocal phrases are the targets. | |
| reference_lyricsopt | STRING | The source's lyrics (Transcribe Lyrics), for the meaning when the brief keeps close to them; requested only then. | |
| stateopt | PLENIO_LYRICS_FIT | The previous Fit Lyrics' state: what it asked the writer. | |
| answeropt | STRING | The writer's answer to the previous Fit Lyrics' prompt; requested only when it asked. |
Outputs (5)
| Name | Type | Description |
|---|---|---|
| lyrics | STRING | The lyrics after this round. |
| prompt | STRING | The repair request for the writer (empty when the lyrics fit or in the last round). |
| schema | STRING | The answer's JSON schema, for Local LLM (the format is then exact). |
| state | PLENIO_LYRICS_FIT | For the next Fit Lyrics. |
| report | PLENIO_REPORT | Lines that fit, what was asked and changed. |