Remove Ghost Mask reference mode
This commit is contained in:
@@ -58,7 +58,7 @@ This node uses Ollama Locally : you will need to install it (very lightweight) a
|
||||
|
||||
- You can still enter your description manually if you don't want to install it but it works very well!
|
||||
|
||||
- Both references mode work (fixed), Licon MSR and Ghost Mask.
|
||||
- Reference mode included: Licon MSR.
|
||||
|
||||
- Use their Lora, that is an important step : https://huggingface.co/LiconStudio/LTX-2.3-Multiple-Subject-Reference/tree/main
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -2538,7 +2538,6 @@ class TimelineEditor {
|
||||
refOptionSelect.className = "prcs-ref-option-select";
|
||||
refOptionSelect.title = "Character reference mode";
|
||||
const REF_OPTIONS = [
|
||||
{ value: "Ghost Mask (End)", label: "Ghost Mask mode" },
|
||||
{ value: "Licon MSR (Prefix)", label: "Licon MSR" },
|
||||
{ value: "OFF", label: "OFF" },
|
||||
];
|
||||
@@ -2548,7 +2547,12 @@ class TimelineEditor {
|
||||
o.textContent = opt.label;
|
||||
refOptionSelect.appendChild(o);
|
||||
});
|
||||
refOptionSelect.value = this.timeline.reference_mode || "OFF";
|
||||
const refOptionValues = new Set(REF_OPTIONS.map(opt => opt.value));
|
||||
const initialRefMode = refOptionValues.has(this.timeline.reference_mode)
|
||||
? this.timeline.reference_mode
|
||||
: "OFF";
|
||||
refOptionSelect.value = initialRefMode;
|
||||
this.timeline.reference_mode = initialRefMode;
|
||||
refOptionSelect.addEventListener("change", (e) => {
|
||||
this.timeline.reference_mode = e.target.value;
|
||||
this.commitChanges();
|
||||
|
||||
@@ -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(
|
||||
@@ -2056,11 +2009,7 @@ class LTXDirector(io.ComfyNode):
|
||||
),
|
||||
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.",
|
||||
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,8 +2131,11 @@ 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".
|
||||
# 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,
|
||||
@@ -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,
|
||||
|
||||
@@ -808,15 +808,6 @@ class LTXDirectorGuide:
|
||||
if auto_snap_ic_grid and model is not None and ic_lora_name != "None":
|
||||
latent_image, noise_mask = _snap_latent_to_downscale(latent_image, noise_mask, latent_downscale_factor, upscale_method)
|
||||
|
||||
# Ghost Mask: the Director kept the latent clean (so it stays length-matched with the audio
|
||||
# latent) and asked us to pre-extend it here by one hidden frame per reference. The tail
|
||||
# sits past the clean region; the reference images (in guide_data["images"], anchored at
|
||||
# (clean + i)) are written into it by the loop below, then dropped downstream by Clean
|
||||
# Latent Slice (length = clean_latent_frames).
|
||||
_ghost_pre_extend = int(guide_data.get("ghost_pre_extend", 0)) if guide_data else 0
|
||||
if _ghost_pre_extend > 0:
|
||||
latent_image, noise_mask = _append_latent_frames(latent_image, noise_mask, _ghost_pre_extend, mask_fill=1.0)
|
||||
|
||||
_, _, latent_length, latent_height, latent_width = latent_image.shape
|
||||
initial_latent_length = int(latent_length)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user