MiniMax H3 Skin Finish Frequency Split / 肤色纹理解耦 (Advanced EXP)
The frequency-split rebuild
- source_frames
- candidate_frames
- used_skin_mask
- audio
- frequency_split_candidate
- source
- selected
- audio
- effective_mask
- rejected_mask
- difference
- report_json
The classic complaint about AI skin isn't that it's too smooth - it's that smoothing flattens the detail that makes skin read as real. Too-smooth skin is the tell that's survived every generation of models. The Frequency Split node is T8's answer to that specific failure: instead of smearing a skin-finish candidate over the whole face, it rebuilds the result from two layers - the candidate's low-frequency tone correction, plus the source frame's existing high-frequency detail. Smooth the color, keep the pores.
How it works
It's deliberately non-generative, and the node description says so plainly: it cannot deblur, cannot create pores, cannot repair identity, and cannot decide a result is better. The math is the boring, reliable kind:
- A low-pass separation splits the candidate and source into tone/brightness (low-frequency) and detail (high-frequency) layers.
low_frequency_strength(default 1.0) blends the candidate's low-frequency correction in; 0 keeps the source's tone entirely.source_detail_gain(default 1.0) controls how much of the source's existing high-frequency detail comes back. 1.0 is neutral; it doesn't invent detail that isn't there.separation_radius_percent(default 1.0) is the low-pass radius as a percentage of the shorter image side, so the same node behaves sensibly across resolutions - capped bymaximum_radius_px(default 32) as a CPU-cost guard.
Then a bundle of conservative gates decides whether each frame is allowed to change at all: minimum/maximum mask area, a maximum_new_clipped_fraction that bounces frames back to source if too many pixels clip, and chunk_frames (default 4) for CPU batching.
The input/output shape
Required: source_frames (IMAGE), candidate_frames (IMAGE - the skin-finish result you're trying to rescue), and used_skin_mask (MASK - semantic skin, e.g. from the pack's ParseNet semantic-mask nodes). Optional audio passes through untouched.
Outputs: frequency_split_candidate (the recombined result), source and selected (the exact source, because by default source stays selected), audio, effective_mask, rejected_mask (which frames/regions the gates refused), difference, and report_json. The accept_candidate toggle (default false) is the entire point of this architecture: nothing is applied until a human flips it after review.
Why you'd reach for it
If you've got a skin-finish candidate that evened out the complexion but wiped out the texture - the "influencer default" look the photorealism lore keeps warning about - this node is the texture rescue. It's also a good citizen in a longer chain: it only touches pixels inside the mask, preserves everything outside it and all auxiliary channels, and keeps audio bound to the same object.
Installing it and gotchas
Part of the comfyui-minimax-h3-audio-T8 pack: ComfyUI Manager search "MiniMax H3 Audio T8", or clone https://github.com/T8mars/comfyui-minimax-h3-audio-T8.git into custom_nodes, update ComfyUI core first, restart. No extra model files - it's pure CPU image math.
Where people get burned: treating it as a beauty filter and cranking low_frequency_strength expecting more smoothing. It can't exceed what the candidate gives it, and over-aggressive settings trip its own clipping gates, silently sending frames back to source. And remember the contract: accept_candidate=false means the selected output is bit-exact source no matter how good the candidate looks. That's the pack's whole ethos - review first, ship second.
Inputs (14)
| Name | Type | Default | Description |
|---|---|---|---|
| source_frames | IMAGE | — | |
| candidate_frames | IMAGE | — | |
| used_skin_mask | MASK | — | |
| low_frequency_strength | FLOAT | 1.000–1 | 0 keeps the source low-frequency layer; 1 uses the candidate's low-frequency tone/brightness correction. |
| source_detail_gain | FLOAT | 1.000–1.25 | Gain for high-frequency detail already present in the source. 1.0 is neutral; this does not create missing detail. |
| separation_radius_percent | FLOAT | 1.000.1–5 | Low-pass radius as a percentage of the shorter image side. Resolution-relative scaling avoids one fixed pixel radius across sizes. |
| maximum_radius_px | INT | 321–128 | Hard CPU-cost cap for the calculated separation radius. |
| minimum_mask_area | FLOAT | 0.00010–0.25 | — |
| maximum_mask_area | FLOAT | 0.500.05–1 | — |
| maximum_new_clipped_fraction | FLOAT | 0.00050–0.25 | Frames exceeding this new clipping fraction return to source. |
| clipping_epsilon | FLOAT | 0.00390.0001–0.05 | — |
| chunk_frames | INT | 41–32 | — |
| accept_candidate | BOOLEAN | false | Source remains selected until the recombined candidate is reviewed. |
| audioopt | AUDIO | — |
Outputs (8)
| Name | Type | Description |
|---|---|---|
| frequency_split_candidate | IMAGE | — |
| source | IMAGE | — |
| selected | IMAGE | — |
| audio | AUDIO | — |
| effective_mask | MASK | — |
| rejected_mask | MASK | — |
| difference | IMAGE | — |
| report_json | STRING | — |