HeartMuLa Lyrics Compliance
Did HeartMuLa Actually Sing What You Wrote? This Node Answers
- audio_input
- transcribed_lyrics
- similarity_score
- exact_match
- report_json
HeartMuLa will happily write you a song that sounds great and sings… something only vaguely resembling your lyrics. That's not a bug in this node pack - it's the model. Upstream HeartMuLa lowercases your text internally, and the README is blunt about it: exact lyric reproduction is "model-limited rather than guaranteed." So this pack doesn't pretend otherwise. Its answer is a measuring stick, and this node is the measuring stick: it transcribes whatever you generated and scores it against the lyrics you actually asked for.
Where it sits. Drop it after HeartMuLa Generate Music (or Generate From Spec) in the graph. It takes two things: audio_input - the AUDIO output of the generator - and expected_lyrics, the text you told it to sing. The clean move is to wire expected_lyrics straight from HeartMuLa Song Spec's lyrics output, so the check compares against the exact string that went into generation. That's exactly what the included workflow does, and it's why these nodes were designed to chain.
How it works. The node hands your audio to HeartTranscriptor-oss, a small transcription model from the official HeartMuLa line, driven through the same vendored heartlib runtime the generator uses. It writes the clip to a temp wav, transcribes it, then normalizes both strings - strips the [Verse]/[Chorus]/[Outro] section headers, lowercases, drops punctuation - before comparing. You get three verdicts at once:
exact_match(BOOLEAN) - strict string equality. Rare, and not a fair gate.similarity_score(FLOAT) - adifflib.SequenceMatcherratio, 0 to 1. 1.0 means the normalized strings are identical.report_json(STRING) - the full breakdown, including per-word recall so you can see which lines actually landed.
The output you'll actually read is transcribed_lyrics - hear what it heard, and you'll instantly understand why the score is what it is.
The Whisper-family knobs - temperature_tuple (default "0.0,0.1,0.2,0.4"), no_speech_threshold (0.4), logprob_threshold (-1) - tune how aggressive the decoder is. You almost never touch them. They're there because the transcriptor descends from Whisper-style decoding, and people who tune that stuff want the levers.
What to expect. Don't treat exact_match as pass/fail - SequenceMatcher ratio is string similarity, not musical quality. An 0.85 with a couple of swapped filler words is usually a win. If you want to auto-retry generation until the score clears a threshold, similarity_score is the number to gate on.
Install. This is part of the ComfyUI-MPC-HeartMuLa pack, so you install the whole pack once. Easiest is ComfyUI Manager → "Install via Git URL" → paste https://github.com/MPC2026/ComfyUI-MPC-HeartMuLa.git, or clone it manually:
cd /path/to/ComfyUI/custom_nodes
git clone https://github.com/MPC2026/ComfyUI-MPC-HeartMuLa.git
cd ComfyUI-MPC-HeartMuLa
python -m pip install -r requirements.txt
Restart ComfyUI and search "HeartMuLa" in the node picker. This node also needs the transcription model in ComfyUI/models/HeartMuLa:
cd /path/to/ComfyUI/models
hf download HeartMuLa/HeartTranscriptor-oss --local-dir ./HeartMuLa/HeartTranscriptor-oss
Gotchas. If the transcriptor folder is missing, the node raises with an explicit hint showing that exact hf download command - it's being helpful, not broken. runtime_profile defaults to auto, which is right on Apple Silicon (transcription on MPS, fallback to CPU). And remember: a low score doesn't mean your audio is bad - it means the model sang different words. That's the whole point of having this node instead of guessing by ear.
Inputs (8)
| Name | Type | Default | Description |
|---|---|---|---|
| audio_input | AUDIO | — | |
| expected_lyrics | STRING | [Verse] Write the lyrics you expect here | — |
| runtime_profile | COMBO | auto | 5 options: auto, apple_silicon_fast, apple_silicon_safe, cuda, cpu |
| auto_download_models | BOOLEAN | false | — |
| keep_model_loaded | BOOLEAN | true | — |
| temperature_tuple | STRING | 0.0,0.1,0.2,0.4 | — |
| no_speech_threshold | FLOAT | 0.400–1 | — |
| logprob_threshold | FLOAT | -1.0-5–5 | — |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| transcribed_lyrics | STRING | — |
| similarity_score | FLOAT | — |
| exact_match | BOOLEAN | — |
| report_json | STRING | — |