fix: an fl2va/ref2va node satisfies H3's AV latent requirement

MiniMaxH3ImageToVideo and MiniMaxH3ReferenceToVideo emit their own AV
latent next to their conditioning, so an Empty MiniMax H3 AV Latent is
not needed alongside one. The requirements panel only counted a slot
filed under the empty_latent ROLE, so the row read as missing for anyone
who added the node as what it mostly is — a conditioning source.

A requirement now counts any slot that genuinely SOURCES the type
(outputs it without consuming one), whatever role it carries. VAE keeps
the role check: it is asked for twice and only the role separates the
video decoder from the audio one. A pass-through patcher (a LoRA on
MODEL/CLIP) still never satisfies a requirement by itself.

The builder needed no change here — it already auto-wires the node's
LATENT into the sampler's latent_template.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
digital-garbage
2026-08-08 22:13:00 +03:00
co-authored by Claude Opus 5
parent bd9cb3062a
commit 7d3cf61920
2 changed files with 22 additions and 4 deletions
+6 -2
View File
@@ -194,7 +194,9 @@ ROLES: dict[str, dict] = {
# Each entry: id, type, label, required, role_hint (role key to suggest adding), hint.
# MiniMax H3 replaces two of these: its own EmptyMiniMaxH3LatentAV emits the video AND
# audio streams in one node, so there is no separate audio-latent step and the latent is
# no longer optional (nothing else produces one). The audio VAE stays required — it decodes
# no longer optional — Studio does not generate one for this family, so a node has to. It
# needn't be the Empty node: fl2va / ref2va build their own AV latent alongside their
# conditioning, and satisfy this the same way. The audio VAE stays required — it decodes
# the generated audio — and gains a second, optional job on H3 (encoding audio references).
FAMILY_REQUIREMENTS: dict[str, dict] = {
"minimax_h3": {
@@ -206,7 +208,9 @@ FAMILY_REQUIREMENTS: dict[str, dict] = {
"clip": {"hint": "Add the MiniMax H3 text encoder (Qwen3-VL-32B, truncated to 50 layers)."},
"init_latent": {"required": True, "label": "AV latent",
"hint": "Add Empty MiniMax H3 AV Latent — it makes the video and audio "
"streams together and feeds the Chain Sampler directly."},
"streams together and feeds the Chain Sampler directly. A "
"MiniMax H3 Image to Video (fl2va) or Reference to Video "
"(ref2va) node covers this too: each builds its own AV latent."},
},
},
}
+16 -2
View File
@@ -1007,9 +1007,23 @@
});
}
// For VAE: need two separate producers (video_vae + audio_vae roles).
// For others: at least one producer of the type (regardless of role).
// Does this slot SOURCE the type — output it without consuming one? A loader or a
// generator does; a patcher that only passes the type through (a LoRA on MODEL/CLIP)
// does not, and can't satisfy a requirement on its own.
function slotSourcesType(type, slot) {
const spec = specFor(slot);
if (!(spec?.outputs || []).some((o) => o.type === type)) return false;
return !(spec?.connection_inputs || []).some((ci) => ci.type === type);
}
// VAE is asked for twice — video and audio — and only the role tells the two apart, so
// those stay role-bound (two separate producers required). Every other requirement is
// about whether the pipeline can GET that type from somewhere, so any node that really
// sources it counts, whatever role the user filed it under: MiniMax H3's fl2va / ref2va
// nodes emit their own AV latent, which is exactly what an Empty AV Latent would provide.
function requirementSatisfied(req) {
if (req.type === "VAE") return slotProducesType(req.type, req.role_hint);
if (config.slots.some((s) => slotSourcesType(req.type, s))) return true;
if (req.role_hint) return slotProducesType(req.type, req.role_hint);
return slotProducesType(req.type, null);
}