Skip to content

Commit 95495d6

Browse files
committed
add last frame support
1 parent 311aa05 commit 95495d6

1 file changed

Lines changed: 21 additions & 4 deletions

File tree

nodes.py

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,8 @@ def INPUT_TYPES(s):
289289
},
290290
"optional": {
291291
"start_latent": ("LATENT", {"tooltip": "init Latents to use for image2video"} ),
292+
"end_latent": ("LATENT", {"tooltip": "end Latents to use for image2video"} ),
293+
"end_image_embeds": ("CLIP_VISION_OUTPUT", {"tooltip": "end Image's clip embeds"} ),
292294
"initial_samples": ("LATENT", {"tooltip": "init Latents to use for video2video"} ),
293295
"denoise_strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
294296
}
@@ -299,8 +301,8 @@ def INPUT_TYPES(s):
299301
FUNCTION = "process"
300302
CATEGORY = "FramePackWrapper"
301303

302-
def process(self, model, shift, positive, negative, latent_window_size, use_teacache, total_second_length, teacache_rel_l1_thresh, image_embeds, steps, cfg,
303-
guidance_scale, seed, sampler, gpu_memory_preservation, start_latent=None, initial_samples=None, denoise_strength=1.0):
304+
def process(self, model, shift, positive, negative, latent_window_size, use_teacache, total_second_length, teacache_rel_l1_thresh, image_embeds, steps, cfg,
305+
guidance_scale, seed, sampler, gpu_memory_preservation, start_latent=None, end_latent=None, end_image_embeds=None, initial_samples=None, denoise_strength=1.0):
304306
total_latent_sections = (total_second_length * 30) / (latent_window_size * 4)
305307
total_latent_sections = int(max(round(total_latent_sections), 1))
306308
print("total_latent_sections: ", total_latent_sections)
@@ -318,11 +320,20 @@ def process(self, model, shift, positive, negative, latent_window_size, use_teac
318320
start_latent = start_latent["samples"] * vae_scaling_factor
319321
if initial_samples is not None:
320322
initial_samples = initial_samples["samples"] * vae_scaling_factor
323+
if end_latent is not None:
324+
end_latent = end_latent["samples"] * vae_scaling_factor
325+
has_end_image = end_latent is not None
321326
print("start_latent", start_latent.shape)
322327
B, C, T, H, W = start_latent.shape
323328

324329
image_encoder_last_hidden_state = image_embeds["last_hidden_state"].to(base_dtype).to(device)
325330

331+
if has_end_image:
332+
assert end_image_embeds is not None
333+
end_image_encoder_last_hidden_state = end_image_embeds["last_hidden_state"].to(base_dtype).to(device)
334+
# Combine both image embeddings or use a weighted approach
335+
image_encoder_last_hidden_state = (image_encoder_last_hidden_state + end_image_encoder_last_hidden_state) / 2
336+
326337
llama_vec = positive[0][0].to(base_dtype).to(device)
327338
clip_l_pooler = positive[0][1]["pooled_output"].to(base_dtype).to(device)
328339

@@ -373,9 +384,10 @@ def process(self, model, shift, positive, negative, latent_window_size, use_teac
373384
for latent_padding in latent_paddings:
374385
print(f"latent_padding: {latent_padding}")
375386
is_last_section = latent_padding == 0
387+
is_first_section = latent_padding == latent_paddings[0]
376388
latent_padding_size = latent_padding * latent_window_size
377389

378-
print(f'latent_padding_size = {latent_padding_size}, is_last_section = {is_last_section}')
390+
print(f'latent_padding_size = {latent_padding_size}, is_last_section = {is_last_section}, is_first_section = {is_first_section}')
379391

380392
indices = torch.arange(0, sum([1, latent_padding_size, latent_window_size, 1, 2, 16])).unsqueeze(0)
381393
clean_latent_indices_pre, blank_indices, latent_indices, clean_latent_indices_post, clean_latent_2x_indices, clean_latent_4x_indices = indices.split([1, latent_padding_size, latent_window_size, 1, 2, 16], dim=1)
@@ -385,6 +397,11 @@ def process(self, model, shift, positive, negative, latent_window_size, use_teac
385397
clean_latents_post, clean_latents_2x, clean_latents_4x = history_latents[:, :, :1 + 2 + 16, :, :].split([1, 2, 16], dim=2)
386398
clean_latents = torch.cat([clean_latents_pre, clean_latents_post], dim=2)
387399

400+
# Use end image latent for the first section if provided
401+
if has_end_image and is_first_section:
402+
clean_latents_post = end_latent.to(history_latents)
403+
clean_latents = torch.cat([clean_latents_pre, clean_latents_post], dim=2)
404+
388405
#vid2vid
389406

390407
if initial_samples is not None:
@@ -455,7 +472,7 @@ def process(self, model, shift, positive, negative, latent_window_size, use_teac
455472
total_generated_latent_frames += int(generated_latents.shape[2])
456473
history_latents = torch.cat([generated_latents.to(history_latents), history_latents], dim=2)
457474

458-
real_history_latents = history_latents[:, :, :total_generated_latent_frames, :, :]
475+
real_history_latents = history_latents[:, :, :total_generated_latent_frames, :, :]
459476

460477
if is_last_section:
461478
break

0 commit comments

Comments
 (0)