Create H3 Ref Character From Folder
One folder in, reusable character out
- vae
- audio_vae
- character
- manifest_path
- decoded_image
- created_paths
Why you'd reach for it
Every other approach to character consistency pays the encoding cost on every run. IP-Adapter re-encodes the face, an edit model re-reads the reference image, a reference-to-video model re-encodes your clips at the head of each generation. H3 RefMod inverts that: encode once, save the latent encodings to disk, then load them forever without touching the VAE again.
Create H3 Ref Character From Folder is the "encode once" half. Point it at a directory of photos, clips and voice recordings, and it produces a character package - visual .safetensors, optional audio .safetensors, a .character.json manifest, and a thumbnail - that the rest of the suite can reuse.
How it works
The node walks folder (resolved and required to exist), sorts what it finds into images, videos and audio, and encodes each entry against the profiles you enabled. display_name is the human label, prompt_alias is the @tag you'll type in prompts, and descriptor is the one that ends up in the generated text - it describes the identity, not the folder ("a South Asian woman"), so write it that way. package_name controls the folder and filename; blank falls back to the display name, and existing packages are never overwritten.
profiles is a JSON blob the UI writes, holding three lists - picture, video and combined - each defaulting to a single 1024 short edge profile with Lanczos downsize and "Keep size" for smaller sources. Turn on more sizes only if you expect to use them: every enabled profile is encoded for every included source, so this is a straight multiply on creation time and disk. The tooltip on sample_frames is the honest one: 16 evenly spaced frames per video is a compact starting point, 0 uses every frame in the chosen range, and it is not FPS - timing still comes from the source, frames aren't repeated to fill it.
voice_duration_limit / maximum_total_voice_duration and the video equivalents (Limited/Unlimited, defaults 10s and 15s) cap how much recording gets packaged. source_ranges is JSON from the Edit source media panel where you exclude files and set recording ranges.
Outputs: character (the package, wire it to the picker or straight to generation), manifest_path, decoded_image (a decoded sample - this is your "did it work?" preview, and it's why the node is an output node), and created_paths (a string listing what got written; send it to a text node).
Combined profiles, and the budget rule
Combined video profiles build one shared canvas from the first selected visual's proportions, then encode pictures and clips into it independently - "Fit whole image" adds borders, "Crop to fill" eats edges. The package stores the compatible entries plus a recipe, so identical encodings can be shared between profiles rather than duplicated.
Token allowances are where you'll meet the model's limits. When a per-video allowance is exceeded, similar saved video samples are dropped first (compared within their own boundaries), then survivors are picked evenly. Pictures are reserved first and are never dropped or resized to fit - if pictures alone exceed the allowance, creation stops and tells you. The README is clear that a saved sample is a unit the video VAE produced, not a source frame, so dropping samples can change motion coverage. Reports distinguish original frames from retained samples.
Install
ComfyUI Manager → search WorkflowX Configurator, or:
cd ComfyUI/custom_nodes
git clone https://github.com/haroonaslam/WorkflowX-Configurator
cd WorkflowX-Configurator && pip install -r requirements.txt
Restart and hard-refresh. You need the full H3 visual VAE connected on vae (the suite checks it's really the MiniMax H3 video VAE and refuses otherwise), and audio_vae if the folder contains voice recordings. H3 support itself comes from ComfyUI, so keep your install current.
Where it goes wrong
A missing upscale model stops creation. If you pick a saved size that requires enlargement and select an upscale model that isn't installed, the run fails rather than falling back. The node's own note here is worth repeating: enlargement does not recover detail, and an upscale model can invent texture.
Old manifests need recreating. Earlier custom character manifests aren't migrated by the current release, and workflow settings aren't migrated either. Existing packages are never deleted or rewritten automatically, so a stale package just sits there.
VAE encoding and downscaling are still lossy. "Original size" means no intentional resizing, not mathematically lossless storage. And H3 remains responsible for appearance and voice - correct associations can't guarantee exact identity.
Inputs (15)
| Name | Type | Default | Description |
|---|---|---|---|
| folder | STRING | — | |
| display_name | STRING | My Character | — |
| package_name | STRING | Folder and filename. Blank uses Display name. Existing packages are never overwritten. | |
| prompt_alias | STRING | my_character | — |
| descriptor | STRING | Describe the identity, for example a South Asian woman. This description is used in the H3 prompt. | |
| description | STRING | — | |
| profiles | STRING | {"picture": [{"id": "1024", "name": "1024 short edge", "size": 1024, "enabled": true, "downsize": "Lanczos", "smaller": "Keep size", "model": "", "framing": "Fit whole image", "budget": 0}], "video": [{"id": "1024", "name": "1024 short edge", "size": 1024, "enabled": true, "downsize": "Lanczos", "smaller": "Keep size", "model": "", "framing": "Fit whole image", "budget": 0}], "combined": [{"id": "1024", "name": "1024 short edge", "size": 1024, "enabled": true, "downsize": "Lanczos", "smaller": "Pad to target", "model": "", "framing": "Fit whole image", "budget": 0}]} | — |
| sample_frames | INT | 160–100000 | Maximum source frames from EACH video. 16 evenly spaced frames is a compact starting point. 0 uses every frame in the chosen range; FPS is not changed. |
| voice_duration_limit | COMBO | 2 options: Unlimited, Limited | |
| maximum_total_voice_duration | FLOAT | 10.00 | — |
| video_duration_limit | COMBO | 2 options: Unlimited, Limited | |
| maximum_total_video_duration | FLOAT | 15.00 | — |
| source_ranges | STRING | [] | — |
| vaeopt | VAE | — | |
| audio_vaeopt | VAE | — |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| character | H3RC_CHARACTER | — |
| manifest_path | STRING | — |
| decoded_image | IMAGE | — |
| created_paths | STRING | — |