H3 Load Video + Face Select
Pick which face MiniMax H3 actually fixes — before the graph runs
- identity_reference
- identity_clip_vision
- images
- audio
- face_pick
- preview
- report
- frame_count
- fps
MiniMax H3 is genuinely good at video, and genuinely bad at faces that take up a small slice of the frame. That's not a resolution problem - a 720p clip still has the same weak head-size-to-frame ratio - so no upscaler fixes it. The ComfyUI-H3-FaceRefine pack takes the FaceDetailer trick from Impact Pack (detect, crop, re-render at real scale, paste back) and stretches it across every frame. H3 Load Video + Face Select is the front end of that: it loads your video, finds every face and every hard cut in one pass, and decides which face is the subject before any sampling happens.
The pitch is "one pass, one decision." This node owns detection when it's wired in. It scans the clip once, hands its detected boxes and shot boundaries to H3 Face Track + Crop through the face_pick output, and that tracker then greys out its own detection settings because the work is already done. The tracker never decodes or detects the same video twice.
The select input is where you say who the subject is. The default is manual: click the Pick faces button on the node, and it shows one frame per shot with every face outlined and numbered. Choose one per shot and press Use these - the answer lands in confirmed_pick as comma-separated indices like 0,3,4, one per shot, saved with the workflow. There's a reason it asks per shot rather than once: at a hard cut every face gets renumbered, so the person who was face 1 before the cut may be face 3 after. That's also how you tell the graph that two differently-numbered faces are the same person.
Don't want to click? select also takes identity_reference (wire in a portrait and each shot picks the matching face), or a ranking rule: largest_face, centre_most, closest_to_xy and friends, with select_index taking the nth face out of that ranking. Two details worth knowing: the subject is chosen once per shot, then continuity follows it - it isn't re-ranked every frame, so a subject who crosses the frame past someone else is still tracked. And manual will refuse to run until a pick exists, failing fast rather than silently refining whoever ranks first.
Set cut_detection to auto (pyscenedetect) on clips with hard cuts, so the subject is chosen per shot and the tracker doesn't smooth the crop across a join. That's the one dependency this node adds over the pack's others: scenedetect>=0.7, installed automatically with requirements.txt along with ultralytics, scipy and insightface.
The rest of the inputs are trim: video accepts a pasted path (read in place, which is what you want for a big clip) or a Browse-picked file copied into ComfyUI's input folder; confidence is the detector's score floor, where lower catches profiles and small faces at the cost of false positives; skip_first_frames and frame_load_cap trim the clip (the audio is cut to match so lipsync stays aligned). X/Y/frame_index only appear with closest_to_xy - the Preview coordinates button shows you where your numbers land before you render anything.
Outputs worth wiring: images and audio go where your old video loader went (the node replaces it, it doesn't sit beside it); frame_count feeds the H3 node's length so it follows the clip; face_pick goes to the tracker; preview to a PreviewImage shows one card per shot with faces numbered. The report output tells you how many shots were found and which frame each pick locked onto - glance at it, because a false cut costs smoothing on both sides of it.
Install: ComfyUI Manager (search "ComfyUI-H3-FaceRefine") or
cd ComfyUI/custom_nodes
git clone https://github.com/Carasibana/ComfyUI-H3-FaceRefine.git
then restart ComfyUI. You must supply a face detector yourself - face_yolov8m.pt from Bingsu/adetailer into models/ultralytics/bbox/ - and the MiniMax H3 model, VAE and Qwen3-VL text encoder if you're not already generating H3 video. The Manual Select example workflow additionally needs VideoHelperSuite (to save) and ComfyUI-H3-NativeAudioLock (for lipsync). One trap the README calls out: don't install onnxruntime-gpu alongside the CPU onnxruntime - the CPU build shadows it, and identity matching silently drops to CPU. On anime or stylized footage, swap in an anime face detector and set identity_model to clip_vision (or ccip) instead of the insightface default, which is trained on photographed faces.
For a niche of a niche, the README is unusually honest about the pain points, and most of them live in this node. confirmed_pick is dropped automatically if you change the video, detector, frame range or cut settings - annoying until you realize those changes renumber the faces your picks described. And remember H3 wants frame counts on its 17k+5 grid, so let frame_load_cap land on one of those if you're trimming. Wire the preview up, watch the report, and you'll know exactly who's getting the facelift.
Inputs (18)
| Name | Type | Default | Description |
|---|---|---|---|
| video | STRING | Path to the source video. Use Browse to pick one out of ComfyUI's input folder, or paste any path - source footage usually lives somewhere else. Surrounding quotes are stripped, so a path copied from Explorer works as pasted. | |
| detector | COMBO | Face detector, same list the tracker uses. THIS node owns detection when it is wired in - it detects once, here, and hands the boxes downstream so the tracker does not repeat the pass. Use an anime face model for illustration; a photographic one finds nothing there. | |
| confidence | FLOAT | 0.350.05–0.95 | Detector confidence floor. Lower finds more faces including profiles and small ones, at the cost of false positives that then appear as selectable indices. |
| select | COMBO | manual | Which of the detected faces is the subject. Detection itself is always automatic; this is only the choice between what it found. manual: review them and choose. Faces are numbered left to right, and the answer lives in confirmed_pick, one index per shot. identity_reference: each shot picks the face matching the reference image wired into identity_reference. Everything else is a rule, with select_index picking out of it. The subject is chosen ONCE per shot and continuity follows that same face from there - it is NOT re-ranked each frame, so a subject who crosses the frame past someone else is still tracked correctly. largest_face / smallest_face: biggest or smallest by height. left_most / right_most / top_most / bottom_most: by the CENTRE of the face box. centre_most: nearest the centre of the frame. closest_to_xy: nearest the X, Y you give, on frame_index. detector_score: the most confident detection. AT A HARD CUT a rank means nothing across the join - everyone is renumbered. With cut_detection ON each shot chooses again by the rule, so a cut can land on a different person. With it OFF the video counts as one shot and continuity runs straight through a real cut onto whichever face is nearest the last position, which may be anyone. To hold one person across cuts, use identity_reference or manual. |
| select_index | INT | 00–63 | Which face in that ranking is the subject. Connect `preview` to a PreviewImage to see which number is who - every detected face is outlined and numbered there. |
| confirmed_pick | STRING | Used when select is manual: the chosen face, one index per shot, comma separated - 0,1,1. Written by Pick faces and saved with the workflow, so it survives restarts. Clear it to be asked again. Ignored while select is one of the automatic rules. | |
| cut_detectionopt | COMBO | none | Hard-cut detection. A cut renumbers every face, so the subject is chosen once PER SHOT rather than once for the video. Also travels downstream so the tracker does not smooth the crop across a cut. |
| cut_thresholdopt | FLOAT | 3.000.5–20 | How far a frame has to stand out from its neighbours to count as a cut. 3.0 is PySceneDetect's adaptive default. Only used when cut detection is on; the report says how many shots were found. |
| skip_first_framesopt | INT | 00–100000 | Drop this many frames from the start. The audio is cut to match, so lipsync stays aligned. |
| frame_load_capopt | INT | 00–100000 | Stop after this many frames. 0 loads everything. Remember H3 wants a count on its 17k+5 grid - 5, 22, 39 ... 226, 362. |
| select_every_nthopt | INT | 11–100 | Keep every nth frame. Above 1 this changes the effective frame rate, and the reported fps changes with it. |
| identity_referenceopt | IMAGE | A picture of the person to refine. Each shot picks the face that matches this, so the same person is followed across a cut without hand-picking. A frame of the clip works; so does a portrait. REQUIRED when select is identity_reference - that mode has no other way to decide, so the node stops with an error if nothing is wired here. Ignored by every other select mode. This differs from H3 Face Track + Crop, where a reference is optional and identity tracking falls back to an anchor taken from the clip itself. | |
| identity_clip_visionopt | CLIP_VISION | Only for identity_model=clip_vision. Add a CLIPVisionLoader and wire it in. | |
| identity_modelopt | COMBO | insightface | How a face is compared to identity_reference. insightface for photographic faces; clip_vision or ccip for illustration, where face recognition trained on photographs does poorly. |
| identity_thresholdopt | FLOAT | 0.280–1 | How close a match has to be to count as the same person. A shot where nothing reaches this is marked as not containing them, and is dropped from the render. |
| Xopt | INT | 00–16384 | Only used by select=closest_to_xy. Horizontal position in PIXELS of the source video frame, measured from the TOP-LEFT corner, increasing to the right. On a 960x544 clip, 0 is the left edge, 960 the right, 480 the middle. The point does not have to sit on a face: the nearest face CENTRE wins, however far away it is. |
| Yopt | INT | 00–16384 | Only used by select=closest_to_xy. Vertical position in PIXELS of the source video frame, measured from the TOP-LEFT corner, increasing DOWNWARD. On a 960x544 clip, 0 is the top edge, 544 the bottom, 272 the middle. |
| frame_indexopt | INT | 00–999999 | Only used by select=closest_to_xy. The frame the X, Y measurement is taken on, counting from 0 for the FIRST frame. It counts the frames this node loaded, so with skip_first_frames or select_every_nth set it counts from the first frame kept, not the first frame of the file. The face found there is followed forwards and backwards through its shot, so pick a frame where the subject is clearly visible. |
Outputs (7)
| Name | Type | Description |
|---|---|---|
| images | IMAGE | — |
| audio | AUDIO | — |
| face_pick | H3FACEPICK | — |
| preview | IMAGE | — |
| report | STRING | — |
| frame_count | INT | — |
| fps | FLOAT | — |