Character Card
One place to describe a character — for the prompt, the lyrics, and the music
- card
- voice
Character consistency is one of those problems people over-engineer. The practical version: you want the same character in every image this session, so the prompt-writing LLM needs to know what "Vasya" looks like - once, in one place, without you re-describing him every run. Character Card is that one place.
You fill the fields you care about and it emits a tidy Markdown block - a heading with the name, a bullet per filled attribute, free-form notes at the end. Empty fields are skipped, so you only describe what matters. That block is meant to be gathered by Context Collector and fed into an LLM's context input, and then a request that just says "Vasya and Kolya drink tea in a cafe" comes back expanded with each character's actual looks.
The inputs that matter:
name- becomes the card heading and the name the LLM binds attributes to.- The appearance fields:
gender,age,ethnicity,eye_color,hair_color,hair_style,build,height,outfit,features- all optional, all skipped when empty. notes- free-form anything-else (personality, accessories, scars), as a- Notes:line.save_preset_as+tags- type a name and run to save the card to the pack's Card Presets library. It saves at run time, so it captures whatever's filled in whether you typed it or wired it in from outside (e.g. a photo description). Re-runs overwrite the same name.
The outputs:
card- the Markdown block. Wire into Context Collector.voice- a separate typed output for the music path (only relevant if you use the pack's Siren music nodes; ignore it otherwise).
The voice output is the interesting design decision. A band member is one card: looks go to the cover-art prompt, voice_tags (a music-caption fragment like "male lead vocal, raspy baritone, close-mic") goes to Siren Cast for the song's caption, and the same card tells the lyrics LLM who it's writing for. Keeping it a separate typed output - rather than part of the Markdown - is deliberate: pouring "brown eyes, navy dress" into a music-production caption just dilutes the part that decides how the vocal sounds.
Install via ComfyUI Manager (search "Kinburg-Nodes") or:
cd ComfyUI/custom_nodes
git clone https://github.com/Kinburg/Kinburg-Nodes
then restart. This node itself is pure string assembly - no model, no dependency - but it's built to feed the pack's Local LLM (GGUF) nodes, which do need llama-cpp-python (installed automatically by install.py) and a GGUF model of your own in ComfyUI/models/llm. The pack is a one-author personal collection with surprisingly thorough docs and a 1395-check test suite.
One trap to dodge: the card doesn't enforce anything. It's reference text, not a binding contract - the LLM still decides how faithfully it weaves the attributes in, and the diffusion model has its own ceiling on multi-character attribute binding. Fill the card, feed the context, and treat the result as "much better than nothing," which it reliably is.
Inputs (16)
| Name | Type | Default | Description |
|---|---|---|---|
| name | STRING | Character name / label — becomes the card heading and the name the LLM binds attributes to. | |
| gender | STRING | Gender. Leave empty to omit this line from the card. | |
| age | STRING | Age. Leave empty to omit this line from the card. | |
| ethnicity | STRING | Ethnicity / skin. Leave empty to omit this line from the card. | |
| eye_color | STRING | Eyes. Leave empty to omit this line from the card. | |
| hair_color | STRING | Hair color. Leave empty to omit this line from the card. | |
| hair_style | STRING | Hair style. Leave empty to omit this line from the card. | |
| build | STRING | Build. Leave empty to omit this line from the card. | |
| height | STRING | Height. Leave empty to omit this line from the card. | |
| outfit | STRING | Outfit / clothing. Leave empty to omit this line from the card. | |
| features | STRING | Distinctive features. Leave empty to omit this line from the card. | |
| voice_tags | STRING | How this member's VOICE sounds, as a music caption fragment — this is the text Siren Cast pastes onto the song's caption for the sections they sing. Write production language, not looks: 'male lead vocal, raspy baritone, close-mic, slight grit on the high notes'. Keep it to the voice and its delivery; genre, tempo and mix belong in Siren Cast's own 'tags', which every section shares. Empty = this card has no voice (a character who doesn't sing) and Siren Cast will say so if a plan row asks for them. | |
| voice_notes | STRING | The voice in prose, for the LLM that writes the lyrics — range, habits, what they never do ('avoids anything above E4, tends to talk-sing the verses'). Goes into the card as a '- Voice:' line and NEVER into the AceStep caption, so it can be as long as you like. | |
| notes | STRING | Anything else (personality, accessories, scars…). Added as a '- Notes:' line at the end of the card. | |
| save_preset_as | STRING | Type a name to save this card to the Card Presets library on the next run. Works whether the fields are typed OR wired in from outside (saved at run time). Empty = don't save. (Re-runs overwrite the same name.) | |
| tags | STRING | Comma-separated tags for filtering the library in Card Presets (e.g. 'heroes, medieval'). Only used when save_preset_as is set. Empty = leave existing tags untouched. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| card | STRING | — |
| voice | KINBURG_VOICE | — |