BFS Shot H3 Conditioning (Advanced)
The shot loop's H3 wiring, done for you
- shot
- clip
- vae
- audio_vae
- model
- vlm
- setting_mask
- positive
- latent
- model
- prompt
What it replaces
If you were building the shot loop by hand, this node is the pile of work you'd otherwise do once per shot: call MiniMax H3's Reference to Video with the shot's prompt, references and length, optionally bolt an aligned guide on with Add Guide, optionally pin the shot's own clip as a duet panel, and push the model through a RoPE patch if you're using the shifted layout. You feed it a shot and it hands back positive, latent, model and prompt.
Then it runs once per shot, because the planner's shots list made it a list node. You sample the latent, decode, and drop the frames into BFS Shot Join.
The setting that decides everything
guide_mode is the one to think about:
aligned guide (Add Guide)- the shot's frames sit on the generated frames, frame by frame. This is the mode for body-swap LoRAs, which were trained on same-resolution aligned guides.native reference video (Video 1)- the shot enters as a reference video, the way H3's Reference to Video node takes a clip, with its soundtrack.both- the two at once, which is heavier and smarter than it sounds.none- conditioning from prompt and references only.
first_frame is a different mechanism from continuity, and it's easy to confuse the two: shot's first frame anchors the shot's own frame from the source video at frame 0, which is what you want for a cut-free continuation of the real footage. Continuity in the planner pulls the previous generated result, which is what you want across cuts. Both at once is usually wrong.
duet turns the shot's own clip into a pinned side panel - off, canvas, or shifted RoPE. For shifted RoPE you must route the model through this node and use its model output, since the shift is applied to the model. The nice detail: BFS Shot Join cuts the panel off by itself, so the sampler and decode half of your workflow doesn't change at all when you turn the duet on. panel_position, panel_size, panel_noise and rope_gap only matter when it's on, and panel_noise 0 means "pin it exactly" while 0.05–0.2 loosens it for bigger changes. Same warning as everywhere else with the shifted layout: keep rope_gap small or H3 draws its own split screen.
The prompt writer, and setting_ref
By default task = planner prompt, which uses each shot's prompt from the planner as-is. Pick any other task (character swap, style, setting, appearance, lighting/weather, custom) and the node writes each shot's prompt in the duet format instead - with a Qwen3-VL on vlm it looks at the shot and its references and writes it, otherwise it falls back to the task's template. The finished text comes out on prompt so you can read it, which is how you decide whether the VLM is earning its VRAM. instruction is the few words about what changes; for a pure character swap you can leave it empty because the person comes from the references.
setting_ref is worth knowing because it's a trick rather than a feature, credited in the docs to TSC: with it on, the node adds one more reference - the shot's middle frame with the person masked out in TV static - so the model sees the place in full detail when the panel or guide is too small to carry it. It becomes the last <Picture n> in the prompt, and setting_mask lets you supply the person's mask yourself; otherwise it falls back to the shot's SAM 3 crop mask, then to SAM 3 "person" on that frame. on (source size, slower) uses the video's own resolution up to a 2048 short edge - sharper, and it costs you.
use_ref_2 and ref_image_size are small but real: the second reference is on by default, and ref_image_size decides whether references come back at match (the generation size) or max.
Install
cd ComfyUI/custom_nodes
git clone https://github.com/alisson-anjos/ComfyUI-BFSNodes
cd ComfyUI-BFSNodes && pip install -r requirements.txt
Restart, and reload the tab. You need a ComfyUI build with the native H3 nodes and an H3 model, VAE and text encoder. Give it an audio_vae when with_audio is on, or the shot's soundtrack won't ride along with the guide video.
Watch for
The latent output is the H3 AV latent, so the sampler's latent_image is this one - not something you built separately. And if you turn the duet on and the result is a split screen, you almost certainly didn't connect the planner's shots output through the whole chain, so the join never got the panel geometry it needs to crop.
Inputs (23)
| Name | Type | Default | Description |
|---|---|---|---|
| shot | BFS_SHOT | — | |
| clip | CLIP | — | |
| vae | VAE | — | |
| guide_mode | COMBO | aligned guide (Add Guide) | aligned guide: the shot's frames sit on the generated frames (MiniMax H3 Add Guide), frame by frame. native reference video: the shot enters as <Video 1> like the reference video input. both: the two together. aligned guide + CLIP video context: Qwen sees the shot at clip_video_fps, while its latents enter only as an aligned guide. Native temporal alignment: experimental mode matching native_temporal_v1 training; requires MODEL routing, 24 fps and no Add Guide/VSA. |
| first_frame | COMBO | none | Anchor the shot's own first frame as an extra aligned image guide. Leave this at none when replacing the source location: its first frame also anchors the original background. |
| ref_image_size | COMBO | match | 2 options: match, max |
| audio_vaeopt | VAE | — | |
| with_audioopt | BOOLEAN | false | Attach the shot's soundtrack to the guide / reference video (needs audio_vae). |
| modelopt | MODEL | Optional: passed through, or patched in native temporal mode. Route MODEL output to the guider (workflows that routed the model through this node keep working). | |
| vlmopt | CLIP | Optional VLM (CLIPLoader with a Qwen3-VL text encoder). Fills {details} when the planner left it (no 📝 Describe refs, no VLM on the planner). | |
| setting_refopt | COMBO | off | This references the ORIGINAL source setting; leave it off when replacing that location. TSC's trick: one more reference picture, the shot's middle frame with the person covered in TV static, so the model sees the place in full detail (the panel / guide is often small). It is the last <Picture n>; a sentence about it is added to subject_definitions (or write {setting} where you want its tag). Mask: setting_mask, else the shot's SAM 3 mask (crop or not), else SAM 3 'person' on that frame. 'source size' uses the video's own resolution (up to 2048 short edge): sharper, slower. |
| setting_maskopt | MASK | Optional mask of the person to cover in the setting picture. | |
| inpaintopt | COMBO | per shot (planner) | per shot (planner): each shot's mode in the Shot Planner decides (Full frame / Mask only / Crop / Crop + mask). only the mask: every shot. off: never. Regenerate ONLY the person. The latent starts from the shot's own frames and the shot's SAM 3 mask (grown by the mask's expand + one latent cell) becomes H3's generation mask; everything else stays exactly as it was. With 'Crop to mask' on the shot it works inside the crop (more pixels for the person, BFS Shot Join pastes it back); without crop it works on the whole frame (no crop / uncrop at all). Needs a mask (text or points) on the shot. Crop + H3 generation mask: credit to Neko (Nekodificador) and AbleJones, whose workflow and nodes this follows. On ComfyUI builds without native H3 generation masks, add a per-row mask patch to the model (e.g. ComfyUI-MiniMaxH3-PerRowMasking). |
| mask_guideopt | COMBO | off | Experimental, 'Mask only' shots (mask, no crop): the shot with ONLY the masked region visible (the rest grey), so the model looks at the subject's pose and outline on its own while the mask limits where it generates. '+ extra guide': a second aligned guide latent next to the normal one (the model sees both). 'instead of the full guide': replaces the normal guide. '+ reference video': enters as a native reference video (<Video n>, after the shot's own if guide_mode uses it). The LoRAs were trained with one full guide, so test against off; it can also pull the old subject's look. |
| source_bluropt | COMBO | off | Blur the source person in what the model SEES of the source (aligned guide, native reference video): '<region> (<what stays sharp>)'. Region: face / head + hands / person (every person the segmenter finds) or masked area (the shot's own mask, the person being replaced, with its expand). keep mouth: lips, teeth and tongue stay sharp; keep lips + tongue: the teeth are blurred too; mouth too: nothing stays sharp. The model still reads the pose and motion but has no face to copy, so the identity comes from the reference. The kept area of 'Mask only' and the output are never blurred. JalenBrunson's swap trick. |
| source_blur_strengthopt | FLOAT | 1.000.1–1 | How coarse the source blur is (1 = no detail left). |
| source_blur_segmenteropt | COMBO | SAM 3.1 | What finds the face / head / hands / person and the mouth for source_blur. SAM 3.1: text prompts (already used by the planner). Sapiens2: body-part classes in one pass, finer lips and teeth (downloads facebook/sapiens2-seg-0.4b, 1.6 GB, to models/sapiens2 the first time). The 'keep lips + tongue' modes always use Sapiens2 for the lips. |
| source_blur_effectopt | COMBO | blur | blur: no detail left. invert colours: keeps the shapes and the expression but not the skin tone or the colours. |
| mask_guide_lookopt | COMBO | grey blurred | What the mask guide shows of the subject. grey blurred: its volume, light and head direction without colours or a face (default). colour: as it is (can make the model copy the old subject). silhouette: only its flat shape. edges: only its outlines. pose (people): the skeleton of the people in the mask (OpenPose colours), from a YOLO pose model in models/ultralytics (e.g. pose/yolov8m-pose.pt; uses ultralytics like the planner's filters). The less it shows, the less the model can copy the old subject; the more, the better it follows the pose. |
| mask_ref_sizeopt | COMBO | 1/2 | mask_guide '+ reference video' only: size of that reference video (fraction of the generation size). The native reference channel keeps a smaller video as it is, so 1/2 costs ~1/4 of the tokens; it only has to show the pose and outline. |
| clip_video_fpsopt | FLOAT | 2.00.5–24 | Only for aligned guide + CLIP video context. Qwen sampling rate for this shot; try 2, 4 or 8 fps. Higher values cost more context/encoding time, not output fps. Console confirms sent frames, video vision tokens and completed encoding. |
| native_guide_scaleopt | FLOAT | 1.0000.125–1 | Native temporal mode only: spatial scale of the motion video before encoding; output size, frame count and identity references stay unchanged. Try 0.5 to reduce guide tokens/VRAM. |
| native_temporal_backendopt | COMBO | flash partitions (no compile) | Native temporal mode only. Flash partitions preserves the temporal attention policy without compilation; Flex is the original implementation. |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| positive | CONDITIONING | — |
| latent | LATENT | — |
| model | MODEL | — |
| prompt | STRING | — |