Portrait Master: Base Character
The Portrait Master node that writes the 'who is this person' half of your prompt
- text_out
"Portrait Master: Base Character" is the node most people install the whole pack for. It's the big one - the monolith of demographics and facial features that turns "generate a portrait" into "generate a 47-year-old half-Italian woman, hourglass body, amber eyes, wavy chestnut hair, amused expression." If the pack's other nodes are the garnish, this is the meal.
In a standard workflow it sits first: you set the person here, hand its text_out to the next Portrait Master node (Skin Details, then Style & Pose), and finally into a CLIPTextEncode. Because these nodes chain - each accepts the previous one's text_in - you can build a character across all five and keep the person consistent while you iterate on style.
How it works
Like every node in the pack it's a prompt-string builder, not a model. Each dropdown and slider contributes a chunk of weighted tag text, everything is joined with commas, lowercased, and returned as a single STRING. The interesting mechanics:
- The core demographic block - gender, age, nationality, androgyny, "ugly" - gets wrapped together in one
(...:1.15)group, so it reads as a unit to the text encoder. - Nationality mixing emits the
[nationality_1:nationality_2:mix_value]syntax, like[Italian:Moroccan:0.6]. That syntax is not native ComfyUI - it needs the ComfyUI Prompt Control extension installed to be interpreted. Without it, the bracket token goes into your prompt as literal text. The README calls this feature experimental, and it is. - Weights are the on/off switch. Every slider that has a weight companion (
shot_weight,body_type_weight,face_shape_weight, …) only contributes to the prompt when the weight is above 0. Set a field to-and it's skipped; leave the weight at 0 and it's skipped anyway.
The inputs that matter
There are roughly fifty fields here, and you will not touch most of them. Start with these:
shot- head portrait, close-up, full body, and so on. Sets the framing.gender,age,nationality_1/nationality_2/nationality_mix- the person's identity core.hair_style/hair_color/hair_length- 119 styles, 23 colors. Big visible lever.facial_expression- 34 expressions with a weight. This plusshotis usually enough to get a recognizable person.body_type- 36 builds. Note it appends "body" to whatever you pick.
Leave the micro-features - cheekbones, jawline, nose size, face balance, face harmony - alone at first. They exist for when you're chasing a very specific face and the model keeps drifting; stacking them all at once produces a bloated prompt, which is the pack's other famous failure mode. The community's been calling these workflows "majorly bloated" since 2023, and it's earned.
Installing it
Base Character ships inside comfyui-portrait-master, so you install the whole pack once:
cd ComfyUI/custom_nodes
git clone https://github.com/florestefano1975/comfyui-portrait-master
Then restart ComfyUI. Or install via ComfyUI Manager (search "Portrait Master", author florestefano1975). No dependencies, no model downloads - it's Python reading dropdown lists from text files.
Common issues
- Loading an old workflow PNG scrambles the dropdowns. The pack was restructured into five modules in v3.x, and a workflow saved against an older version can load with values that aren't in the current lists anymore - the community hit "Red" face shape and "Amused" body type after updates. Re-set the fields manually.
- The output is lowercased - including your
text_in. Don't bother typing proper nouns with capitals into the input; they'll come out lowercase. - Your prompt is too long and the model drifts. This is real: on SDXL-lineage CLIP encoders long tag dumps dilute attention. Use
-to drop fields you don't need rather than piling everything on. - Nationality mixing does nothing visible. Check that ComfyUI Prompt Control is installed; otherwise the
[a:b:0.5]token passes through as text.
Inputs (56)
| Name | Type | Default | Description |
|---|---|---|---|
| shot | COMBO | - | 10 options: -, random 🎲, Close-up, Face, Full body, Full-length portrait, +4 |
| shot_weight | FLOAT | 1.000–2 | — |
| gender | COMBO | - | 4 options: -, random 🎲, Man, Woman |
| androgynous | FLOAT | 0.000–2 | — |
| ugly | FLOAT | 0.000–2 | — |
| ordinary_face | FLOAT | 0.000–2 | — |
| age | COMBO | - | 39 options: -, random 🎲, 18, 20, 22, 24, +33 |
| nationality_1 | COMBO | - | 194 options: -, random 🎲, Afghan, Albanian, Algerian, Andorran, +188 |
| nationality_2 | COMBO | - | 194 options: -, random 🎲, Afghan, Albanian, Algerian, Andorran, +188 |
| nationality_mix | FLOAT | 0.500–1 | — |
| body_type | COMBO | - | 36 options: -, random 🎲, Beefy, Buff, Buxom, Chubby, +30 |
| body_type_weight | FLOAT | 1.000–2 | — |
| breast_size | COMBO | - | 7 options: -, random 🎲, flat, huge, large, medium, +1 |
| breast_size_weight | FLOAT | 1.000–2 | — |
| butt_size | COMBO | - | 7 options: -, random 🎲, athletic, large, medium, skinny, +1 |
| butt_size_weight | FLOAT | 1.000–2 | — |
| eyes_color | COMBO | - | 12 options: -, random 🎲, Albino, Amber, Blue, Brown, +6 |
| eyes_shape | COMBO | - | 14 options: -, random 🎲, Almond Eyes Shape, Asian Eyes Shape, Close-Set Eyes Shape, Deep Set Eyes Shape, +8 |
| eyebrows_color | COMBO | - | 28 options: -, random 🎲, auburn, black, blonde, brown, +22 |
| eyebrows_shape | COMBO | - | 23 options: -, random 🎲, angular, angular thick, angular thin, arched, +17 |
| eyebrows_thickness | COMBO | - | 13 options: -, random 🎲, bold, defined, dense, medium, +7 |
| eyebrows_weight | FLOAT | 1.000–2 | — |
| lips_color | COMBO | - | 17 options: -, random 🎲, Berry Lips, Black Lips, Blue Lips, Brown Lips, +11 |
| lips_shape | COMBO | - | 23 options: -, random 🎲, Biting Lips, Bow-shaped Lips, Closed Lips, Cupid's Bow Lips, +17 |
| facial_expression | COMBO | - | 34 options: -, random 🎲, Amused, Angry, Anxious, Bored, +28 |
| facial_expression_weight | FLOAT | 1.000–2 | — |
| face_shape | COMBO | - | 25 options: -, random 🎲, Circle, Diamond, Heart, Heart with Pointed Chin, +19 |
| face_shape_weight | FLOAT | 1.000–2 | — |
| facial_asymmetry | FLOAT | 0.000–2 | — |
| hair_style | COMBO | - | 119 options: -, random 🎲, A-line bob, Afro, Asymmetrical, Balayage, +113 |
| hair_color | COMBO | - | 23 options: -, random 🎲, Auburn, Black, Blonde, Burgundy, +17 |
| hair_length | COMBO | - | 5 options: -, random 🎲, Long, Medium, Short |
| disheveled | FLOAT | 0.000–2 | — |
| beard | COMBO | - | 22 options: -, random 🎲, Anchor Beard, Balbo Beard, Chevron Mustache, Chinstrap Beard, +16 |
| beard_color | COMBO | - | 23 options: -, random 🎲, Auburn, Black, Blonde, Burgundy, +17 |
| cheekbones | COMBO | - | 28 options: -, random 🎲, angular, angular, arched, asymmetrical, +22 |
| cheekbones_weight | FLOAT | 1.000–2 | — |
| jawline | COMBO | - | 36 options: -, random 🎲, angular, angular, asymmetrical, asymmetrical, +30 |
| jawline_weight | FLOAT | 1.000–2 | — |
| nose_shape | COMBO | - | 27 options: -, random 🎲, angular, aquiline, arched, broad, +21 |
| nose_size | COMBO | - | 36 options: -, random 🎲, angular, angular, arched, broad, +30 |
| neck | COMBO | - | 40 options: -, random 🎲, angular, angular, arched, arched, +34 |
| face_symmetry | COMBO | - | 10 options: -, random 🎲, asymmetrical, balanced, disharmonious, disproportional, +4 |
| face_symmetry_weight | FLOAT | 1.000–2 | — |
| face_proportions | COMBO | - | 8 options: -, random 🎲, balanced, disharmonious, disproportional, harmonious, +2 |
| face_proportions_weight | FLOAT | 1.000–2 | — |
| face_balance | COMBO | - | 60 options: -, random 🎲, angular, angular, arched, arched, +54 |
| face_balance_weight | FLOAT | 1.000–2 | — |
| face_harmony | COMBO | - | 10 options: -, random 🎲, balanced, disharmonious, even, harmonious, +4 |
| face_harmony_weight | FLOAT | 1.000–2 | — |
| active | BOOLEAN | true | — |
| load_preset | COMBO | 1 options: -- disabled -- | |
| save_preset_as | STRING | — | |
| save_preset | BOOLEAN | false | — |
| text_inopt | STRING | — | |
| seedopt | INT | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| text_out | STRING | — |