From 7d3cf61920efa995d069d733ffc11497ffc5f9f0 Mon Sep 17 00:00:00 2001 From: digital-garbage <133010426+digital-garbage@users.noreply.github.com> Date: Sat, 8 Aug 2026 22:13:00 +0300 Subject: [PATCH] fix: an fl2va/ref2va node satisfies H3's AV latent requirement MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- movie_editor/backend/nodes.py | 8 ++++++-- movie_editor/frontend/models.js | 18 ++++++++++++++++-- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/movie_editor/backend/nodes.py b/movie_editor/backend/nodes.py index d51addf6..93d187e5 100644 --- a/movie_editor/backend/nodes.py +++ b/movie_editor/backend/nodes.py @@ -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."}, }, }, } diff --git a/movie_editor/frontend/models.js b/movie_editor/frontend/models.js index 26501de6..27c02951 100644 --- a/movie_editor/frontend/models.js +++ b/movie_editor/frontend/models.js @@ -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); }