Nodes/MiniMax H3 Audio T8/MiniMax H3 Face Refine Quality Gate / 候选质量门 (Advanced)
ComfyUI Node

MiniMax H3 Face Refine Quality Gate / 候选质量门 (Advanced)

An automatic 'don't ship the worse face' check before export

By T8mars·Created 20 days ago·Updated a day ago· 807
MiniMax H3 Face Refine Quality Gate / 候选质量门 (Advanced)
  • base_frames
  • candidate_frames
  • changed_mask
  • face_plan
  • safe_candidate_frames
  • accepted_change_mask
  • rejected_frame_mask
  • accepted_frame_count
  • rejected_frame_count
  • report_json
min_structure_ssim0.82
min_sharpness_ratio1.02
max_sharpness_ratio2.00
max_face_mean_abs_delta0.060
max_residual_temporal_jitter0.050
minimum_accept_run3
edge_fade_frames2

This is the node that stops you from exporting a face that got worse. Face refine is not a guaranteed win - the second pass can melt a face, swap identity, or introduce flicker, and if you're batch-processing a video you might not notice until it's rendered. The Quality Gate sits between your stitch candidate and your export, and it rejects obvious regressions frame-by-frame using conservative proxy thresholds. Rejected frames quietly return to the original source. It's not AI taste - it's a tripwire for the failure modes you can actually measure.

What it measures, per frame: source-relative structure (SSIM), the face-region change magnitude, measured sharpness, and temporal residual (how much the candidate jumps relative to its neighbors). Every one of those must pass for the frame to be accepted, and accepted frames must come in a continuous run of at least minimum_accept_run (3) - a single good frame surrounded by rejects doesn't count, because isolated good frames are where flicker lives. edge_fade_frames (2) feathers the boundary between accepted and rejected runs so the output doesn't hard-cut.

Inputs: base_frames, candidate_frames, changed_mask (so it only scores what actually changed), and face_plan.

The dials you'd actually move:

  • min_structure_ssim (0.82) - if the candidate's structure diverges too far from source, it's probably a different face. Lower = more permissive.
  • min_sharpness_ratio (1.02) / max_sharpness_ratio (2) - the candidate must be sharper than source, but not suspiciously sharper (oversharpening is a refine artifact).
  • max_face_mean_abs_delta (0.06) - normalized face-region change cap. This is your identity guard.
  • max_residual_temporal_jitter (0.05) - temporal consistency guard.

Outputs: safe_candidate_frames (the mixture: accepted refined frames + source where rejected), accepted_change_mask, rejected_frame_mask, accepted_frame_count, rejected_frame_count, and report_json so you can see why frames were rejected.

Now the honesty clause, and it's important: passing this gate is not identity proof or quality proof. These are conservative proxy thresholds. The description says it plainly - the result still requires full-video human review. What the gate is genuinely good at: catching the obvious regression automatically so you don't ship it, and giving you a count of how many frames your refine actually improved versus bailed on. If rejected_frame_count is high, that's not a gate failure, that's information - your denoise curve is too hot, or the crop geometry is off.

Install: ComfyUI Manager → "MiniMax H3 Audio T8", or:

cd ComfyUI/custom_nodes
git clone https://github.com/T8mars/comfyui-minimax-h3-audio-T8

Restart after. No forced pip deps, no model downloads - it's all image statistics on the frames you already have.

CategoryT8/MiniMax H3/Quality/Experimental/Face Refine Parity

Inputs (11)

NameTypeDefaultDescription
base_framesIMAGE
candidate_framesIMAGE
changed_maskMASK
face_planH3_T8_FACE_REFINE_PARITY_PLAN
min_structure_ssimFLOAT0.820–1
min_sharpness_ratioFLOAT1.020–10
max_sharpness_ratioFLOAT2.000–20
max_face_mean_abs_deltaFLOAT0.0600–1
max_residual_temporal_jitterFLOAT0.0500–1
minimum_accept_runINT31–121
edge_fade_framesINT20–60

Outputs (6)

NameTypeDescription
safe_candidate_framesIMAGE
accepted_change_maskMASK
rejected_frame_maskMASK
accepted_frame_countINT
rejected_frame_countINT
report_jsonSTRING