fix(studio): the scene split no longer discards a wired reference
The split re-encodes each scene from text and its entries replace output_conditioning WHOLESALE. It re-establishes H3's visual conditioning from source_image / h3_references — and nothing in the editor pipeline sets either, because the reference lives on the R2V node, not on Studio. So a wired reference conditioning was replaced by text-only encodes: not appearance drift, a different person. _v2_transition_scene_conditionings returns None when clip is None, so the wired conditioning survived with CLIP disconnected. That is why disconnecting CLIP "fixed" it, and why every fix upstream of the split changed nothing. Studio cannot split a conditioning it did not build. When one is wired it keeps it, for every scene, and says so.
This commit is contained in:
@@ -38,6 +38,14 @@
|
||||
`$style` while the encoded prompt had it resolved.
|
||||
|
||||
### Fixed
|
||||
- **A wired reference conditioning is no longer thrown away by the scene split.** The split
|
||||
re-encodes every scene from text and its entries replace the output wholesale. It
|
||||
re-establishes H3's visual conditioning from `source_image` / `h3_references` — neither of
|
||||
which anything in the editor pipeline sets — so on a reference run the identity was
|
||||
replaced by text-only encodes and the character came out as a different person entirely.
|
||||
With CLIP disconnected the split returned None and the wired conditioning survived, which
|
||||
is why disconnecting CLIP appeared to fix it. Studio cannot split a conditioning it did not
|
||||
build, so it now keeps the one it was given and says so.
|
||||
- **A reference image's encoded rows are no longer steered.** H3 tokenizes a reference INTO
|
||||
the conditioning — comfy marks the whole vision block as 0 in `minimax_token_tags` and text
|
||||
as 1 — and those rows are Qwen's encoding of the picture. Every steering path (learned
|
||||
|
||||
+17
-1
@@ -13094,7 +13094,23 @@ class FunPackVideoRefinerV2(FunPackVideoRefiner):
|
||||
)
|
||||
if _conditioning_plan_reason:
|
||||
print(f"[FunPackVideoRefinerV2] {_conditioning_plan_reason}")
|
||||
if split_by_transitions:
|
||||
# The split RE-ENCODES every scene from text and its entries replace
|
||||
# `output_conditioning` wholesale. It re-establishes H3's visual conditioning from
|
||||
# `source_image` / `h3_references` — but a wired CONDITIONING carries a reference this
|
||||
# node never received: nothing in the editor pipeline sets either of those, so the
|
||||
# re-encode is textually blind to the picture and the identity is simply gone. Not
|
||||
# drift — a different person. Studio cannot split a conditioning it did not build, so
|
||||
# it keeps the one it was given.
|
||||
if split_by_transitions and conditioning_owner == "CONDITIONING-owned":
|
||||
_log.note_on_change(
|
||||
"studio:split_vs_wired", "FunPackStudio",
|
||||
"the positive CONDITIONING is wired, so the scene split is SKIPPED — "
|
||||
"splitting means re-encoding each scene from text, and this node cannot "
|
||||
"reproduce a reference it never received. Every scene uses the wired "
|
||||
"conditioning. Disconnect it to let Studio split and encode per scene.")
|
||||
status = status + ("\nTransition split: skipped — the wired positive "
|
||||
"CONDITIONING owns the prompt") + enhancement_status
|
||||
elif split_by_transitions:
|
||||
try:
|
||||
scene_texts = split_scene_texts
|
||||
if scene_texts:
|
||||
|
||||
@@ -7,6 +7,7 @@ so the vision block precedes the prompt and every prompt row is a hidden state t
|
||||
already read the picture. Studio cannot reproduce that: nothing in the editor pipeline wires
|
||||
`h3_references` or `source_image`, so its encode never sees an image at all.
|
||||
"""
|
||||
import inspect
|
||||
import sys
|
||||
import types
|
||||
|
||||
@@ -83,3 +84,34 @@ def test_an_invalid_wired_conditioning_falls_back_to_clip(studio, monkeypatch, c
|
||||
assert owner == "CLIP-owned"
|
||||
assert torch.equal(cond, torch.ones(1, 4, 8))
|
||||
assert "invalid" in capsys.readouterr().out
|
||||
|
||||
|
||||
# --- the scene split cannot rebuild what it did not encode -----------------
|
||||
|
||||
def test_the_split_is_skipped_when_the_conditioning_is_wired(monkeypatch, capsys):
|
||||
"""The split re-encodes every scene from text and its entries replace the output
|
||||
WHOLESALE. It re-establishes H3's visual conditioning from source_image /
|
||||
h3_references — neither of which the editor pipeline ever sets — so a wired reference
|
||||
conditioning was replaced by text-only encodes and the character became someone else.
|
||||
|
||||
With CLIP disconnected the split returns None and the wired conditioning survived, which
|
||||
is exactly why disconnecting CLIP 'fixed' it.
|
||||
"""
|
||||
import conditioning
|
||||
node = conditioning.FunPackVideoRefinerV2()
|
||||
called = []
|
||||
monkeypatch.setattr(node, "_v2_transition_scene_conditionings",
|
||||
lambda *a, **k: called.append(a) or None, raising=False)
|
||||
|
||||
src = inspect.getsource(conditioning.FunPackVideoRefinerV2.refine_v2)
|
||||
# The guard is on ownership, not on CLIP being absent.
|
||||
assert 'split_by_transitions and conditioning_owner == "CONDITIONING-owned"' in src
|
||||
assert "elif split_by_transitions:" in src
|
||||
|
||||
|
||||
def test_the_skip_is_reported_not_silent():
|
||||
"""A silently unsplit multi-scene run looks like the scene texts were ignored."""
|
||||
import conditioning
|
||||
src = inspect.getsource(conditioning.FunPackVideoRefinerV2.refine_v2)
|
||||
assert "the scene split is SKIPPED" in src
|
||||
assert "Disconnect it to let Studio split and encode per scene." in src
|
||||
|
||||
Reference in New Issue
Block a user