Remove Ghost Mask reference mode

This commit is contained in:
OpenClaw Agent
2026-07-17 07:45:53 +00:00
parent 7b4e8865d6
commit 5c4349d9b9
5 changed files with 35 additions and 89 deletions

View File

@@ -1698,7 +1698,6 @@ def _build_reference_mode_outputs(
clean_latent_frames: int,
reference_strength: float,
optional_latent,
ref_images,
resize_method: str,
divisible_by: int,
prepare_tensor_image,
@@ -1785,52 +1784,6 @@ def _build_reference_mode_outputs(
)
return patched, conditioning, latent, out_guide_data
extra_refs = []
if reference_mode == "Ghost Mask (End)" and ref_images is not None:
try:
for bi in range(ref_images.shape[0]):
extra_refs.append(ref_images[bi:bi + 1])
except Exception as e:
log.warning("[LTXDirector] Could not process ref_images input: %s", e)
ghost_refs = char_images + extra_refs
is_ghost = reference_mode == "Ghost Mask (End)" and bool(ghost_refs)
n_refs = len(ghost_refs) if is_ghost else 0
if is_ghost:
for i, single_ref in enumerate(ghost_refs):
ref_tensor = prepare_tensor_image(single_ref, latent_w, latent_h)
guide_data["images"].append(ref_tensor)
guide_data["insert_frames"].append((clean_latent_frames + i) * 8)
guide_data["strengths"].append(float(reference_strength))
guide_data["ghost_pre_extend"] = int(n_refs)
total_latent_frames = clean_latent_frames + n_refs
tail_pixels = n_refs * 8
local_part = local_prompts.strip() if local_prompts.strip() else global_prompt
clean_lengths = segment_lengths.strip() if segment_lengths.strip() else str(duration_frames)
injected_local = f"{local_part} | {global_prompt}"
injected_lengths = f"{clean_lengths},{tail_pixels}"
dummy_full = {"samples": torch.zeros([1, 128, total_latent_frames, latent_grid_h, latent_grid_w], device=_dev)}
patched, conditioning = _encode_relay(
model, clip, dummy_full, global_prompt, injected_local, injected_lengths, epsilon,
)
if optional_latent is None:
latent = {
"samples": torch.zeros([1, 128, clean_latent_frames, latent_grid_h, latent_grid_w], device=_dev),
"noise_mask": torch.ones((1, 1, clean_latent_frames, latent_grid_h, latent_grid_w), dtype=torch.float32, device=_dev),
}
else:
latent = optional_latent
log.info(
"[LTXDirector] Ghost Mask: %d references; guide will hide them in a tail past "
"frame %d (clean_latent_frames=%d). Enable Clean Latent Slice (length=%d) downstream.",
n_refs, clean_latent_frames, clean_latent_frames, clean_latent_frames,
)
return patched, conditioning, latent, guide_data
if optional_latent is None:
latent = {"samples": torch.zeros([1, 128, clean_latent_frames, latent_grid_h, latent_grid_w], device=_dev)}
log.info(
@@ -2054,13 +2007,9 @@ class LTXDirector(io.ComfyNode):
"vae", optional=True,
tooltip="Optional. Connect the LTX Autoencoder/VAE here to natively encode the MSR visual reference slideshow into the latent prefix. Required for the 'Licon MSR' ref option.",
),
io.Float.Input(
"reference_strength", default=1.0, min=0.0, max=5.0, step=0.05, optional=True,
tooltip="Guide strength applied to the character reference images (Ghost Mask / Licon MSR ref options).",
),
io.Image.Input(
"ref_images", optional=True,
tooltip="Ghost Mask only. Extra reference image(s) (e.g. an object) — a single image or a batch. Appended as their own block of hidden reference frames AFTER the @char references, for any number of characters loaded (0-6). Ignored in MSR / OFF modes.",
io.Float.Input(
"reference_strength", default=1.0, min=0.0, max=5.0, step=0.05, optional=True,
tooltip="Guide strength applied to the character reference images when using Licon MSR.",
),
MSRCharacterSetData.Input(
"character_set",
@@ -2107,7 +2056,7 @@ class LTXDirector(io.ComfyNode):
custom_width=768, custom_height=512, resize_method="maintain aspect ratio",
divisible_by=32, img_compression=0, audio_vae=None, optional_latent=None,
use_custom_audio=False, inpaint_audio=True, use_custom_motion=True, override_audio=False,
vae=None, reference_strength=1.0, ref_images=None, character_set=None, timeline=None,
vae=None, reference_strength=1.0, character_set=None, timeline=None,
start=None, end=None, duration=None) -> io.NodeOutput:
input_dir = folder_paths.get_input_directory()
image_cache = {}
@@ -2182,9 +2131,12 @@ class LTXDirector(io.ComfyNode):
log.info(f"[LTXDirector] execute RECEIVED global_prompt: {repr(global_prompt)}")
# --- Reference option (set by the toolbar "Ref Option" dropdown, stored in timeline JSON) ---
# One of: "Ghost Mask (End)", "Licon MSR (Prefix)", "OFF".
reference_mode = tdata.get("reference_mode", "OFF")
# One of: "Licon MSR (Prefix)", "OFF".
reference_mode = tdata.get("reference_mode", "OFF")
if reference_mode not in {"Licon MSR (Prefix)", "OFF"}:
reference_mode = "OFF"
tdata["reference_mode"] = reference_mode
characters = _extract_runtime_character_entries(
tdata=tdata,
character_set=character_set,
@@ -2195,7 +2147,7 @@ class LTXDirector(io.ComfyNode):
char_images = [img for slot_images in char_slot_images for img in slot_images]
# --- @charN substitution ---
# Ghost Mask / OFF: swap @char tags for their VLM descriptions in the prompt text.
# OFF: swap @char tags for their VLM descriptions in the prompt text.
# Licon MSR: leave the tags raw — there the reference IMAGE drives identity, and the
# tags are used only to pick which character slots feed the slideshow.
if reference_mode == "Licon MSR (Prefix)":
@@ -2267,7 +2219,6 @@ class LTXDirector(io.ComfyNode):
clean_latent_frames=clean_latent_frames,
reference_strength=reference_strength,
optional_latent=optional_latent,
ref_images=ref_images,
resize_method=resize_method,
divisible_by=divisible_by,
prepare_tensor_image=prepare_tensor_image,