Lyrics Clean
The five seconds of tidying that saves an hour of bad timing
- lyrics
- title
If you generate a song locally, the lyrics almost never come out clean. A text model hands you Title: Hold The Line Tonight, a parenthetical subtitle underneath it, ** around everything, [VERSE 1 - x2] instead of [verse], and one line of cheerful commentary at the end. Paste that straight into a song model and it will happily try to sing the word "Title:".
Lyrics Clean is a text janitor. One input, two outputs, no cleverness - and it's the node that keeps the words being sung and the words being timed the same words.
What it actually does to the text
Hand it a mess and it runs a sanitiser over it. Concretely, in the pack's own code:
- Drops
Title:/Song Title:/Name:lines, and stash the value as the title. - Drops
Artist:,Album:,Subtitle:,Genre:,by,written bylines and---separators. - Unwraps markdown:
**[VERSE 1 - x2]**becomes[verse],**/__/backticks come off. - Canonicalises section tags.
[Chorus 2],[hook],[refrain]all become[chorus];[Verse 3]becomes[verse];[intro],[outro],[interlude],[instrumental],[solo]are kept as-is because the timing code treats them as non-singing sections. - Deletes any
[tag]it doesn't recognise, so a stray[prod. someone]doesn't become a sung line. - Strips old timing if you paste a finished
.lrc: the[00:12.40]cues and the enhanced-LRC<00:12.40>word tags both come out, and the[ti:]tag becomes the title. This is why pasting an existing.lrcand re-timing it doesn't stack two sets of timestamps. - Throws away YuE/Qwen's internal empty-vocal markers (
空歌词, "empty lyrics 2"), which are metadata about a section having no words rather than words.
If there's no Title: line - which is the normal case for words you typed yourself - the title is derived from the lyrics instead: it looks for the line you repeated most, prefers one that sat in a chorus, trims it to six words, and cuts trailing filler (oh, yeah, la) and dangling prepositions. That's how a song ends up named "No Pineapples In My Pizza" rather than "Generated Song".
Inputs and outputs
The only input is text, a multiline box. Paste lyrics, or wire a text generator into it - the bundled yue2_song_to_lrc_qwen3.json workflow feeds a local Qwen3-VL straight in.
Two outputs, and the wiring is the point:
lyrics→ goes to two places: the song model's lyrics input (Compose, or your MiniMax/YuE node) and into Lyrics to LRC. One string, two consumers, so the sung words and the timed words physically cannot drift apart. This is the single most important habit in the pack.title→ Song Filename'stitleinput, which turns it into a filename prefix.
Install
ComfyUI Manager → search ComfyUI-SongLRC → install → restart. Or by hand:
cd ComfyUI/custom_nodes
git clone https://github.com/TheAwaken1/ComfyUI-SongLRC
pip install -r ComfyUI-SongLRC/requirements.txt
That's numpy and soundfile, nothing else. WhisperX is optional and only matters for the timing node, not this one.
Where it bites
It is lossy on purpose, so it will occasionally eat something you wanted. A line in brackets that isn't a section name goes; so does a one-word line like "Ow" (under two characters is dropped). If the lyrics matter to you, keep the raw text in a Note or a text-file save node upstream so you can diff.
The derived title is a guess. If the hook is "la la la", your file is called La La. Set title on Song Filename by hand when you care about the filename, and leave the derivation for the lazy days.
Inputs (1)
| Name | Type | Default | Description |
|---|---|---|---|
| text | STRING | Paste lyrics here, or connect a text generator. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| lyrics | STRING | — |
| title | STRING | — |