maint: remove the mid-scene guide

Not used on H3, not used on LTX any more. Two widgets, the append method, the
Editor's continuity controls for it, and the auto-enable that turned it on for
every multi-scene carry chain.

JoyAI memory and carried i2v guides keep the guide-attention machinery they
share with it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
digital-garbage
2026-08-27 14:32:20 +03:00
co-authored by Claude Opus 5
parent aebc286042
commit 7537ec0bef
10 changed files with 12 additions and 158 deletions
-3
View File
@@ -201,7 +201,6 @@ _OWNED_BY = {
"joyai_frame_select": ("joyai_memory", None),
"joyai_memory_size": ("joyai_memory", None),
"joyai_memory_strength": ("joyai_memory", None),
"mid_scene_guide_strength": ("mid_scene_guide", None),
"negative_erase_mode": ("negative_erase", ('true',)),
"negative_erase_renorm": ("negative_erase", ('true',)),
"negative_erase_strength": ("negative_erase", ('true',)),
@@ -270,8 +269,6 @@ _EDITOR_DEFAULTS = {
"joyai_memory": False,
"joyai_memory_size": 7,
"joyai_memory_strength": 0.3,
"mid_scene_guide": False,
"mid_scene_guide_strength": 0.25,
"negative_erase": False,
"negative_erase_mode": "project",
"negative_erase_renorm": True,
-2
View File
@@ -83,8 +83,6 @@ def normalize_continuity_settings(raw: Optional[dict]) -> dict[str, Any]:
"identity_pin_strength": float(raw.get("identity_pin_strength", 0.35)),
"prior_scene_guides": bool(raw.get("prior_scene_guides", True)),
"prior_scene_strength": float(raw.get("prior_scene_strength", 0.35)),
"mid_scene_guide": bool(raw.get("mid_scene_guide", True)),
"mid_scene_guide_strength": float(raw.get("mid_scene_guide_strength", 0.3)),
"guide_decay": float(raw.get("guide_decay", 0.85)),
"solo_scene_guides": bool(raw.get("solo_scene_guides", True)),
}
+1 -14
View File
@@ -269,10 +269,6 @@
hint: "How much freedom the decoder gets while adding that detail. Higher looks more detailed but drifts further from what was actually generated. Only used when Decode noise scale is above 0." },
{ name: "decode_tile_size", label: "Decode tile size", kind: "int", default: 0, min: 0, max: 4096, step: 64,
hint: "Decodes the video in tiles instead of all at once, to fit in less VRAM. 0 is off — set it to 512 if decoding runs out of memory." },
{ name: "mid_scene_guide", label: "Mid-scene guide", kind: "bool", default: false,
hint: "Shows each scene the middle frame of the one before it, so people and layout stay put across a cut. Costs about 45% more time per scene, and JoyAI-Echo memory replaces it when that's on." },
{ name: "mid_scene_guide_strength", label: "Guide strength", kind: "float", default: 0.25, min: 0.0, max: 1.0, step: 0.05, dependsOn: "mid_scene_guide",
hint: "How hard that frame pulls. 0.25-0.35 is the measured band: below it the audio degrades and appearance drifts, above it the guide fights any real change of composition." },
{ name: "joyai_memory", label: "JoyAI-Echo memory", kind: "bool", default: false,
hint: "Keeps a bank of frames from earlier shots and shows them to every new scene, so a character stays the same across the whole video. Costs guide tokens (slower scenes), and takes over from Mid-scene guide." },
{ name: "joyai_memory_size", label: "Memory size", kind: "int", default: 7, min: 1, max: 32, step: 1, dependsOn: "joyai_memory",
@@ -387,8 +383,6 @@
identity_pin_strength: 0.35,
prior_scene_guides: true,
prior_scene_strength: 0.35,
mid_scene_guide: true,
mid_scene_guide_strength: 0.3,
guide_decay: 0.85,
solo_scene_guides: true,
};
@@ -401,8 +395,6 @@
identity_pin_strength: cs.identity_pin_strength != null ? +cs.identity_pin_strength : CONTINUITY_DEFAULTS.identity_pin_strength,
prior_scene_guides: cs.prior_scene_guides !== false,
prior_scene_strength: cs.prior_scene_strength != null ? +cs.prior_scene_strength : CONTINUITY_DEFAULTS.prior_scene_strength,
mid_scene_guide: cs.mid_scene_guide !== false,
mid_scene_guide_strength: cs.mid_scene_guide_strength != null ? +cs.mid_scene_guide_strength : CONTINUITY_DEFAULTS.mid_scene_guide_strength,
guide_decay: cs.guide_decay != null ? +cs.guide_decay : CONTINUITY_DEFAULTS.guide_decay,
solo_scene_guides: cs.solo_scene_guides !== false,
};
@@ -526,7 +518,7 @@
chain_timing: ["frame_overlap", "transition_duration", "use_same_seed", "cut_opening_frames"],
chain_guidance: ["cfg", "embed_guidance", "embed_guidance_source", "embed_guidance_strength", "score_slider", "score_slider_strength", "taste_nearest_prompt", "output_guidance", "output_guidance_strength", "dynashift", "dynashift_strength", "dynashift_threshold"],
chain_decode: ["decode_noise_scale", "decode_timestep", "decode_tile_size"],
chain_experimental: ["context_windows", "context_window_length", "context_window_overlap", "context_window_schedule", "context_window_fuse", "context_window_freenoise", "context_window_retain_first", "h3_audio_clock", "h3_video_detail", "segmented_detailing", "detail_targets", "detail_strength", "detail_threshold", "detail_max_area", "detail_mode", "detail_denoise", "mid_scene_guide", "mid_scene_guide_strength", "joyai_memory", "joyai_memory_size", "joyai_fix_frames", "joyai_frame_select", "joyai_memory_strength", "joyai_audio_memory", "v2a_grad_scale", "alg_blur_guides", "alg_guide_blur_strength", "alg_guide_blur_sigma_threshold", "bounded_attention_enabled", "identity_transfer_enabled", "source_id", "phase_scale", "id_strength", "arcface_mode", "debug_log"],
chain_experimental: ["context_windows", "context_window_length", "context_window_overlap", "context_window_schedule", "context_window_fuse", "context_window_freenoise", "context_window_retain_first", "h3_audio_clock", "h3_video_detail", "segmented_detailing", "detail_targets", "detail_strength", "detail_threshold", "detail_max_area", "detail_mode", "detail_denoise", "joyai_memory", "joyai_memory_size", "joyai_fix_frames", "joyai_frame_select", "joyai_memory_strength", "joyai_audio_memory", "v2a_grad_scale", "alg_blur_guides", "alg_guide_blur_strength", "alg_guide_blur_sigma_threshold", "bounded_attention_enabled", "identity_transfer_enabled", "source_id", "phase_scale", "id_strength", "arcface_mode", "debug_log"],
};
function countChainView(p, id, st) {
@@ -821,9 +813,6 @@
{ hint: "Lets each scene look at frames from the one before it, so the look carries down the chain." });
mk("Prior guides on solo mixed runs", cs.solo_scene_guides, "solo_scene_guides",
{ hint: "Does the same when you render a single scene out of a mixed timeline. Off, that scene uses only its own anchor." });
mk("Mid-scene layout guide (carry chains)", cs.mid_scene_guide, "mid_scene_guide",
{ disabled: !multiScene, title: multiScene ? "" : "Only applies to multi-scene carry chains",
hint: "Shows each scene the middle frame of the one before it, so people stay where they were. Only applies to multi-scene carry chains." });
const num = (label, val, key, min, max, step, hint) => {
const i = el("input"); i.type = "number"; i.min = String(min); i.max = String(max); i.step = String(step);
i.value = val; i.disabled = !cs.auto_enabled; i.dataset.k = "cs-" + key;
@@ -834,8 +823,6 @@
"How hard the identity pin pulls. Higher holds the face better and follows the prompt less.");
num("Prior guide strength", cs.prior_scene_strength, "prior_scene_strength", 0.0, 1.0, 0.05,
"How hard borrowed frames from earlier scenes pull. Higher keeps the look, lower lets each scene be its own shot.");
num("Mid-scene strength", cs.mid_scene_guide_strength, "mid_scene_guide_strength", 0.0, 1.0, 0.05,
"How hard the mid-scene layout frame pulls. 0.25-0.35 is the safe band — below it the audio degrades, above it the guide fights real changes of composition.");
num("Guide decay / scene", cs.guide_decay, "guide_decay", 0.5, 1, 0.05,
"How much weaker guides get with each scene further down the chain. 1.0 keeps them at full strength the whole way.");
-4
View File
@@ -733,10 +733,6 @@ def _run_sampler_inputs(
if scene_count > 1 and not guides:
samp["carry_i2v_guides"] = True
if cs["auto_enabled"] and scene_count > 1 and cs["mid_scene_guide"]:
samp["mid_scene_guide"] = True
samp["mid_scene_guide_strength"] = cs["mid_scene_guide_strength"]
return samp
+1 -1
View File
@@ -175,7 +175,7 @@ def test_simple_mode_leaves_everything_that_is_not_refinement_alone():
and the second pass in particular was allowed by Easy Gen, which this mode replaced."""
on = {
"second_pass": True, "second_pass_op": "upscale_2x",
"mid_scene_guide": True, "joyai_memory": True, "joyai_audio_memory": True,
"joyai_memory": True, "joyai_audio_memory": True,
"carry_i2v_guides": True, "alg_anchor": True, "alg_blur_guides": True,
"bounded_attention_enabled": True, "identity_transfer_enabled": True,
"segmented_detailing": True, "context_windows": True,
-11
View File
@@ -157,17 +157,6 @@ def test_mixed_solo_sampler_inputs():
assert guides["scenes"][0][0]["media_ref"] == "img1"
def test_carry_chain_auto_mid_scene_guide():
import json
full = _project(scenes=[
{"id": "s1", "text": "a"},
{"id": "s2", "text": "b", "source": {"type": "carry"}},
])
samp = _run_sampler_inputs(full, 2, full=full)
assert samp["mid_scene_guide"] is True
assert samp["carry_i2v_guides"] is False
guides = json.loads(samp["funpack_scene_guides"])
assert guides["scenes"][1][0]["source"] == "template"
def test_identity_pin_media_refs_without_mixed_anchors():
-1
View File
@@ -271,7 +271,6 @@ def test_continuity_defaults_auto_on():
cs = normalize_continuity_settings({})
assert cs["auto_enabled"] is True
assert cs["prior_scene_guides"] is True
assert cs["mid_scene_guide"] is True
def test_auto_continuity_solo_image_no_prior_guides():
+10 -111
View File
@@ -1157,7 +1157,7 @@ def _alg_blur_frames(model, latent_image, kappa, frame_indices=(), tail_count=0)
`frame_indices` is any iterable of frame indices within the video stream's T dimension to
blur (each filtered independently) — frame 0 for the genuine i2v anchor, and/or the trailing
indices of newly-appended guide-attention frames (mid_scene_guide / carry_i2v_guides-as-guide /
indices of newly-appended guide-attention frames (carry_i2v_guides-as-guide /
configured guides / JoyAI memory — see EXPERIMENTAL alg_blur_guides) when extending the same
idea to those. Indices outside the actual frame count are silently skipped.
@@ -2358,7 +2358,7 @@ def sample_funpack_distilled_flow(model, x, sigmas, extra_args=None, callback=No
no i2v anchor (denoise_mask is None) or the packed latent layout can't be read.
- EXPERIMENTAL alg_guide_tail_frames (>0 extends the same idea, not from the paper):
additionally blurs that many trailing video frames — the newly-appended guide-
attention frames this scene (mid_scene_guide / carry_i2v_guides-as-guide /
attention frames this scene (carry_i2v_guides-as-guide /
configured guides / JoyAI memory), set by the Scene Chain Sampler's alg_blur_guides
toggle right before this chunk's sample call. 0 = untouched (default). Standalone:
works with alg_enabled off (anchor stays sharp, only the guide tail is blurred), with
@@ -2867,14 +2867,6 @@ class FunPackLTXAVSceneChainSampler:
"default": False,
"tooltip": "Carry protected frames from latent_template noise_mask into each continuation chunk as a style guide.",
}),
"mid_scene_guide": ("BOOLEAN", {
"default": False,
"tooltip": "Experimental: append the middle frame of the previous scene as a guide for the current scene via LTX guide attention. Helps maintain character positioning across scenes.",
}),
"mid_scene_guide_strength": ("FLOAT", {
"default": 0.25, "min": 0.0, "max": 1.0, "step": 0.05,
"tooltip": "Guide attention strength for mid-scene anchor. Full 0..1 range. 0.25-0.35 is the measured sweet spot: below 0.25 audio degrades and character appearance drifts, above 0.35 spatial conflicts appear when scene composition shifts. Outside that band is yours to explore — 0 disables the guide's pull entirely.",
}),
"embed_guidance": ("BOOLEAN", {
"default": False,
"tooltip": "Apply the Refiner's learned quality direction at each denoising step, not just once before sampling. Requires refinement_key_input and enough liked generations to have a direction. Adds ~20-30% inference overhead.",
@@ -2922,7 +2914,7 @@ class FunPackLTXAVSceneChainSampler:
# mapping and lands a numeric on a combo (e.g. joyai_frame_select got 0).
"joyai_memory": ("BOOLEAN", {
"default": False,
"tooltip": "JoyAI-Echo cross-shot memory bank. REQUIRES the JoyAI-Echo LoRA — without it the injected memory frames change nothing, because the base model was never trained to read them as memory. Generalizes mid_scene_guide from one anchor to a managed set of clean prior-shot frames injected into each scene via LTX guide attention, so character/scene identity carries across the whole chain (JoyAI-Echo's story-level consistency). The first joyai_fix_frames scenes are pinned permanently as a global anchor; the rest is a rolling most-recent window capped at joyai_memory_size. Supersedes mid_scene_guide when on. Video memory only; pair it with joyai_audio_memory for the soundtrack.",
"tooltip": "JoyAI-Echo cross-shot memory bank. REQUIRES the JoyAI-Echo LoRA — without it the injected memory frames change nothing, because the base model was never trained to read them as memory. Injects a managed set of clean prior-shot frames injected into each scene via LTX guide attention, so character/scene identity carries across the whole chain (JoyAI-Echo's story-level consistency). The first joyai_fix_frames scenes are pinned permanently as a global anchor; the rest is a rolling most-recent window capped at joyai_memory_size. Video memory only; pair it with joyai_audio_memory for the soundtrack.",
}),
"joyai_memory_size": ("INT", {
"default": 7, "min": 1, "max": 32,
@@ -2938,7 +2930,7 @@ class FunPackLTXAVSceneChainSampler:
}),
"joyai_memory_strength": ("FLOAT", {
"default": 0.3, "min": 0.25, "max": 10.0, "step": 0.05,
"tooltip": "Guide-attention strength for each memory frame. 0.25 floor as mid_scene_guide (below it audio degrades and identity drifts). Uncapped at the top: 0.25-0.5 is the audio-safe band, higher values push identity harder but may degrade audio/over-constrain motion.",
"tooltip": "Guide-attention strength for each memory frame. 0.25 floor (below it audio degrades and identity drifts). Uncapped at the top: 0.25-0.5 is the audio-safe band, higher values push identity harder but may degrade audio/over-constrain motion.",
}),
# NOTE: append-only — keep new sampler widgets at the END of this block so the
# builder's positional reference-workflow mapping (extract_widgets) stays aligned.
@@ -2979,7 +2971,7 @@ class FunPackLTXAVSceneChainSampler:
}),
"alg_blur_guides": ("BOOLEAN", {
"default": False,
"tooltip": "EXPERIMENTAL: extends ALG (see alg_anchor) from just the i2v anchor to also blur newly-appended guide-attention frames this scene (mid_scene_guide / carry_i2v_guides-as-guide / configured per-scene guides / JoyAI memory), for the same early steps. Standalone: works even with the anchor blur off (anchor stays sharp), with its own alg_guide_blur_strength / alg_guide_blur_sigma_threshold controls below. Works with ANY wired sampler — inside the loop on FunPack Distilled Flow, and through a denoiser proxy (same sigma schedule, same result) on everything else. No effect if no guide frames were appended this scene.",
"tooltip": "EXPERIMENTAL: extends ALG (see alg_anchor) from just the i2v anchor to also blur newly-appended guide-attention frames this scene (carry_i2v_guides-as-guide / configured per-scene guides / JoyAI memory), for the same early steps. Standalone: works even with the anchor blur off (anchor stays sharp), with its own alg_guide_blur_strength / alg_guide_blur_sigma_threshold controls below. Works with ANY wired sampler — inside the loop on FunPack Distilled Flow, and through a denoiser proxy (same sigma schedule, same result) on everything else. No effect if no guide frames were appended this scene.",
}),
"bounded_attention_enabled": ("BOOLEAN", {
"default": False,
@@ -4530,7 +4522,6 @@ class FunPackLTXAVSceneChainSampler:
boundaries,
scene_runs,
carry_i2v_guides,
mid_scene_guide,
embed_guidance,
embed_guidance_strength,
embed_guidance_source,
@@ -4568,12 +4559,6 @@ class FunPackLTXAVSceneChainSampler:
"note": "Scene 1 template frames are prepended as hidden guide tokens in continuation chunks only — "
"does not inject scene 2 into scene 1.",
})
if mid_scene_guide:
global_steering.append({
"mechanism": "mid_scene_guide",
"scope": "scene_2_onward",
"note": "Middle frame of scene N guides scene N+1 denoising — does not retroactively change scene N.",
})
global_steering.append({
"mechanism": "studio_absolute_steer",
"scope": "all_scenes_pre_sample",
@@ -6037,84 +6022,6 @@ class FunPackLTXAVSceneChainSampler:
tail_crop += tail
return chunk, positive, negative, head_crop, tail_crop, identity_ref_filename
def _append_mid_scene_guide(self, chunk, previous_output, positive, negative, vae, strength):
"""Append the middle frame of the previous scene as a guide for the current chunk
using LTX's guide attention mechanism (keyframe_idxs + guide_attention_entries).
Audio-safe: appends only to the video tensor, guide tokens influence denoising
through attention weights rather than overwriting hidden states."""
prev_tensors = self._latent_tensors(previous_output)
chunk_tensors = self._latent_tensors(chunk)
if not prev_tensors or not chunk_tensors:
return chunk, positive, negative, 0
# Middle frame of previous scene as guide source
F_prev = self._tensor_frames(prev_tensors[0])
guide_frame = self._time_slice(prev_tensors[0], F_prev // 2, F_prev // 2 + 1)
guide_frame = guide_frame.to(device=chunk_tensors[0].device, dtype=chunk_tensors[0].dtype)
if self._is_h3:
# A mid-clip pin is not something H3's packed layout can place, and the LTX path
# below would append a latent frame off its grid rather than refuse. Routed
# through the keyframe path so it declines by the same rule, and says so.
positive, negative, tail = self._append_h3_keyframe(
guide_frame, max(1, int(self._h3_frame_count)) // 2, strength,
positive, negative)
return chunk, positive, negative, tail
# LTX from here down. Imported after the H3 branch so the H3 path does not depend on
# an LTX-only module importing.
try:
from comfy_extras.nodes_lt import LTXVAddGuide, _append_guide_attention_entry
except ImportError as _e:
_log.failed("FunPackSceneChain", "mid-scene guide (ComfyUI LTX guide API)", _e,
"the scene renders with NO mid-scene guide")
return chunk, positive, negative, 0
# Target temporal position: middle of current chunk in pixel space
F_chunk = self._tensor_frames(chunk_tensors[0])
mid_chunk = F_chunk // 2
scale_factors = getattr(vae, 'downscale_index_formula', [8, 8, 8])
time_scale = int(scale_factors[0]) if hasattr(scale_factors, '__getitem__') else 8
causal_fix = (mid_chunk == 0)
pixel_frame_idx = 0 if causal_fix else 1 + (mid_chunk - 1) * time_scale
# Add keyframe positional indices to conditioning
positive = LTXVAddGuide.add_keyframe_index(
positive, pixel_frame_idx, guide_frame, scale_factors, causal_fix=causal_fix
)
negative = LTXVAddGuide.add_keyframe_index(
negative, pixel_frame_idx, guide_frame, scale_factors, causal_fix=causal_fix
)
# Register guide attention entry (strength controls how strongly noisy frames
# attend to the guide tokens vs. ignoring them)
guide_latent_shape = [guide_frame.shape[2], guide_frame.shape[3], guide_frame.shape[4]]
pre_filter_count = guide_frame.shape[2] * guide_frame.shape[3] * guide_frame.shape[4]
positive, negative = _append_guide_attention_entry(
positive, negative, pre_filter_count, guide_latent_shape, strength=float(strength)
)
# Append guide frame to video tensor (mask = 1-strength, partially pinned)
result = self._clone_latent(chunk)
tensors = self._latent_tensors(result)
masks = self._latent_masks(result, len(tensors))
if masks[0] is None:
masks[0] = torch.ones(
tensors[0].shape[0], 1, tensors[0].shape[2], 1, 1,
dtype=torch.float32, device=tensors[0].device,
)
guide_mask = torch.full_like(masks[0][:, :, :1], max(0.0, 1.0 - float(strength)))
tensors[0] = torch.cat([tensors[0], guide_frame], dim=2)
masks[0] = torch.cat([masks[0], guide_mask.to(masks[0].device, masks[0].dtype)], dim=2)
if self._is_nested(result.get("samples")):
result["samples"] = comfy.nested_tensor.NestedTensor(tensors)
result["noise_mask"] = comfy.nested_tensor.NestedTensor(masks)
else:
result["samples"] = tensors[0]
result["noise_mask"] = masks[0]
return result, positive, negative, 1
def _harvest_joyai_frame(self, sampled, select):
"""Pick one clean latent frame from a finished scene for the memory bank.
@@ -6136,7 +6043,7 @@ class FunPackLTXAVSceneChainSampler:
def _append_joyai_memory_guides(self, chunk, frames, positive, negative, vae, strength):
"""JoyAI-Echo memory injection: attach every banked prior-shot frame to the current chunk
as a clean LTX guide, so attention carries identity/scene forward across the whole chain.
The single-anchor mid_scene_guide generalized to N frames — reuses _append_guide_latent
N clean prior-shot frames — reuses _append_guide_latent
per entry. Memory frames are placed at distinct early (prefix) positions, matching JoyAI's
sequence-prefix concat. Audio-safe (guide tokens influence via attention, not overwrite).
Returns the total appended-frame count so the caller crops them off the output tail."""
@@ -6964,7 +6871,6 @@ class FunPackLTXAVSceneChainSampler:
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,
mid_scene_guide=False, mid_scene_guide_strength=0.4,
joyai_memory=False, joyai_memory_size=7, joyai_fix_frames=3,
joyai_frame_select="center", joyai_memory_strength=0.3,
joyai_audio_memory=False, v2a_grad_scale=1.0,
@@ -7169,7 +7075,7 @@ class FunPackLTXAVSceneChainSampler:
return self._run_batch_training(
model, vae, positive, negative, sampler, sigmas, seed, latent_template,
num_frames_per_scene, frame_overlap, cfg, max_scenes, use_same_seed,
carry_i2v_guides, mid_scene_guide, mid_scene_guide_strength,
carry_i2v_guides,
embed_guidance, embed_guidance_strength, transition_duration,
decode_tile_size, refinement_key_input, embed_guidance_source,
score_slider, score_slider_strength,
@@ -7495,11 +7401,6 @@ class FunPackLTXAVSceneChainSampler:
chunk, audio_tail = self._append_joyai_audio_memory(chunk, joyai_bank.audio())
if audio_tail > 0:
run_mechanisms.append(f"joyai_audio_memory({audio_tail})")
elif mid_scene_guide and not custom_guides:
run_mechanisms.append("mid_scene_guide")
chunk, scene_positive, scene_negative, guide_tail = self._append_mid_scene_guide(
chunk, output, scene_positive, scene_negative, vae, mid_scene_guide_strength,
)
elif not custom_guides:
guide_tail = 0
@@ -7752,7 +7653,7 @@ class FunPackLTXAVSceneChainSampler:
"previous scene, not an anchor, and cutting them would break "
"the join with it")
elif guide_tail > 0 or audio_tail > 0:
_reason = ("scene is carrying appended frames (mid_scene_guide / carried "
_reason = ("scene is carrying appended frames (carried "
"i2v guides / JoyAI audio memory) that are stripped after "
"sampling — the audio crop is derived from the video length, "
"which those extra frames would make wrong")
@@ -8207,7 +8108,6 @@ class FunPackLTXAVSceneChainSampler:
boundaries=boundary_entries,
scene_runs=scene_runs,
carry_i2v_guides=bool(carry_i2v_guides),
mid_scene_guide=bool(mid_scene_guide),
embed_guidance=bool(embed_guidance),
embed_guidance_strength=float(embed_guidance_strength),
embed_guidance_source=str(embed_guidance_source or "relative"),
@@ -8373,7 +8273,7 @@ class FunPackLTXAVSceneChainSampler:
def _run_batch_training(self, model, vae, positive, negative, sampler, sigmas, seed,
latent_template, num_frames_per_scene, frame_overlap, cfg, max_scenes,
use_same_seed, carry_i2v_guides, mid_scene_guide, mid_scene_guide_strength,
use_same_seed, carry_i2v_guides,
embed_guidance, embed_guidance_strength, transition_duration,
decode_tile_size, refinement_key_input, embed_guidance_source="relative",
score_slider=False, score_slider_strength=1.0,
@@ -8429,8 +8329,7 @@ class FunPackLTXAVSceneChainSampler:
out = self.sample(
model, vae, pos_i, negative, sampler, sigmas, iter_seed, latent_template,
num_frames_per_scene, frame_overlap, cfg, max_scenes, use_same_seed=use_same_seed,
carry_i2v_guides=carry_i2v_guides, mid_scene_guide=mid_scene_guide,
mid_scene_guide_strength=mid_scene_guide_strength, embed_guidance=embed_guidance,
carry_i2v_guides=carry_i2v_guides, embed_guidance=embed_guidance,
embed_guidance_strength=embed_guidance_strength, embed_guidance_source=embed_guidance_source,
score_slider=score_slider, score_slider_strength=score_slider_strength,
joyai_memory=joyai_memory, joyai_memory_size=joyai_memory_size,
-10
View File
@@ -643,16 +643,6 @@ def test_holding_the_reference_outranks_continuing_from_the_last_shot():
assert float(_pins(out)[0]["latent"].max()) == 5.0
def test_mid_scene_guide_declines_on_h3_instead_of_damaging_the_latent(capsys):
"""H3's packed layout places a pin at the first or last frame, nowhere between."""
node = h3_node(frame_count=124)
chunk = av_latent(video_t=37)
before = chunk["samples"].unbind()[0].shape
out_chunk, positive, _neg, tail = node._append_mid_scene_guide(
chunk, av_latent(video_t=37), [[torch.zeros(1, 8, 16), {}]], None, LTXVAE(), 1.0)
assert out_chunk["samples"].unbind()[0].shape == before
assert tail == 0 and _pins(positive) == []
assert "pins only the first" in capsys.readouterr().out
# ── pins vs a resolution-changing second pass ────────────────────────────────
-1
View File
@@ -480,7 +480,6 @@ def test_overlap_diagnostics_report_latent_blend_zone():
{"index": 2, "text": "hero runs", "encode_text": "hero runs", "mechanisms": ["latent_overlap(16px)"]},
],
carry_i2v_guides=True,
mid_scene_guide=False,
embed_guidance=True,
embed_guidance_strength=0.15,
embed_guidance_source="absolute",