From cf3f0b64a5cd91cf88c22b1005cf21735338ea5b Mon Sep 17 00:00:00 2001 From: digital-garbage <133010426+digital-garbage@users.noreply.github.com> Date: Fri, 5 Jun 2026 20:56:52 +0300 Subject: [PATCH] Revert i2v anchor (DynamicConditioning): no-op on packed AV, not worth keeping DynamicConditioning is an unpacked-video technique; on LTXAV (packed AV latent, 3D mask) it can only no-op (comfy's process_timestep patchifies expecting 5D). Rather than keep dead knobs in the Chain Sampler UI, remove i2v_anchor_power / i2v_anchor_first_frame_only, the install block, and _install_i2v_anchor entirely. The packed-safe path for cross-cut appearance carry (strengthen the Chain Sampler's own carry/guide masks pre-pack) remains available as a future native feature. Co-Authored-By: Claude Opus 4.8 --- samplers.py | 83 ----------------------------------------------------- 1 file changed, 83 deletions(-) diff --git a/samplers.py b/samplers.py index 7088f86d..85143dcd 100644 --- a/samplers.py +++ b/samplers.py @@ -2070,14 +2070,6 @@ class FunPackLTXAVSceneChainSampler: "default": 0.05, "min": 0.0, "max": 1.0, "step": 0.001, "tooltip": "Decode timestep fed to the VAE decoder when decode_noise_scale > 0. ~0.05 adds subtle detail; higher gives the decoder more freedom (more deviation from the latent).", }), - "i2v_anchor_power": ("FLOAT", { - "default": 1.0, "min": 1.0, "max": 2.0, "step": 0.01, - "tooltip": "Progressively strengthen i2v adherence to the conditioning frame as denoising proceeds (port of LTXV DynamicConditioning): the denoise mask is raised to power**step. 1.0 = off. NOTE: only works on UNPACKED 5D video masks; on PACKED audio+video (LTXAV) it safely no-ops (the mask is 3D and comfy's per-token-timestep patchify needs 5D). ~zero overhead.", - }), - "i2v_anchor_first_frame_only": ("BOOLEAN", { - "default": True, - "tooltip": "When i2v_anchor_power > 1.0: apply the ramp only to the first (conditioning) frame, leaving the rest free. Off ramps the whole mask.", - }), "embed_guidance_source": (["relative", "absolute"], { "default": "relative", "tooltip": "Which learned direction embed_guidance steers toward. Relative: this prompt's liked direction (needs refinement_key_input). Absolute: the global, prompt-agnostic taste direction the Refiner accumulates across all prompts — works with no key.", @@ -2785,75 +2777,6 @@ class FunPackLTXAVSceneChainSampler: result.seed = seed return result - def _install_i2v_anchor(self, model, power, first_frame_only): - """Port of LTXV DynamicConditioning: progressively strengthen i2v adherence to the - conditioning frame as denoising proceeds, by raising the denoise mask to power**step. - Uses the stock comfy ModelPatcher API (set_model_denoise_mask_function) — no modified - model, no extra forward pass. Fully defensive: any missing mask / unexpected shape / error - falls through to the unmodified mask, so it's a safe no-op when it can't apply.""" - p = float(power) - - def _find_step(sigma, step_sigmas): - try: - for idx, s in enumerate(step_sigmas): - if s <= sigma: - return idx - return len(step_sigmas) - 1 - except Exception: - return 0 - - def _denoise_mask_fn(sigma, denoise_mask, extra_options): - try: - step_sigmas = extra_options.get("sigmas") - inner = extra_options.get("model") - if denoise_mask is None or step_sigmas is None or inner is None: - return denoise_mask - exp = p ** _find_step(sigma, step_sigmas) - if abs(exp - 1.0) < 1e-6: - return denoise_mask - # This technique (LTXV DynamicConditioning) assumes an UNPACKED 5D video mask - # [B,C,F,H,W]: comfy's LTXAV process_timestep patchifies the mask expecting 5D. - # LTXAV PACKS the AV latent, so its denoise mask is 3D [B,C,N] — touching or - # propagating that crashes patchify (expected 5, got 3). So operate ONLY on genuine - # 5D masks; on packed AV (or anything else) this is a clean no-op. - if denoise_mask.dim() != 5: - if not getattr(self, "_i2v_anchor_packed_warned", False): - self._i2v_anchor_packed_warned = True - print("[FunPackSceneChain] i2v anchor: packed/non-5D denoise mask " - f"(ndim={denoise_mask.dim()}) -> no-op (technique needs unpacked video).") - return denoise_mask - mask = denoise_mask.clone() - if first_frame_only: - try: - num_channels = inner.model_patcher.model.diffusion_model.in_channels - except Exception: - num_channels = mask.shape[1] - mask[:, :num_channels, :1] = mask[:, :num_channels, :1] ** exp - else: - mask = mask ** exp - # Propagate to the conds so per-token timestep values stay consistent. - try: - for ck in inner.conds: - if "positive" in ck or "negative" in ck: - for cond in inner.conds[ck]: - mc = cond.get("model_conds") if isinstance(cond, dict) else None - if mc and "denoise_mask" in mc: - mc["denoise_mask"].cond = mask - except Exception: - pass - return mask - except Exception: - return denoise_mask - - try: - patched = model.clone() - patched.set_model_denoise_mask_function(_denoise_mask_fn) - print(f"[FunPackSceneChain] i2v anchor ramp on (power={p}, first_frame_only={first_frame_only})") - return patched - except Exception as e: - print(f"[FunPackSceneChain] i2v anchor install failed ({e}); continuing without it.") - return model - def sample(self, model, vae, positive, negative, sampler, sigmas, seed, latent_template, num_frames_per_scene, frame_overlap, cfg, max_scenes, use_same_seed=False, carry_i2v_guides=False, @@ -2862,7 +2785,6 @@ class FunPackLTXAVSceneChainSampler: embed_guidance_source="relative", transition_duration=16, decode_tile_size=0, decode_noise_scale=0.0, decode_timestep=0.05, - i2v_anchor_power=1.0, i2v_anchor_first_frame_only=True, refinement_key_input="", unique_id=None, prompt=None): if not isinstance(positive, list) or not positive: raise ValueError("positive conditioning must contain at least one scene entry.") @@ -2875,11 +2797,6 @@ class FunPackLTXAVSceneChainSampler: if decode_noise_scale and decode_noise_scale > 0: vae = self._vae_with_decode_noise(vae, decode_timestep, decode_noise_scale, seed) - # i2v anchor ramp (LTXV DynamicConditioning): patch the model BEFORE the batch/main split - # so both paths inherit it. power<=1.0 = off. - if i2v_anchor_power and i2v_anchor_power > 1.0: - model = self._install_i2v_anchor(model, i2v_anchor_power, bool(i2v_anchor_first_frame_only)) - # Batch Training: Studio (the hub) packs N conditionings into positive, each scene entry # tagged 'funpack_batch_variant'. That marker is the only trigger — the sampler has no # batch-count input. Sample one chain per packed entry, persist each for rating in Studio.