Universal 模型动态加载器
The Universal dynamic model loader
- model
- clip
- vae
- audio_vae
Every MiniMax H3 tutorial starts the same way: a diffusion-model loader, a separate CLIP loader, a VAE loader, and then a second VAE loader for the audio VAE, plus a LoRA loader if you're being fancy. Four to six nodes, six sets of dropdowns, all doing one thing.
UniversalH3ModelLoader ("Universal 模型动态加载器") collapses that into one node with four outputs. No, the name doesn't mean it does anything clever with formats - it means it loads whatever you point it at, from one place.
The one input is a JSON blob you never type
The schema is almost rude: a single loader_config STRING, multiline, defaulting to {}. That's the entire input surface.
You don't write that JSON. The pack ships a front-end panel (web/universal_model_loader.js) that renders five sections inside the node - 主模型 (Model), LoRA 插件, CLIP 文本编码器, 视频 VAE, 音频 VAE (Audio) - each with an "+ Add" button and a file row. Pick files there and the panel serialises the whole thing into loader_config:
{"models": [{"name": "...", "weight_dtype": "default"}],
"loras": [{"name": "...", "strength": 1.0}],
"clips": [{"name": "...", "clip_type": "minimax"}],
"vaes": [{"name": "..."}],
"audio_vaes": [{"name": "..."}]}
Then execute() reads it back and does the ordinary ComfyUI work in order. For the main model it tries diffusion_models first via comfy.sd.load_diffusion_model, and falls back to checkpoints through load_checkpoint_guess_config (which conveniently also yields a CLIP and a VAE). LoRAs are loaded to a state dict first, then applied with load_lora_for_models. The text encoder goes through comfy.sd.load_clip with clip_type defaulting to minimax, and both VAEs are built with comfy.sd.VAE(...) from the vae folder.
That's it. It's the same four calls four nodes would make; you're buying layout, not magic.
What you actually get out
Four outputs, all standard ComfyUI types, so they wire anywhere:
model- the diffusion model, after any LoRAsclip- your text encodervae- the video VAEaudio_vae- the audio VAE, which is the thing H3 needs and which half the workflows in the wild forget
The tooltips are sparse on purpose, so here's the judgement call: for H3, fill the model, the text encoder and both VAEs. The downstream director nodes raise their own error if the audio VAE is missing, because H3 generates picture and audio in the same pass - a silent video pipeline isn't what you loaded this for.
Install
Manager, search "Universal Prompt Optimizer". Or:
cd ComfyUI/custom_nodes
git clone https://github.com/aihaipan/ComfyUI-Universal_Prompt_Optimizer.git
Restart. The pack declares exactly one Python dependency - aiohttp, used by its prompt-optimizer routes - and that already ships with ComfyUI, so there's no pip install step. Needs Python 3.10+ and a ComfyUI recent enough to have the comfy_api.latest node API, which this whole pack is written against.
Files go where ComfyUI expects them: diffusion models in models/diffusion_models, text encoders in models/text_encoders (the loader also tries models/clip), VAEs in models/vae, LoRAs in models/loras. Nothing is downloaded for you. H3 itself is a ~42.5GB, 33B omni-modal model - and mind the licence, which excludes the EU, UK, Korea and the US from its applicable territory.
The traps, all of them in the source
Only the last entry counts for CLIP and VAEs. The code reads clips[-1], vaes[-1], audio_vaes[-1]. Add two video VAEs and the second one silently wins; add two text encoders and you get the bottom row. Multi-model rows behave similarly - the loop finishes on the last one. One row per slot, and the panel stops being mysterious.
The audio VAE must live in models/vae. It's looked up in the vae folder only. If you've filed it under an audio-specific folder because the name says audio, the node won't find it and you'll get 「音频 VAE 未找到」.
LoRA strength is one number for both halves. strength is passed to model and clip at the same value. Fine for most H3 LoRAs, but you can't dial the text side down here.
Dropdown contents come from your own ComfyUI. weight_dtype is read off UNETLoader's options and clip_type off CLIPLoader's. If minimax isn't in the type list, your ComfyUI is older than the model and no amount of restarting will invent it.
An empty loader_config is an empty loader. The three failure messages are the author's own and refreshingly direct: 「必须至少加载一个主模型!」, 「视频 VAE 未找到,请在"视频 VAE"区点击 +Add 并选择一个文件!」, and the same for audio. If the node's panel renders red text about UI 渲染失败 instead, the front-end threw - F12, read the console, and note that the backend half would still work if you fed it valid JSON by hand.
Don't hand-edit the JSON unless you mean it. It's a serialisation of panel state, not a documented API. A malformed blob is caught and treated as {}, which turns into a confusing "no model" error several nodes downstream.
Compare it to chaining loaders and you're trading per-widget visibility for one panel. For a four-model H3 setup that's a good trade. For an SDXL checkpoint with one LoRA, the core nodes are already fine and I wouldn't bother.
Inputs (1)
| Name | Type | Default | Description |
|---|---|---|---|
| loader_config | STRING | {} | — |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| model | MODEL | — |
| clip | CLIP | — |
| vae | VAE | — |
| audio_vae | VAE | — |