Nodes/ComfyUI-LyricForge/LyricForge ACE-Step Generator
ComfyUI Node

LyricForge ACE-Step Generator

Caption, lyrics, BPM and key from one keyword box

By knishika62·Created 7 months ago·Updated 7 months ago· 13
LyricForge ACE-Step Generator
    • caption
    • lyrics
    • bpm
    • key_scale
    keywordsj-pop 冬の歌 女性ボーカル 雪 カフェ
    api_endpointhttp://localhost:1234/v1/chat/completions
    api_keylm-studio
    modellocal-model
    languageJapanese
    song_structureStandard
    temperature0.7

    ACE-Step (ByteDance's open, Apache-2.0 text-to-music diffusion model) doesn't want comma-separated tags the way HeartMuLa does - it wants a natural-language caption, plus a lyric line, a BPM, and a key/scale, and it wants them precise. That's a lot of stuff to write by hand before you've generated a single second of audio. The LyricForge ACE-Step Generator is the sibling node that does the whole description job in one shot: type a keyword sentence, get back a caption, full lyrics, a BPM integer, and a key/scale string. It's not a music model either - it's the text-prep layer that sits between you and the ACE-Step text encoder.

    How it works: identical plumbing to its HeartMuLa sibling - build a system prompt, POST to an OpenAI-compatible /v1/chat/completions endpoint, parse the reply. The difference is what the prompt demands. For ACE-Step it specifies the caption recipe (genre, mood, instruments, sound texture, era reference, vocal character), then BPM ranges by tempo feel (ballad 60–80, up-tempo 110–140, fast dance 140–180) and a mood-to-key mapping (bright/positive → major, sad/dark → minor). The parser then pulls out CAPTION, BPM (coerced to an int), KEY_SCALE (normalized to things like A minor or F# minor), and LYRICS with ACE-Step's structure tags - including its own sections like [Build], [Drop] and [Breakdown], not just [Verse 1] / [Chorus].

    The inputs are the shared pack set: keywords (multiline), plus api_endpoint / api_key / model - which default to LM Studio values (http://localhost:1234, key lm-studio, model local-model). Change all three if you're not running LM Studio; the endpoint gets /v1/chat/completions appended automatically. Optional: language (Japanese/English/Chinese), song_structure (Standard/Short/Extended), temperature (0–2, default 0.7).

    The outputs and the wiring are where this node earns its keep - four of them:

    • caption → the caption input on TextEncodeAceStepAudio1.5
    • lyrics → the lyrics input on the same encoder
    • bpm (an actual INT) → the bpm input
    • key_scalehere's the gotcha the README is upfront about: ACE-Step's key/scale input is a COMBO (dropdown), so you cannot wire a string into it. You read the value and select it by hand in the ACE-Step node. Annoying, but it's a one-time per-run copy, and the value's right there on the node.

    From there the flow is standard: TextEncodeAceStepAudio1.5 → KSampler → VAEDecodeAudio → Save Audio.

    Install: same as the rest of the pack -

    cd ComfyUI/custom_nodes/
    git clone https://github.com/knishika62/ComfyUI-LyricForge.git
    cd ComfyUI-LyricForge
    pip install -r requirements.txt
    

    restart, and you're done. The only dependency is requests. The heavy lifting is all elsewhere: you still need the ACE-Step 1.5 checkpoint (multi-GB) and its ComfyUI node, which this pack does not install. The README documents this node's caption/BPM/key behavior in detail in ACESTEP_ANALYSIS.md if you want the spec.

    Reality check on the BPM and key: they're guesses - the LLM infers them from your keywords and mood, it doesn't analyze anything. They're a genuinely good starting point for a caption-driven workflow, but treat them as suggestions, not the finished arrangement; you'll often nudge the BPM yourself after hearing the first take. Same shared caveats as the sibling node: the API call is synchronous with a 120s timeout (UI freezes while it thinks - normal), and any failure surfaces as literal Error: ... strings in the outputs with a fallback of 120 BPM / C major. If that's what you see, the console is telling you exactly which call failed. And the quality ceiling is your LLM - a weak local model produces generic captions, so don't blame the node when a 3B model phones it in.

    CategoryLyricForge

    Inputs (7)

    NameTypeDefaultDescription
    keywordsSTRINGj-pop 冬の歌 女性ボーカル 雪 カフェ
    api_endpointSTRINGhttp://localhost:1234/v1/chat/completions
    api_keySTRINGlm-studio
    modelSTRINGlocal-model
    languageoptCOMBOJapanese3 options: Japanese, English, Chinese
    song_structureoptCOMBOStandard3 options: Standard, Short, Extended
    temperatureoptFLOAT0.70–2

    Outputs (4)

    NameTypeDescription
    captionSTRING
    lyricsSTRING
    bpmINT
    key_scaleSTRING