Fabrice-TIERCELIN commited on
Commit
51a3a31
·
verified ·
1 Parent(s): a78dc3e

Before merge

Browse files
Files changed (1) hide show
  1. app.py +106 -535
app.py CHANGED
@@ -7,23 +7,15 @@ os.environ['HF_HOME'] = os.path.abspath(os.path.realpath(os.path.join(os.path.di
7
  try:
8
  import spaces
9
  except:
10
- class spaces():
11
- def GPU(*args, **kwargs):
12
- def decorator(function):
13
- def new_function(*dummy_args, **dummy_kwargs):
14
- return function(*dummy_args, **dummy_kwargs)
15
- return new_function
16
- return decorator
17
-
18
  import gradio as gr
19
  import torch
20
  import traceback
21
  import einops
22
  import safetensors.torch as sf
 
23
  import random
24
  import time
25
- import numpy as np
26
- import argparse
27
  import math
28
  # 20250506 pftq: Added for video input loading
29
  import decord
@@ -46,76 +38,74 @@ from diffusers_helper.hunyuan import encode_prompt_conds, vae_decode, vae_encode
46
  from diffusers_helper.utils import save_bcthw_as_mp4, crop_or_pad_yield_mask, soft_append_bcthw, resize_and_center_crop, state_dict_weighted_merge, state_dict_offset_merge, generate_timestamp
47
  from diffusers_helper.models.hunyuan_video_packed import HunyuanVideoTransformer3DModelPacked
48
  from diffusers_helper.pipelines.k_diffusion_hunyuan import sample_hunyuan
49
- from diffusers_helper.memory import cpu, gpu, get_cuda_free_memory_gb, move_model_to_device_with_memory_preservation, offload_model_from_device_for_memory_preservation, fake_diffusers_current_device, DynamicSwapInstaller, unload_complete_models, load_model_as_complete
 
50
  from diffusers_helper.thread_utils import AsyncStream, async_run
51
  from diffusers_helper.gradio.progress_bar import make_progress_bar_css, make_progress_bar_html
52
  from transformers import SiglipImageProcessor, SiglipVisionModel
53
  from diffusers_helper.clip_vision import hf_clip_vision_encode
54
  from diffusers_helper.bucket_tools import find_nearest_bucket
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
 
56
- parser = argparse.ArgumentParser()
57
- parser.add_argument('--share', action='store_true')
58
- parser.add_argument("--server", type=str, default='0.0.0.0')
59
- parser.add_argument("--port", type=int, required=False)
60
- parser.add_argument("--inbrowser", action='store_true')
61
- args = parser.parse_args()
62
-
63
- # for win desktop probably use --server 127.0.0.1 --inbrowser
64
- # For linux server probably use --server 127.0.0.1 or do not use any cmd flags
65
- print(args)
66
-
67
- free_mem_gb = get_cuda_free_memory_gb(gpu)
68
- high_vram = free_mem_gb > 60
69
-
70
- print(f'Free VRAM {free_mem_gb} GB')
71
- print(f'High-VRAM Mode: {high_vram}')
72
-
73
- text_encoder = LlamaModel.from_pretrained("hunyuanvideo-community/HunyuanVideo", subfolder='text_encoder', torch_dtype=torch.float16).cpu()
74
- text_encoder_2 = CLIPTextModel.from_pretrained("hunyuanvideo-community/HunyuanVideo", subfolder='text_encoder_2', torch_dtype=torch.float16).cpu()
75
- tokenizer = LlamaTokenizerFast.from_pretrained("hunyuanvideo-community/HunyuanVideo", subfolder='tokenizer')
76
- tokenizer_2 = CLIPTokenizer.from_pretrained("hunyuanvideo-community/HunyuanVideo", subfolder='tokenizer_2')
77
- vae = AutoencoderKLHunyuanVideo.from_pretrained("hunyuanvideo-community/HunyuanVideo", subfolder='vae', torch_dtype=torch.float16).cpu()
78
-
79
- feature_extractor = SiglipImageProcessor.from_pretrained("lllyasviel/flux_redux_bfl", subfolder='feature_extractor')
80
- image_encoder = SiglipVisionModel.from_pretrained("lllyasviel/flux_redux_bfl", subfolder='image_encoder', torch_dtype=torch.float16).cpu()
81
-
82
- transformer = HunyuanVideoTransformer3DModelPacked.from_pretrained('lllyasviel/FramePackI2V_HY', torch_dtype=torch.bfloat16).cpu()
83
-
84
- vae.eval()
85
- text_encoder.eval()
86
- text_encoder_2.eval()
87
- image_encoder.eval()
88
- transformer.eval()
89
-
90
- if not high_vram:
91
- vae.enable_slicing()
92
- vae.enable_tiling()
93
-
94
- transformer.high_quality_fp32_output_for_inference = True
95
- print('transformer.high_quality_fp32_output_for_inference = True')
96
-
97
- transformer.to(dtype=torch.bfloat16)
98
- vae.to(dtype=torch.float16)
99
- image_encoder.to(dtype=torch.float16)
100
- text_encoder.to(dtype=torch.float16)
101
- text_encoder_2.to(dtype=torch.float16)
102
-
103
- vae.requires_grad_(False)
104
- text_encoder.requires_grad_(False)
105
- text_encoder_2.requires_grad_(False)
106
- image_encoder.requires_grad_(False)
107
- transformer.requires_grad_(False)
108
-
109
- if not high_vram:
110
- # DynamicSwapInstaller is same as huggingface's enable_sequential_offload but 3x faster
111
- DynamicSwapInstaller.install_model(transformer, device=gpu)
112
- DynamicSwapInstaller.install_model(text_encoder, device=gpu)
113
- else:
114
- text_encoder.to(gpu)
115
- text_encoder_2.to(gpu)
116
- image_encoder.to(gpu)
117
- vae.to(gpu)
118
- transformer.to(gpu)
119
 
120
  stream = AsyncStream()
121
 
@@ -124,7 +114,6 @@ os.makedirs(outputs_folder, exist_ok=True)
124
 
125
  input_image_debug_value = [None]
126
  input_video_debug_value = [None]
127
- end_image_debug_value = [None]
128
  prompt_debug_value = [None]
129
  total_second_length_debug_value = [None]
130
 
@@ -319,7 +308,7 @@ def set_mp4_comments_imageio_ffmpeg(input_file, comments):
319
  return False
320
 
321
  @torch.no_grad()
322
- def worker(input_image, image_position, end_image, prompts, n_prompt, seed, total_second_length, latent_window_size, steps, cfg, gs, rs, gpu_memory_preservation, enable_preview, use_teacache, mp4_crf, fps_number):
323
  def encode_prompt(prompt, n_prompt):
324
  llama_vec, clip_l_pooler = encode_prompt_conds(prompt, text_encoder, text_encoder_2, tokenizer, tokenizer_2)
325
 
@@ -588,275 +577,6 @@ def worker(input_image, image_position, end_image, prompts, n_prompt, seed, tota
588
  stream.output_queue.push(('end', None))
589
  return
590
 
591
- @torch.no_grad()
592
- def worker_start_end(input_image, image_position, end_image, prompts, n_prompt, seed, total_second_length, latent_window_size, steps, cfg, gs, rs, gpu_memory_preservation, enable_preview, use_teacache, mp4_crf, fps_number):
593
- def encode_prompt(prompt, n_prompt):
594
- llama_vec, clip_l_pooler = encode_prompt_conds(prompt, text_encoder, text_encoder_2, tokenizer, tokenizer_2)
595
-
596
- if cfg == 1:
597
- llama_vec_n, clip_l_pooler_n = torch.zeros_like(llama_vec), torch.zeros_like(clip_l_pooler)
598
- else:
599
- llama_vec_n, clip_l_pooler_n = encode_prompt_conds(n_prompt, text_encoder, text_encoder_2, tokenizer, tokenizer_2)
600
-
601
- llama_vec, llama_attention_mask = crop_or_pad_yield_mask(llama_vec, length=512)
602
- llama_vec_n, llama_attention_mask_n = crop_or_pad_yield_mask(llama_vec_n, length=512)
603
-
604
- llama_vec = llama_vec.to(transformer.dtype)
605
- llama_vec_n = llama_vec_n.to(transformer.dtype)
606
- clip_l_pooler = clip_l_pooler.to(transformer.dtype)
607
- clip_l_pooler_n = clip_l_pooler_n.to(transformer.dtype)
608
- return [llama_vec, clip_l_pooler, llama_vec_n, clip_l_pooler_n, llama_attention_mask, llama_attention_mask_n]
609
-
610
- total_latent_sections = (total_second_length * fps_number) / (latent_window_size * 4)
611
- total_latent_sections = int(max(round(total_latent_sections), 1))
612
-
613
- job_id = generate_timestamp()
614
-
615
- stream.output_queue.push(('progress', (None, '', make_progress_bar_html(0, 'Starting ...'))))
616
-
617
- try:
618
- # Clean GPU
619
- if not high_vram:
620
- unload_complete_models(
621
- text_encoder, text_encoder_2, image_encoder, vae, transformer
622
- )
623
-
624
- # Text encoding
625
-
626
- stream.output_queue.push(('progress', (None, '', make_progress_bar_html(0, 'Text encoding ...'))))
627
-
628
- if not high_vram:
629
- fake_diffusers_current_device(text_encoder, gpu) # since we only encode one text - that is one model move and one encode, offload is same time consumption since it is also one load and one encode.
630
- load_model_as_complete(text_encoder_2, target_device=gpu)
631
-
632
-
633
- prompt_parameters = []
634
-
635
- for prompt_part in prompts[:total_latent_sections]:
636
- prompt_parameters.append(encode_prompt(prompt_part, n_prompt))
637
-
638
- # Clean GPU
639
- if not high_vram:
640
- unload_complete_models(
641
- text_encoder, text_encoder_2
642
- )
643
-
644
- # Processing input image (start frame)
645
- stream.output_queue.push(('progress', (None, '', make_progress_bar_html(0, 'Processing start frame ...'))))
646
-
647
- H, W, C = input_image.shape
648
- height, width = find_nearest_bucket(H, W, resolution=640)
649
- input_image_np = resize_and_center_crop(input_image, target_width=width, target_height=height)
650
-
651
- Image.fromarray(input_image_np).save(os.path.join(outputs_folder, f'{job_id}_start.png'))
652
-
653
- input_image_pt = torch.from_numpy(input_image_np).float() / 127.5 - 1
654
- input_image_pt = input_image_pt.permute(2, 0, 1)[None, :, None]
655
-
656
- # Processing end image (if provided)
657
- has_end_image = end_image is not None
658
- if has_end_image:
659
- stream.output_queue.push(('progress', (None, '', make_progress_bar_html(0, 'Processing end frame ...'))))
660
-
661
- H_end, W_end, C_end = end_image.shape
662
- end_image_np = resize_and_center_crop(end_image, target_width=width, target_height=height)
663
-
664
- Image.fromarray(end_image_np).save(os.path.join(outputs_folder, f'{job_id}_end.png'))
665
-
666
- end_image_pt = torch.from_numpy(end_image_np).float() / 127.5 - 1
667
- end_image_pt = end_image_pt.permute(2, 0, 1)[None, :, None]
668
-
669
- # VAE encoding
670
- stream.output_queue.push(('progress', (None, '', make_progress_bar_html(0, 'VAE encoding ...'))))
671
-
672
- if not high_vram:
673
- load_model_as_complete(vae, target_device=gpu)
674
-
675
- start_latent = vae_encode(input_image_pt, vae)
676
-
677
- if has_end_image:
678
- end_latent = vae_encode(end_image_pt, vae)
679
-
680
- # CLIP Vision
681
- stream.output_queue.push(('progress', (None, '', make_progress_bar_html(0, 'CLIP Vision encoding ...'))))
682
-
683
- if not high_vram:
684
- load_model_as_complete(image_encoder, target_device=gpu)
685
-
686
- image_encoder_output = hf_clip_vision_encode(input_image_np, feature_extractor, image_encoder)
687
- image_encoder_last_hidden_state = image_encoder_output.last_hidden_state
688
-
689
- if has_end_image:
690
- end_image_encoder_output = hf_clip_vision_encode(end_image_np, feature_extractor, image_encoder)
691
- end_image_encoder_last_hidden_state = end_image_encoder_output.last_hidden_state
692
- # Combine both image embeddings or use a weighted approach
693
- image_encoder_last_hidden_state = (image_encoder_last_hidden_state + end_image_encoder_last_hidden_state) / 2
694
-
695
- # Clean GPU
696
- if not high_vram:
697
- unload_complete_models(
698
- image_encoder
699
- )
700
-
701
- # Dtype
702
- image_encoder_last_hidden_state = image_encoder_last_hidden_state.to(transformer.dtype)
703
-
704
- # Sampling
705
- stream.output_queue.push(('progress', (None, '', make_progress_bar_html(0, 'Start sampling ...'))))
706
-
707
- rnd = torch.Generator("cpu").manual_seed(seed)
708
- num_frames = latent_window_size * 4 - 3
709
-
710
- history_latents = torch.zeros(size=(1, 16, 1 + 2 + 16, height // 8, width // 8), dtype=torch.float32, device=cpu)
711
- start_latent = start_latent.to(history_latents)
712
- if has_end_image:
713
- end_latent = end_latent.to(history_latents)
714
-
715
- history_pixels = None
716
- total_generated_latent_frames = 0
717
-
718
- if total_latent_sections > 4:
719
- # In theory the latent_paddings should follow the above sequence, but it seems that duplicating some
720
- # items looks better than expanding it when total_latent_sections > 4
721
- # One can try to remove below trick and just
722
- # use `latent_paddings = list(reversed(range(total_latent_sections)))` to compare
723
- latent_paddings = [3] + [2] * (total_latent_sections - 3) + [1, 0]
724
- else:
725
- # Convert an iterator to a list
726
- latent_paddings = list(range(total_latent_sections - 1, -1, -1))
727
-
728
- if enable_preview:
729
- def callback(d):
730
- preview = d['denoised']
731
- preview = vae_decode_fake(preview)
732
-
733
- preview = (preview * 255.0).detach().cpu().numpy().clip(0, 255).astype(np.uint8)
734
- preview = einops.rearrange(preview, 'b c t h w -> (b h) (t w) c')
735
-
736
- if stream.input_queue.top() == 'end':
737
- stream.output_queue.push(('end', None))
738
- raise KeyboardInterrupt('User ends the task.')
739
-
740
- current_step = d['i'] + 1
741
- percentage = int(100.0 * current_step / steps)
742
- hint = f'Sampling {current_step}/{steps}'
743
- desc = f'Total generated frames: {int(max(0, total_generated_latent_frames * 4 - 3))}, Video length: {max(0, (total_generated_latent_frames * 4 - 3) / fps_number) :.2f} seconds (FPS-30), Resolution: {height}px * {width}px. The video is being extended now ...'
744
- stream.output_queue.push(('progress', (preview, desc, make_progress_bar_html(percentage, hint))))
745
- return
746
- else:
747
- def callback(d):
748
- return
749
-
750
- for latent_padding in latent_paddings:
751
- is_last_section = latent_padding == 0
752
- is_first_section = latent_padding == latent_paddings[0]
753
- latent_padding_size = latent_padding * latent_window_size
754
-
755
- if stream.input_queue.top() == 'end':
756
- stream.output_queue.push(('end', None))
757
- return
758
-
759
- print(f'latent_padding_size = {latent_padding_size}, is_last_section = {is_last_section}, is_first_section = {is_first_section}')
760
-
761
- if len(prompt_parameters) > 0:
762
- [llama_vec, clip_l_pooler, llama_vec_n, clip_l_pooler_n, llama_attention_mask, llama_attention_mask_n] = prompt_parameters.pop(len(prompt_parameters) - 1)
763
-
764
- indices = torch.arange(1 + latent_padding_size + latent_window_size + 1 + 2 + 16).unsqueeze(0)
765
- 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)
766
- clean_latent_indices = torch.cat([clean_latent_indices_pre, clean_latent_indices_post], dim=1)
767
-
768
- clean_latents_post, clean_latents_2x, clean_latents_4x = history_latents[:, :, :1 + 2 + 16, :, :].split([1, 2, 16], dim=2)
769
-
770
- # Use end image latent for the first section if provided
771
- if has_end_image and is_first_section:
772
- clean_latents_post = end_latent
773
-
774
- clean_latents = torch.cat([start_latent, clean_latents_post], dim=2)
775
-
776
- if not high_vram:
777
- unload_complete_models()
778
- move_model_to_device_with_memory_preservation(transformer, target_device=gpu, preserved_memory_gb=gpu_memory_preservation)
779
-
780
- if use_teacache:
781
- transformer.initialize_teacache(enable_teacache=True, num_steps=steps)
782
- else:
783
- transformer.initialize_teacache(enable_teacache=False)
784
-
785
- generated_latents = sample_hunyuan(
786
- transformer=transformer,
787
- sampler='unipc',
788
- width=width,
789
- height=height,
790
- frames=num_frames,
791
- real_guidance_scale=cfg,
792
- distilled_guidance_scale=gs,
793
- guidance_rescale=rs,
794
- # shift=3.0,
795
- num_inference_steps=steps,
796
- generator=rnd,
797
- prompt_embeds=llama_vec,
798
- prompt_embeds_mask=llama_attention_mask,
799
- prompt_poolers=clip_l_pooler,
800
- negative_prompt_embeds=llama_vec_n,
801
- negative_prompt_embeds_mask=llama_attention_mask_n,
802
- negative_prompt_poolers=clip_l_pooler_n,
803
- device=gpu,
804
- dtype=torch.bfloat16,
805
- image_embeddings=image_encoder_last_hidden_state,
806
- latent_indices=latent_indices,
807
- clean_latents=clean_latents,
808
- clean_latent_indices=clean_latent_indices,
809
- clean_latents_2x=clean_latents_2x,
810
- clean_latent_2x_indices=clean_latent_2x_indices,
811
- clean_latents_4x=clean_latents_4x,
812
- clean_latent_4x_indices=clean_latent_4x_indices,
813
- callback=callback,
814
- )
815
-
816
- if is_last_section:
817
- generated_latents = torch.cat([start_latent.to(generated_latents), generated_latents], dim=2)
818
-
819
- total_generated_latent_frames += int(generated_latents.shape[2])
820
- history_latents = torch.cat([generated_latents.to(history_latents), history_latents], dim=2)
821
-
822
- if not high_vram:
823
- offload_model_from_device_for_memory_preservation(transformer, target_device=gpu, preserved_memory_gb=8)
824
- load_model_as_complete(vae, target_device=gpu)
825
-
826
- if history_pixels is None:
827
- history_pixels = vae_decode(history_latents[:, :, :total_generated_latent_frames, :, :], vae).cpu()
828
- else:
829
- section_latent_frames = (latent_window_size * 2 + 1) if is_last_section else (latent_window_size * 2)
830
- overlapped_frames = latent_window_size * 4 - 3
831
-
832
- current_pixels = vae_decode(history_latents[:, :, :min(total_generated_latent_frames, section_latent_frames)], vae).cpu()
833
- history_pixels = soft_append_bcthw(current_pixels, history_pixels, overlapped_frames)
834
-
835
- if not high_vram:
836
- unload_complete_models(vae)
837
-
838
- if enable_preview or is_last_section:
839
- output_filename = os.path.join(outputs_folder, f'{job_id}_{total_generated_latent_frames}.mp4')
840
-
841
- save_bcthw_as_mp4(history_pixels, output_filename, fps=fps_number, crf=mp4_crf)
842
-
843
- print(f'Decoded. Pixel shape {history_pixels.shape}')
844
-
845
- stream.output_queue.push(('file', output_filename))
846
-
847
- if is_last_section:
848
- break
849
- except:
850
- traceback.print_exc()
851
-
852
- if not high_vram:
853
- unload_complete_models(
854
- text_encoder, text_encoder_2, image_encoder, vae, transformer
855
- )
856
-
857
- stream.output_queue.push(('end', None))
858
- return
859
-
860
  # 20250506 pftq: Modified worker to accept video input and clean frame count
861
  @torch.no_grad()
862
  def worker_video(input_video, prompts, n_prompt, seed, batch, resolution, total_second_length, latent_window_size, steps, cfg, gs, rs, gpu_memory_preservation, enable_preview, use_teacache, no_resize, mp4_crf, num_clean_frames, vae_batch):
@@ -1137,17 +857,18 @@ def worker_video(input_video, prompts, n_prompt, seed, batch, resolution, total_
1137
  stream.output_queue.push(('end', None))
1138
  return
1139
 
1140
- def get_duration(input_image, image_position, end_image, prompts, generation_mode, n_prompt, seed, resolution, total_second_length, allocation_time, latent_window_size, steps, cfg, gs, rs, gpu_memory_preservation, enable_preview, use_teacache, mp4_crf, fps_number):
1141
  return allocation_time
1142
 
 
1143
  @spaces.GPU(duration=get_duration)
1144
- def process_on_gpu(input_image, image_position, end_image, prompts, generation_mode, n_prompt, seed, resolution, total_second_length, allocation_time, latent_window_size, steps, cfg, gs, rs, gpu_memory_preservation, enable_preview, use_teacache, mp4_crf, fps_number
1145
  ):
1146
  start = time.time()
1147
  global stream
1148
  stream = AsyncStream()
1149
 
1150
- async_run(worker_start_end if generation_mode == "start_end" else worker, input_image, image_position, end_image, prompts, n_prompt, seed, total_second_length, latent_window_size, steps, cfg, gs, rs, gpu_memory_preservation, enable_preview, use_teacache, mp4_crf, fps_number)
1151
 
1152
  output_filename = None
1153
 
@@ -1178,7 +899,6 @@ def process_on_gpu(input_image, image_position, end_image, prompts, generation_m
1178
 
1179
  def process(input_image,
1180
  image_position=0,
1181
- end_image=None,
1182
  prompt="",
1183
  generation_mode="image",
1184
  n_prompt="",
@@ -1189,12 +909,12 @@ def process(input_image,
1189
  resolution=640,
1190
  total_second_length=5,
1191
  latent_window_size=9,
1192
- steps=30,
1193
  cfg=1.0,
1194
  gs=10.0,
1195
  rs=0.0,
1196
  gpu_memory_preservation=6,
1197
- enable_preview=False,
1198
  use_teacache=False,
1199
  mp4_crf=16,
1200
  fps_number=30
@@ -1202,13 +922,12 @@ def process(input_image,
1202
  if auto_allocation:
1203
  allocation_time = min(total_second_length * 60 * (1.5 if use_teacache else 3.0) * (1 + ((steps - 25) / 25))**2, 600)
1204
 
1205
- if input_image_debug_value[0] is not None or end_image_debug_value[0] is not None or prompt_debug_value[0] is not None or total_second_length_debug_value[0] is not None:
1206
  input_image = input_image_debug_value[0]
1207
- end_image = end_image_debug_value[0]
1208
  prompt = prompt_debug_value[0]
1209
  total_second_length = total_second_length_debug_value[0]
1210
  allocation_time = min(total_second_length_debug_value[0] * 60 * 100, 600)
1211
- input_image_debug_value[0] = end_image_debug_value[0] = input_video_debug_value[0] = prompt_debug_value[0] = total_second_length_debug_value[0] = None
1212
 
1213
  if torch.cuda.device_count() == 0:
1214
  gr.Warning('Set this space to GPU config to make it work.')
@@ -1230,7 +949,6 @@ def process(input_image,
1230
 
1231
  yield from process_on_gpu(input_image,
1232
  image_position,
1233
- end_image,
1234
  prompts,
1235
  generation_mode,
1236
  n_prompt,
@@ -1253,6 +971,7 @@ def process(input_image,
1253
  def get_duration_video(input_video, prompts, n_prompt, seed, batch, resolution, total_second_length, allocation_time, latent_window_size, steps, cfg, gs, rs, gpu_memory_preservation, enable_preview, use_teacache, no_resize, mp4_crf, num_clean_frames, vae_batch):
1254
  return allocation_time
1255
 
 
1256
  @spaces.GPU(duration=get_duration_video)
1257
  def process_video_on_gpu(input_video, prompts, n_prompt, seed, batch, resolution, total_second_length, allocation_time, latent_window_size, steps, cfg, gs, rs, gpu_memory_preservation, enable_preview, use_teacache, no_resize, mp4_crf, num_clean_frames, vae_batch):
1258
  start = time.time()
@@ -1300,7 +1019,7 @@ def process_video(input_video, prompt, n_prompt, randomize_seed, seed, auto_allo
1300
  prompt = prompt_debug_value[0]
1301
  total_second_length = total_second_length_debug_value[0]
1302
  allocation_time = min(total_second_length_debug_value[0] * 60 * 100, 600)
1303
- input_image_debug_value[0] = end_image_debug_value[0] = input_video_debug_value[0] = prompt_debug_value[0] = total_second_length_debug_value[0] = None
1304
 
1305
  if torch.cuda.device_count() == 0:
1306
  gr.Warning('Set this space to GPU config to make it work.')
@@ -1400,10 +1119,9 @@ with block:
1400
  local_storage = gr.BrowserState(default_local_storage)
1401
  with gr.Row():
1402
  with gr.Column():
1403
- generation_mode = gr.Radio([["Text-to-Video", "text"], ["Image-to-Video", "image"], ["Start & end frames", "start_end"], ["Video Extension", "video"]], elem_id="generation-mode", label="Generation mode", value = "image")
1404
  text_to_video_hint = gr.HTML("Text-to-Video badly works with a flash effect at the start. I discourage to use the Text-to-Video feature. You should rather generate an image with Flux and use Image-to-Video. You will save time.")
1405
  input_image = gr.Image(sources='upload', type="numpy", label="Image", height=320)
1406
- end_image = gr.Image(sources='upload', type="numpy", label="End Frame (Optional)", height=320)
1407
  image_position = gr.Slider(label="Image position", minimum=0, maximum=100, value=0, step=1, info='0=Video start; 100=Video end (lower quality)')
1408
  input_video = gr.Video(sources='upload', label="Input Video", height=320)
1409
  timeless_prompt = gr.Textbox(label="Timeless prompt", info='Used on the whole duration of the generation', value='', placeholder="The creature starts to move, fast motion, fixed camera, focus motion, consistent arm, consistent position, mute colors, insanely detailed")
@@ -1429,7 +1147,7 @@ with block:
1429
  enable_preview = gr.Checkbox(label='Enable preview', value=True, info='Display a preview around each second generated but it costs 2 sec. for each second generated.')
1430
  use_teacache = gr.Checkbox(label='Use TeaCache', value=False, info='Faster speed and no break in brightness, but often makes hands and fingers slightly worse.')
1431
 
1432
- n_prompt = gr.Textbox(label="Negative Prompt", value="Missing arm, long hand, unrealistic position, impossible contortion, visible bone, muscle contraction, poorly framed, blurred, blurry, over-smooth", info='Requires using normal CFG (undistilled) instead of Distilled (set Distilled=1 and CFG > 1).')
1433
 
1434
  fps_number = gr.Slider(label="Frame per seconds", info="The model is trained for 30 fps so other fps may generate weird results", minimum=10, maximum=60, value=30, step=1)
1435
 
@@ -1479,7 +1197,6 @@ with block:
1479
 
1480
  with gr.Accordion("Debug", open=False):
1481
  input_image_debug = gr.Image(type="numpy", label="Image Debug", height=320)
1482
- end_image_debug = gr.Image(type="numpy", label="End Image Debug", height=320)
1483
  input_video_debug = gr.Video(sources='upload', label="Input Video Debug", height=320)
1484
  prompt_debug = gr.Textbox(label="Prompt Debug", value='')
1485
  total_second_length_debug = gr.Slider(label="Additional Video Length to Generate (seconds) Debug", minimum=1, maximum=120, value=1, step=0.1)
@@ -1491,7 +1208,8 @@ with block:
1491
  progress_desc = gr.Markdown('', elem_classes='no-generating-animation')
1492
  progress_bar = gr.HTML('', elem_classes='no-generating-animation')
1493
 
1494
- ips = [input_image, image_position, end_image, final_prompt, generation_mode, n_prompt, randomize_seed, seed, auto_allocation, allocation_time, resolution, total_second_length, latent_window_size, steps, cfg, gs, rs, gpu_memory_preservation, enable_preview, use_teacache, mp4_crf, fps_number]
 
1495
  ips_video = [input_video, final_prompt, n_prompt, randomize_seed, seed, auto_allocation, allocation_time, batch, resolution, total_second_length, latent_window_size, steps, cfg, gs, rs, gpu_memory_preservation, enable_preview, use_teacache, no_resize, mp4_crf, num_clean_frames, vae_batch]
1496
 
1497
  with gr.Row(elem_id="text_examples", visible=False):
@@ -1501,10 +1219,9 @@ with block:
1501
  [
1502
  None, # input_image
1503
  0, # image_position
1504
- None, # end_image
1505
  "Overcrowed street in Japan, photorealistic, realistic, intricate details, 8k, insanely detailed",
1506
  "text", # generation_mode
1507
- "Missing arm, long hand, unrealistic position, impossible contortion, visible bone, muscle contraction, poorly framed, blurred, blurry, over-smooth", # n_prompt
1508
  True, # randomize_seed
1509
  42, # seed
1510
  True, # auto_allocation
@@ -1537,10 +1254,9 @@ with block:
1537
  [
1538
  "./img_examples/Example2.webp", # input_image
1539
  0, # image_position
1540
- None, # end_image
1541
  "A man on the left and a woman on the right face each other ready to start a conversation, large space between the persons, full view, full-length view, 3D, pixar, 3D render, CGI. The man talks and the woman listens; A man on the left and a woman on the right face each other ready to start a conversation, large space between the persons, full view, full-length view, 3D, pixar, 3D render, CGI. The woman talks, the man stops talking and the man listens; A man on the left and a woman on the right face each other ready to start a conversation, large space between the persons, full view, full-length view, 3D, pixar, 3D render, CGI. The woman talks and the man listens",
1542
  "image", # generation_mode
1543
- "Missing arm, long hand, unrealistic position, impossible contortion, visible bone, muscle contraction, poorly framed, blurred, blurry, over-smooth", # n_prompt
1544
  True, # randomize_seed
1545
  42, # seed
1546
  True, # auto_allocation
@@ -1561,10 +1277,9 @@ with block:
1561
  [
1562
  "./img_examples/Example1.png", # input_image
1563
  0, # image_position
1564
- None, # end_image
1565
  "A dolphin emerges from the water, photorealistic, realistic, intricate details, 8k, insanely detailed",
1566
  "image", # generation_mode
1567
- "Missing arm, long hand, unrealistic position, impossible contortion, visible bone, muscle contraction, poorly framed, blurred, blurry, over-smooth", # n_prompt
1568
  True, # randomize_seed
1569
  42, # seed
1570
  True, # auto_allocation
@@ -1585,10 +1300,9 @@ with block:
1585
  [
1586
  "./img_examples/Example4.webp", # input_image
1587
  1, # image_position
1588
- None, # end_image
1589
  "A building starting to explode, photorealistic, realisitc, 8k, insanely detailed",
1590
  "image", # generation_mode
1591
- "Missing arm, long hand, unrealistic position, impossible contortion, visible bone, muscle contraction, poorly framed, blurred, blurry, over-smooth", # n_prompt
1592
  True, # randomize_seed
1593
  42, # seed
1594
  True, # auto_allocation
@@ -1609,10 +1323,9 @@ with block:
1609
  [
1610
  "./img_examples/Example4.webp", # input_image
1611
  50, # image_position
1612
- None, # end_image
1613
  "A building starting to explode, photorealistic, realisitc, 8k, insanely detailed",
1614
  "image", # generation_mode
1615
- "Missing arm, long hand, unrealistic position, impossible contortion, visible bone, muscle contraction, poorly framed, blurred, blurry, over-smooth", # n_prompt
1616
  True, # randomize_seed
1617
  42, # seed
1618
  True, # auto_allocation
@@ -1633,46 +1346,9 @@ with block:
1633
  [
1634
  "./img_examples/Example4.webp", # input_image
1635
  100, # image_position
1636
- None, # end_image
1637
  "A building starting to explode, photorealistic, realisitc, 8k, insanely detailed",
1638
  "image", # generation_mode
1639
- "Missing arm, long hand, unrealistic position, impossible contortion, visible bone, muscle contraction, poorly framed, blurred, blurry, over-smooth", # n_prompt
1640
- True, # randomize_seed
1641
- 42, # seed
1642
- True, # auto_allocation
1643
- 180, # allocation_time
1644
- 672, # resolution
1645
- 1, # total_second_length
1646
- 9, # latent_window_size
1647
- 30, # steps
1648
- 1.0, # cfg
1649
- 10.0, # gs
1650
- 0.0, # rs
1651
- 6, # gpu_memory_preservation
1652
- False, # enable_preview
1653
- False, # use_teacache
1654
- 16, # mp4_crf
1655
- 30 # fps_number
1656
- ],
1657
- ],
1658
- run_on_click = True,
1659
- fn = process,
1660
- inputs = ips,
1661
- outputs = [result_video, preview_image, progress_desc, progress_bar, start_button, end_button, warning],
1662
- cache_examples = torch.cuda.device_count() > 0,
1663
- )
1664
-
1665
- with gr.Row(elem_id="start_end_examples", visible=False):
1666
- gr.Examples(
1667
- label = "Examples from start and end frames",
1668
- examples = [
1669
- [
1670
- "./img_examples/Example2.webp", # input_image
1671
- 0, # image_position
1672
- None, # end_image
1673
- "A man on the left and a woman on the right face each other ready to start a conversation, large space between the persons, full view, full-length view, 3D, pixar, 3D render, CGI. The man talks and the woman listens; A man on the left and a woman on the right face each other ready to start a conversation, large space between the persons, full view, full-length view, 3D, pixar, 3D render, CGI. The woman talks, the man stops talking and the man listens; A man on the left and a woman on the right face each other ready to start a conversation, large space between the persons, full view, full-length view, 3D, pixar, 3D render, CGI. The woman talks and the man listens",
1674
- "start_end", # generation_mode
1675
- "Missing arm, long hand, unrealistic position, impossible contortion, visible bone, muscle contraction, poorly framed, blurred, blurry, over-smooth", # n_prompt
1676
  True, # randomize_seed
1677
  42, # seed
1678
  True, # auto_allocation
@@ -1705,7 +1381,7 @@ with block:
1705
  [
1706
  "./img_examples/Example1.mp4", # input_video
1707
  "View of the sea as far as the eye can see, from the seaside, a piece of land is barely visible on the horizon at the middle, the sky is radiant, reflections of the sun in the water, photorealistic, realistic, intricate details, 8k, insanely detailed",
1708
- "Missing arm, long hand, unrealistic position, impossible contortion, visible bone, muscle contraction, poorly framed, blurred, blurry, over-smooth", # n_prompt
1709
  True, # randomize_seed
1710
  42, # seed
1711
  True, # auto_allocation
@@ -1729,7 +1405,7 @@ with block:
1729
  [
1730
  "./img_examples/Example1.mp4", # input_video
1731
  "View of the sea as far as the eye can see, from the seaside, a piece of land is barely visible on the horizon at the middle, the sky is radiant, reflections of the sun in the water, photorealistic, realistic, intricate details, 8k, insanely detailed",
1732
- "Missing arm, long hand, unrealistic position, impossible contortion, visible bone, muscle contraction, poorly framed, blurred, blurry, over-smooth", # n_prompt
1733
  True, # randomize_seed
1734
  42, # seed
1735
  True, # auto_allocation
@@ -1764,10 +1440,9 @@ with block:
1764
  [
1765
  None, # input_image
1766
  0, # image_position
1767
- None, # end_image
1768
  "Overcrowed street in Japan, photorealistic, realistic, intricate details, 8k, insanely detailed",
1769
  "text", # generation_mode
1770
- "Missing arm, long hand, unrealistic position, impossible contortion, visible bone, muscle contraction, poorly framed, blurred, blurry, over-smooth", # n_prompt
1771
  True, # randomize_seed
1772
  42, # seed
1773
  True, # auto_allocation
@@ -1799,10 +1474,9 @@ with block:
1799
  [
1800
  "./img_examples/Example1.png", # input_image
1801
  0, # image_position
1802
- None, # end_image
1803
  "A dolphin emerges from the water, photorealistic, realistic, intricate details, 8k, insanely detailed",
1804
  "image", # generation_mode
1805
- "Missing arm, long hand, unrealistic position, impossible contortion, visible bone, muscle contraction, poorly framed, blurred, blurry, over-smooth", # n_prompt
1806
  True, # randomize_seed
1807
  42, # seed
1808
  True, # auto_allocation
@@ -1823,10 +1497,9 @@ with block:
1823
  [
1824
  "./img_examples/Example2.webp", # input_image
1825
  0, # image_position
1826
- None, # end_image
1827
  "A man on the left and a woman on the right face each other ready to start a conversation, large space between the persons, full view, full-length view, 3D, pixar, 3D render, CGI. The man talks and the woman listens; A man on the left and a woman on the right face each other ready to start a conversation, large space between the persons, full view, full-length view, 3D, pixar, 3D render, CGI. The woman talks, the man stops talking and the man listens; A man on the left and a woman on the right face each other ready to start a conversation, large space between the persons, full view, full-length view, 3D, pixar, 3D render, CGI. The woman talks and the man listens",
1828
  "image", # generation_mode
1829
- "Missing arm, long hand, unrealistic position, impossible contortion, visible bone, muscle contraction, poorly framed, blurred, blurry, over-smooth", # n_prompt
1830
  True, # randomize_seed
1831
  42, # seed
1832
  True, # auto_allocation
@@ -1847,10 +1520,9 @@ with block:
1847
  [
1848
  "./img_examples/Example2.webp", # input_image
1849
  0, # image_position
1850
- None, # end_image
1851
  "A man on the left and a woman on the right face each other ready to start a conversation, large space between the persons, full view, full-length view, 3D, pixar, 3D render, CGI. The woman talks and the man listens; A man on the left and a woman on the right face each other ready to start a conversation, large space between the persons, full view, full-length view, 3D, pixar, 3D render, CGI. The man talks, the woman stops talking and the woman listens A man on the left and a woman on the right face each other ready to start a conversation, large space between the persons, full view, full-length view, 3D, pixar, 3D render, CGI. The man talks and the woman listens",
1852
  "image", # generation_mode
1853
- "Missing arm, long hand, unrealistic position, impossible contortion, visible bone, muscle contraction, poorly framed, blurred, blurry, over-smooth", # n_prompt
1854
  True, # randomize_seed
1855
  42, # seed
1856
  True, # auto_allocation
@@ -1871,10 +1543,9 @@ with block:
1871
  [
1872
  "./img_examples/Example3.jpg", # input_image
1873
  0, # image_position
1874
- None, # end_image
1875
  "A boy is walking to the right, full view, full-length view, cartoon",
1876
  "image", # generation_mode
1877
- "Missing arm, long hand, unrealistic position, impossible contortion, visible bone, muscle contraction, poorly framed, blurred, blurry, over-smooth", # n_prompt
1878
  True, # randomize_seed
1879
  42, # seed
1880
  True, # auto_allocation
@@ -1895,10 +1566,9 @@ with block:
1895
  [
1896
  "./img_examples/Example4.webp", # input_image
1897
  100, # image_position
1898
- None, # end_image
1899
  "A building starting to explode, photorealistic, realisitc, 8k, insanely detailed",
1900
  "image", # generation_mode
1901
- "Missing arm, long hand, unrealistic position, impossible contortion, visible bone, muscle contraction, poorly framed, blurred, blurry, over-smooth", # n_prompt
1902
  True, # randomize_seed
1903
  42, # seed
1904
  True, # auto_allocation
@@ -1924,48 +1594,13 @@ with block:
1924
  cache_examples = False,
1925
  )
1926
 
1927
- gr.Examples(
1928
- label = "🖼️ Examples from start and end frames",
1929
- examples = [
1930
- [
1931
- "./img_examples/Example1.png", # input_image
1932
- 0, # image_position
1933
- None, # end_image
1934
- "A dolphin emerges from the water, photorealistic, realistic, intricate details, 8k, insanely detailed",
1935
- "start_end", # generation_mode
1936
- "Missing arm, long hand, unrealistic position, impossible contortion, visible bone, muscle contraction, poorly framed, blurred, blurry, over-smooth", # n_prompt
1937
- True, # randomize_seed
1938
- 42, # seed
1939
- True, # auto_allocation
1940
- 180, # allocation_time
1941
- 672, # resolution
1942
- 1, # total_second_length
1943
- 9, # latent_window_size
1944
- 30, # steps
1945
- 1.0, # cfg
1946
- 10.0, # gs
1947
- 0.0, # rs
1948
- 6, # gpu_memory_preservation
1949
- False, # enable_preview
1950
- True, # use_teacache
1951
- 16, # mp4_crf
1952
- 30 # fps_number
1953
- ],
1954
- ],
1955
- run_on_click = True,
1956
- fn = process,
1957
- inputs = ips,
1958
- outputs = [result_video, preview_image, progress_desc, progress_bar, start_button, end_button, warning],
1959
- cache_examples = False,
1960
- )
1961
-
1962
  gr.Examples(
1963
  label = "🎥 Examples from video",
1964
  examples = [
1965
  [
1966
  "./img_examples/Example1.mp4", # input_video
1967
  "View of the sea as far as the eye can see, from the seaside, a piece of land is barely visible on the horizon at the middle, the sky is radiant, reflections of the sun in the water, photorealistic, realistic, intricate details, 8k, insanely detailed",
1968
- "Missing arm, long hand, unrealistic position, impossible contortion, visible bone, muscle contraction, poorly framed, blurred, blurry, over-smooth", # n_prompt
1969
  True, # randomize_seed
1970
  42, # seed
1971
  True, # auto_allocation
@@ -2016,106 +1651,42 @@ with block:
2016
 
2017
  def handle_generation_mode_change(generation_mode_data):
2018
  if generation_mode_data == "text":
2019
- return [
2020
- gr.update(visible = True), # text_to_video_hint
2021
- gr.update(visible = False), # image_position
2022
- gr.update(visible = False), # input_image
2023
- gr.update(visible = False), # end_image
2024
- gr.update(visible = False), # input_video
2025
- gr.update(visible = True), # start_button
2026
- gr.update(visible = False), # start_button_video
2027
- gr.update(visible = False), # no_resize
2028
- gr.update(visible = False), # batch
2029
- gr.update(visible = False), # num_clean_frames
2030
- gr.update(visible = False), # vae_batch
2031
- gr.update(visible = False), # prompt_hint
2032
- gr.update(visible = True) # fps_number
2033
- ]
2034
  elif generation_mode_data == "image":
2035
- return [
2036
- gr.update(visible = False), # text_to_video_hint
2037
- gr.update(visible = True), # image_position
2038
- gr.update(visible = True), # input_image
2039
- gr.update(visible = False), # end_image
2040
- gr.update(visible = False), # input_video
2041
- gr.update(visible = True), # start_button
2042
- gr.update(visible = False), # start_button_video
2043
- gr.update(visible = False), # no_resize
2044
- gr.update(visible = False), # batch
2045
- gr.update(visible = False), # num_clean_frames
2046
- gr.update(visible = False), # vae_batch
2047
- gr.update(visible = False), # prompt_hint
2048
- gr.update(visible = True) # fps_number
2049
- ]
2050
- elif generation_mode_data == "start_end":
2051
- return [
2052
- gr.update(visible = False), # text_to_video_hint
2053
- gr.update(visible = False), # image_position
2054
- gr.update(visible = True), # input_image
2055
- gr.update(visible = True), # end_image
2056
- gr.update(visible = False), # input_video
2057
- gr.update(visible = True), # start_button
2058
- gr.update(visible = False), # start_button_video
2059
- gr.update(visible = False), # no_resize
2060
- gr.update(visible = False), # batch
2061
- gr.update(visible = False), # num_clean_frames
2062
- gr.update(visible = False), # vae_batch
2063
- gr.update(visible = False), # prompt_hint
2064
- gr.update(visible = True) # fps_number
2065
- ]
2066
  elif generation_mode_data == "video":
2067
- return [
2068
- gr.update(visible = False), # text_to_video_hint
2069
- gr.update(visible = False), # image_position
2070
- gr.update(visible = False), # input_image
2071
- gr.update(visible = False), # end_image
2072
- gr.update(visible = True), # input_video
2073
- gr.update(visible = False), # start_button
2074
- gr.update(visible = True), # start_button_video
2075
- gr.update(visible = True), # no_resize
2076
- gr.update(visible = True), # batch
2077
- gr.update(visible = True), # num_clean_frames
2078
- gr.update(visible = True), # vae_batch
2079
- gr.update(visible = True), # prompt_hint
2080
- gr.update(visible = False) # fps_number
2081
- ]
2082
-
2083
- def handle_field_debug_change(input_image_debug_data, input_video_debug_data, end_image_debug_data, prompt_debug_data, total_second_length_debug_data):
2084
  print("handle_field_debug_change")
2085
  input_image_debug_value[0] = input_image_debug_data
2086
  input_video_debug_value[0] = input_video_debug_data
2087
- end_image_debug_value[0] = end_image_debug_data
2088
  prompt_debug_value[0] = prompt_debug_data
2089
  total_second_length_debug_value[0] = total_second_length_debug_data
2090
  return []
2091
 
2092
  input_image_debug.upload(
2093
  fn=handle_field_debug_change,
2094
- inputs=[input_image_debug, input_video_debug, end_image_debug, prompt_debug, total_second_length_debug],
2095
  outputs=[]
2096
  )
2097
 
2098
  input_video_debug.upload(
2099
  fn=handle_field_debug_change,
2100
- inputs=[input_image_debug, input_video_debug, end_image_debug, prompt_debug, total_second_length_debug],
2101
- outputs=[]
2102
- )
2103
-
2104
- end_image_debug.upload(
2105
- fn=handle_field_debug_change,
2106
- inputs=[input_image_debug, input_video_debug, end_image_debug, prompt_debug, total_second_length_debug],
2107
  outputs=[]
2108
  )
2109
 
2110
  prompt_debug.change(
2111
  fn=handle_field_debug_change,
2112
- inputs=[input_image_debug, input_video_debug, end_image_debug, prompt_debug, total_second_length_debug],
2113
  outputs=[]
2114
  )
2115
 
2116
  total_second_length_debug.change(
2117
  fn=handle_field_debug_change,
2118
- inputs=[input_image_debug, input_video_debug, end_image_debug, prompt_debug, total_second_length_debug],
2119
  outputs=[]
2120
  )
2121
 
@@ -2139,7 +1710,7 @@ with block:
2139
  generation_mode.change(
2140
  fn=handle_generation_mode_change,
2141
  inputs=[generation_mode],
2142
- outputs=[text_to_video_hint, image_position, input_image, end_image, input_video, start_button, start_button_video, no_resize, batch, num_clean_frames, vae_batch, prompt_hint, fps_number]
2143
  )
2144
 
2145
  # Update display when the page loads
@@ -2147,7 +1718,7 @@ with block:
2147
  fn=handle_generation_mode_change, inputs = [
2148
  generation_mode
2149
  ], outputs = [
2150
- text_to_video_hint, image_position, input_image, end_image, input_video, start_button, start_button_video, no_resize, batch, num_clean_frames, vae_batch, prompt_hint, fps_number
2151
  ]
2152
  )
2153
 
 
7
  try:
8
  import spaces
9
  except:
10
+ print("Not on HuggingFace")
 
 
 
 
 
 
 
11
  import gradio as gr
12
  import torch
13
  import traceback
14
  import einops
15
  import safetensors.torch as sf
16
+ import numpy as np
17
  import random
18
  import time
 
 
19
  import math
20
  # 20250506 pftq: Added for video input loading
21
  import decord
 
38
  from diffusers_helper.utils import save_bcthw_as_mp4, crop_or_pad_yield_mask, soft_append_bcthw, resize_and_center_crop, state_dict_weighted_merge, state_dict_offset_merge, generate_timestamp
39
  from diffusers_helper.models.hunyuan_video_packed import HunyuanVideoTransformer3DModelPacked
40
  from diffusers_helper.pipelines.k_diffusion_hunyuan import sample_hunyuan
41
+ if torch.cuda.device_count() > 0:
42
+ from diffusers_helper.memory import cpu, gpu, get_cuda_free_memory_gb, move_model_to_device_with_memory_preservation, offload_model_from_device_for_memory_preservation, fake_diffusers_current_device, DynamicSwapInstaller, unload_complete_models, load_model_as_complete
43
  from diffusers_helper.thread_utils import AsyncStream, async_run
44
  from diffusers_helper.gradio.progress_bar import make_progress_bar_css, make_progress_bar_html
45
  from transformers import SiglipImageProcessor, SiglipVisionModel
46
  from diffusers_helper.clip_vision import hf_clip_vision_encode
47
  from diffusers_helper.bucket_tools import find_nearest_bucket
48
+ from diffusers import BitsAndBytesConfig as DiffusersBitsAndBytesConfig, HunyuanVideoTransformer3DModel, HunyuanVideoPipeline
49
+ import pillow_heif
50
+
51
+ pillow_heif.register_heif_opener()
52
+
53
+ high_vram = False
54
+ free_mem_gb = 0
55
+
56
+ if torch.cuda.device_count() > 0:
57
+ free_mem_gb = get_cuda_free_memory_gb(gpu)
58
+ high_vram = free_mem_gb > 60
59
+
60
+ #print(f'Free VRAM {free_mem_gb} GB')
61
+ #print(f'High-VRAM Mode: {high_vram}')
62
+
63
+ text_encoder = LlamaModel.from_pretrained("hunyuanvideo-community/HunyuanVideo", subfolder='text_encoder', torch_dtype=torch.float16).cpu()
64
+ text_encoder_2 = CLIPTextModel.from_pretrained("hunyuanvideo-community/HunyuanVideo", subfolder='text_encoder_2', torch_dtype=torch.float16).cpu()
65
+ tokenizer = LlamaTokenizerFast.from_pretrained("hunyuanvideo-community/HunyuanVideo", subfolder='tokenizer')
66
+ tokenizer_2 = CLIPTokenizer.from_pretrained("hunyuanvideo-community/HunyuanVideo", subfolder='tokenizer_2')
67
+ vae = AutoencoderKLHunyuanVideo.from_pretrained("hunyuanvideo-community/HunyuanVideo", subfolder='vae', torch_dtype=torch.float16).cpu()
68
+
69
+ feature_extractor = SiglipImageProcessor.from_pretrained("lllyasviel/flux_redux_bfl", subfolder='feature_extractor')
70
+ image_encoder = SiglipVisionModel.from_pretrained("lllyasviel/flux_redux_bfl", subfolder='image_encoder', torch_dtype=torch.float16).cpu()
71
 
72
+ transformer = HunyuanVideoTransformer3DModelPacked.from_pretrained('lllyasviel/FramePack_F1_I2V_HY_20250503', torch_dtype=torch.bfloat16).cpu()
73
+
74
+ vae.eval()
75
+ text_encoder.eval()
76
+ text_encoder_2.eval()
77
+ image_encoder.eval()
78
+ transformer.eval()
79
+
80
+ if not high_vram:
81
+ vae.enable_slicing()
82
+ vae.enable_tiling()
83
+
84
+ transformer.high_quality_fp32_output_for_inference = True
85
+ #print('transformer.high_quality_fp32_output_for_inference = True')
86
+
87
+ transformer.to(dtype=torch.bfloat16)
88
+ vae.to(dtype=torch.float16)
89
+ image_encoder.to(dtype=torch.float16)
90
+ text_encoder.to(dtype=torch.float16)
91
+ text_encoder_2.to(dtype=torch.float16)
92
+
93
+ vae.requires_grad_(False)
94
+ text_encoder.requires_grad_(False)
95
+ text_encoder_2.requires_grad_(False)
96
+ image_encoder.requires_grad_(False)
97
+ transformer.requires_grad_(False)
98
+
99
+ if not high_vram:
100
+ # DynamicSwapInstaller is same as huggingface's enable_sequential_offload but 3x faster
101
+ DynamicSwapInstaller.install_model(transformer, device=gpu)
102
+ DynamicSwapInstaller.install_model(text_encoder, device=gpu)
103
+ else:
104
+ text_encoder.to(gpu)
105
+ text_encoder_2.to(gpu)
106
+ image_encoder.to(gpu)
107
+ vae.to(gpu)
108
+ transformer.to(gpu)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
 
110
  stream = AsyncStream()
111
 
 
114
 
115
  input_image_debug_value = [None]
116
  input_video_debug_value = [None]
 
117
  prompt_debug_value = [None]
118
  total_second_length_debug_value = [None]
119
 
 
308
  return False
309
 
310
  @torch.no_grad()
311
+ def worker(input_image, image_position, prompts, n_prompt, seed, resolution, total_second_length, latent_window_size, steps, cfg, gs, rs, gpu_memory_preservation, enable_preview, use_teacache, mp4_crf, fps_number):
312
  def encode_prompt(prompt, n_prompt):
313
  llama_vec, clip_l_pooler = encode_prompt_conds(prompt, text_encoder, text_encoder_2, tokenizer, tokenizer_2)
314
 
 
577
  stream.output_queue.push(('end', None))
578
  return
579
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
580
  # 20250506 pftq: Modified worker to accept video input and clean frame count
581
  @torch.no_grad()
582
  def worker_video(input_video, prompts, n_prompt, seed, batch, resolution, total_second_length, latent_window_size, steps, cfg, gs, rs, gpu_memory_preservation, enable_preview, use_teacache, no_resize, mp4_crf, num_clean_frames, vae_batch):
 
857
  stream.output_queue.push(('end', None))
858
  return
859
 
860
+ def get_duration(input_image, image_position, prompts, generation_mode, n_prompt, seed, resolution, total_second_length, allocation_time, latent_window_size, steps, cfg, gs, rs, gpu_memory_preservation, enable_preview, use_teacache, mp4_crf, fps_number):
861
  return allocation_time
862
 
863
+ # Remove this decorator if you run on local
864
  @spaces.GPU(duration=get_duration)
865
+ def process_on_gpu(input_image, image_position, prompts, generation_mode, n_prompt, seed, resolution, total_second_length, allocation_time, latent_window_size, steps, cfg, gs, rs, gpu_memory_preservation, enable_preview, use_teacache, mp4_crf, fps_number
866
  ):
867
  start = time.time()
868
  global stream
869
  stream = AsyncStream()
870
 
871
+ async_run(worker, input_image, image_position, prompts, n_prompt, seed, resolution, total_second_length, latent_window_size, steps, cfg, gs, rs, gpu_memory_preservation, enable_preview, use_teacache, mp4_crf, fps_number)
872
 
873
  output_filename = None
874
 
 
899
 
900
  def process(input_image,
901
  image_position=0,
 
902
  prompt="",
903
  generation_mode="image",
904
  n_prompt="",
 
909
  resolution=640,
910
  total_second_length=5,
911
  latent_window_size=9,
912
+ steps=25,
913
  cfg=1.0,
914
  gs=10.0,
915
  rs=0.0,
916
  gpu_memory_preservation=6,
917
+ enable_preview=True,
918
  use_teacache=False,
919
  mp4_crf=16,
920
  fps_number=30
 
922
  if auto_allocation:
923
  allocation_time = min(total_second_length * 60 * (1.5 if use_teacache else 3.0) * (1 + ((steps - 25) / 25))**2, 600)
924
 
925
+ if input_image_debug_value[0] is not None or prompt_debug_value[0] is not None or total_second_length_debug_value[0] is not None:
926
  input_image = input_image_debug_value[0]
 
927
  prompt = prompt_debug_value[0]
928
  total_second_length = total_second_length_debug_value[0]
929
  allocation_time = min(total_second_length_debug_value[0] * 60 * 100, 600)
930
+ input_image_debug_value[0] = prompt_debug_value[0] = total_second_length_debug_value[0] = None
931
 
932
  if torch.cuda.device_count() == 0:
933
  gr.Warning('Set this space to GPU config to make it work.')
 
949
 
950
  yield from process_on_gpu(input_image,
951
  image_position,
 
952
  prompts,
953
  generation_mode,
954
  n_prompt,
 
971
  def get_duration_video(input_video, prompts, n_prompt, seed, batch, resolution, total_second_length, allocation_time, latent_window_size, steps, cfg, gs, rs, gpu_memory_preservation, enable_preview, use_teacache, no_resize, mp4_crf, num_clean_frames, vae_batch):
972
  return allocation_time
973
 
974
+ # Remove this decorator if you run on local
975
  @spaces.GPU(duration=get_duration_video)
976
  def process_video_on_gpu(input_video, prompts, n_prompt, seed, batch, resolution, total_second_length, allocation_time, latent_window_size, steps, cfg, gs, rs, gpu_memory_preservation, enable_preview, use_teacache, no_resize, mp4_crf, num_clean_frames, vae_batch):
977
  start = time.time()
 
1019
  prompt = prompt_debug_value[0]
1020
  total_second_length = total_second_length_debug_value[0]
1021
  allocation_time = min(total_second_length_debug_value[0] * 60 * 100, 600)
1022
+ input_video_debug_value[0] = prompt_debug_value[0] = total_second_length_debug_value[0] = None
1023
 
1024
  if torch.cuda.device_count() == 0:
1025
  gr.Warning('Set this space to GPU config to make it work.')
 
1119
  local_storage = gr.BrowserState(default_local_storage)
1120
  with gr.Row():
1121
  with gr.Column():
1122
+ generation_mode = gr.Radio([["Text-to-Video", "text"], ["Image-to-Video", "image"], ["Video Extension", "video"]], elem_id="generation-mode", label="Generation mode", value = "image")
1123
  text_to_video_hint = gr.HTML("Text-to-Video badly works with a flash effect at the start. I discourage to use the Text-to-Video feature. You should rather generate an image with Flux and use Image-to-Video. You will save time.")
1124
  input_image = gr.Image(sources='upload', type="numpy", label="Image", height=320)
 
1125
  image_position = gr.Slider(label="Image position", minimum=0, maximum=100, value=0, step=1, info='0=Video start; 100=Video end (lower quality)')
1126
  input_video = gr.Video(sources='upload', label="Input Video", height=320)
1127
  timeless_prompt = gr.Textbox(label="Timeless prompt", info='Used on the whole duration of the generation', value='', placeholder="The creature starts to move, fast motion, fixed camera, focus motion, consistent arm, consistent position, mute colors, insanely detailed")
 
1147
  enable_preview = gr.Checkbox(label='Enable preview', value=True, info='Display a preview around each second generated but it costs 2 sec. for each second generated.')
1148
  use_teacache = gr.Checkbox(label='Use TeaCache', value=False, info='Faster speed and no break in brightness, but often makes hands and fingers slightly worse.')
1149
 
1150
+ n_prompt = gr.Textbox(label="Negative Prompt", value="Missing arm, long hand, unrealistic position, impossible contortion, visible bone, muscle contraction, blurred, blurry, over-smooth", info='Requires using normal CFG (undistilled) instead of Distilled (set Distilled=1 and CFG > 1).')
1151
 
1152
  fps_number = gr.Slider(label="Frame per seconds", info="The model is trained for 30 fps so other fps may generate weird results", minimum=10, maximum=60, value=30, step=1)
1153
 
 
1197
 
1198
  with gr.Accordion("Debug", open=False):
1199
  input_image_debug = gr.Image(type="numpy", label="Image Debug", height=320)
 
1200
  input_video_debug = gr.Video(sources='upload', label="Input Video Debug", height=320)
1201
  prompt_debug = gr.Textbox(label="Prompt Debug", value='')
1202
  total_second_length_debug = gr.Slider(label="Additional Video Length to Generate (seconds) Debug", minimum=1, maximum=120, value=1, step=0.1)
 
1208
  progress_desc = gr.Markdown('', elem_classes='no-generating-animation')
1209
  progress_bar = gr.HTML('', elem_classes='no-generating-animation')
1210
 
1211
+ # 20250506 pftq: Updated inputs to include num_clean_frames
1212
+ ips = [input_image, image_position, final_prompt, generation_mode, n_prompt, randomize_seed, seed, auto_allocation, allocation_time, resolution, total_second_length, latent_window_size, steps, cfg, gs, rs, gpu_memory_preservation, enable_preview, use_teacache, mp4_crf, fps_number]
1213
  ips_video = [input_video, final_prompt, n_prompt, randomize_seed, seed, auto_allocation, allocation_time, batch, resolution, total_second_length, latent_window_size, steps, cfg, gs, rs, gpu_memory_preservation, enable_preview, use_teacache, no_resize, mp4_crf, num_clean_frames, vae_batch]
1214
 
1215
  with gr.Row(elem_id="text_examples", visible=False):
 
1219
  [
1220
  None, # input_image
1221
  0, # image_position
 
1222
  "Overcrowed street in Japan, photorealistic, realistic, intricate details, 8k, insanely detailed",
1223
  "text", # generation_mode
1224
+ "Missing arm, long hand, unrealistic position, impossible contortion, visible bone, muscle contraction, blurred, blurry, over-smooth", # n_prompt
1225
  True, # randomize_seed
1226
  42, # seed
1227
  True, # auto_allocation
 
1254
  [
1255
  "./img_examples/Example2.webp", # input_image
1256
  0, # image_position
 
1257
  "A man on the left and a woman on the right face each other ready to start a conversation, large space between the persons, full view, full-length view, 3D, pixar, 3D render, CGI. The man talks and the woman listens; A man on the left and a woman on the right face each other ready to start a conversation, large space between the persons, full view, full-length view, 3D, pixar, 3D render, CGI. The woman talks, the man stops talking and the man listens; A man on the left and a woman on the right face each other ready to start a conversation, large space between the persons, full view, full-length view, 3D, pixar, 3D render, CGI. The woman talks and the man listens",
1258
  "image", # generation_mode
1259
+ "Missing arm, long hand, unrealistic position, impossible contortion, visible bone, muscle contraction, blurred, blurry, over-smooth", # n_prompt
1260
  True, # randomize_seed
1261
  42, # seed
1262
  True, # auto_allocation
 
1277
  [
1278
  "./img_examples/Example1.png", # input_image
1279
  0, # image_position
 
1280
  "A dolphin emerges from the water, photorealistic, realistic, intricate details, 8k, insanely detailed",
1281
  "image", # generation_mode
1282
+ "Missing arm, long hand, unrealistic position, impossible contortion, visible bone, muscle contraction, blurred, blurry, over-smooth", # n_prompt
1283
  True, # randomize_seed
1284
  42, # seed
1285
  True, # auto_allocation
 
1300
  [
1301
  "./img_examples/Example4.webp", # input_image
1302
  1, # image_position
 
1303
  "A building starting to explode, photorealistic, realisitc, 8k, insanely detailed",
1304
  "image", # generation_mode
1305
+ "Missing arm, long hand, unrealistic position, impossible contortion, visible bone, muscle contraction, blurred, blurry, over-smooth", # n_prompt
1306
  True, # randomize_seed
1307
  42, # seed
1308
  True, # auto_allocation
 
1323
  [
1324
  "./img_examples/Example4.webp", # input_image
1325
  50, # image_position
 
1326
  "A building starting to explode, photorealistic, realisitc, 8k, insanely detailed",
1327
  "image", # generation_mode
1328
+ "Missing arm, long hand, unrealistic position, impossible contortion, visible bone, muscle contraction, blurred, blurry, over-smooth", # n_prompt
1329
  True, # randomize_seed
1330
  42, # seed
1331
  True, # auto_allocation
 
1346
  [
1347
  "./img_examples/Example4.webp", # input_image
1348
  100, # image_position
 
1349
  "A building starting to explode, photorealistic, realisitc, 8k, insanely detailed",
1350
  "image", # generation_mode
1351
+ "Missing arm, long hand, unrealistic position, impossible contortion, visible bone, muscle contraction, blurred, blurry, over-smooth", # n_prompt
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1352
  True, # randomize_seed
1353
  42, # seed
1354
  True, # auto_allocation
 
1381
  [
1382
  "./img_examples/Example1.mp4", # input_video
1383
  "View of the sea as far as the eye can see, from the seaside, a piece of land is barely visible on the horizon at the middle, the sky is radiant, reflections of the sun in the water, photorealistic, realistic, intricate details, 8k, insanely detailed",
1384
+ "Missing arm, long hand, unrealistic position, impossible contortion, visible bone, muscle contraction, blurred, blurry, over-smooth", # n_prompt
1385
  True, # randomize_seed
1386
  42, # seed
1387
  True, # auto_allocation
 
1405
  [
1406
  "./img_examples/Example1.mp4", # input_video
1407
  "View of the sea as far as the eye can see, from the seaside, a piece of land is barely visible on the horizon at the middle, the sky is radiant, reflections of the sun in the water, photorealistic, realistic, intricate details, 8k, insanely detailed",
1408
+ "Missing arm, long hand, unrealistic position, impossible contortion, visible bone, muscle contraction, blurred, blurry, over-smooth", # n_prompt
1409
  True, # randomize_seed
1410
  42, # seed
1411
  True, # auto_allocation
 
1440
  [
1441
  None, # input_image
1442
  0, # image_position
 
1443
  "Overcrowed street in Japan, photorealistic, realistic, intricate details, 8k, insanely detailed",
1444
  "text", # generation_mode
1445
+ "Missing arm, long hand, unrealistic position, impossible contortion, visible bone, muscle contraction, blurred, blurry, over-smooth", # n_prompt
1446
  True, # randomize_seed
1447
  42, # seed
1448
  True, # auto_allocation
 
1474
  [
1475
  "./img_examples/Example1.png", # input_image
1476
  0, # image_position
 
1477
  "A dolphin emerges from the water, photorealistic, realistic, intricate details, 8k, insanely detailed",
1478
  "image", # generation_mode
1479
+ "Missing arm, long hand, unrealistic position, impossible contortion, visible bone, muscle contraction, blurred, blurry, over-smooth", # n_prompt
1480
  True, # randomize_seed
1481
  42, # seed
1482
  True, # auto_allocation
 
1497
  [
1498
  "./img_examples/Example2.webp", # input_image
1499
  0, # image_position
 
1500
  "A man on the left and a woman on the right face each other ready to start a conversation, large space between the persons, full view, full-length view, 3D, pixar, 3D render, CGI. The man talks and the woman listens; A man on the left and a woman on the right face each other ready to start a conversation, large space between the persons, full view, full-length view, 3D, pixar, 3D render, CGI. The woman talks, the man stops talking and the man listens; A man on the left and a woman on the right face each other ready to start a conversation, large space between the persons, full view, full-length view, 3D, pixar, 3D render, CGI. The woman talks and the man listens",
1501
  "image", # generation_mode
1502
+ "Missing arm, long hand, unrealistic position, impossible contortion, visible bone, muscle contraction, blurred, blurry, over-smooth", # n_prompt
1503
  True, # randomize_seed
1504
  42, # seed
1505
  True, # auto_allocation
 
1520
  [
1521
  "./img_examples/Example2.webp", # input_image
1522
  0, # image_position
 
1523
  "A man on the left and a woman on the right face each other ready to start a conversation, large space between the persons, full view, full-length view, 3D, pixar, 3D render, CGI. The woman talks and the man listens; A man on the left and a woman on the right face each other ready to start a conversation, large space between the persons, full view, full-length view, 3D, pixar, 3D render, CGI. The man talks, the woman stops talking and the woman listens A man on the left and a woman on the right face each other ready to start a conversation, large space between the persons, full view, full-length view, 3D, pixar, 3D render, CGI. The man talks and the woman listens",
1524
  "image", # generation_mode
1525
+ "Missing arm, long hand, unrealistic position, impossible contortion, visible bone, muscle contraction, blurred, blurry, over-smooth", # n_prompt
1526
  True, # randomize_seed
1527
  42, # seed
1528
  True, # auto_allocation
 
1543
  [
1544
  "./img_examples/Example3.jpg", # input_image
1545
  0, # image_position
 
1546
  "A boy is walking to the right, full view, full-length view, cartoon",
1547
  "image", # generation_mode
1548
+ "Missing arm, long hand, unrealistic position, impossible contortion, visible bone, muscle contraction, blurred, blurry, over-smooth", # n_prompt
1549
  True, # randomize_seed
1550
  42, # seed
1551
  True, # auto_allocation
 
1566
  [
1567
  "./img_examples/Example4.webp", # input_image
1568
  100, # image_position
 
1569
  "A building starting to explode, photorealistic, realisitc, 8k, insanely detailed",
1570
  "image", # generation_mode
1571
+ "Missing arm, long hand, unrealistic position, impossible contortion, visible bone, muscle contraction, blurred, blurry, over-smooth", # n_prompt
1572
  True, # randomize_seed
1573
  42, # seed
1574
  True, # auto_allocation
 
1594
  cache_examples = False,
1595
  )
1596
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1597
  gr.Examples(
1598
  label = "🎥 Examples from video",
1599
  examples = [
1600
  [
1601
  "./img_examples/Example1.mp4", # input_video
1602
  "View of the sea as far as the eye can see, from the seaside, a piece of land is barely visible on the horizon at the middle, the sky is radiant, reflections of the sun in the water, photorealistic, realistic, intricate details, 8k, insanely detailed",
1603
+ "Missing arm, long hand, unrealistic position, impossible contortion, visible bone, muscle contraction, blurred, blurry, over-smooth", # n_prompt
1604
  True, # randomize_seed
1605
  42, # seed
1606
  True, # auto_allocation
 
1651
 
1652
  def handle_generation_mode_change(generation_mode_data):
1653
  if generation_mode_data == "text":
1654
+ return [gr.update(visible = True), gr.update(visible = False), gr.update(visible = False), gr.update(visible = False), gr.update(visible = True), gr.update(visible = False), gr.update(visible = False), gr.update(visible = False), gr.update(visible = False), gr.update(visible = False), gr.update(visible = False), gr.update(visible = True)]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1655
  elif generation_mode_data == "image":
1656
+ return [gr.update(visible = False), gr.update(visible = True), gr.update(visible = True), gr.update(visible = False), gr.update(visible = True), gr.update(visible = False), gr.update(visible = False), gr.update(visible = False), gr.update(visible = False), gr.update(visible = False), gr.update(visible = False), gr.update(visible = True)]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1657
  elif generation_mode_data == "video":
1658
+ return [gr.update(visible = False), gr.update(visible = False), gr.update(visible = False), gr.update(visible = True), gr.update(visible = False), gr.update(visible = True), gr.update(visible = True), gr.update(visible = True), gr.update(visible = True), gr.update(visible = True), gr.update(visible = True), gr.update(visible = False)]
1659
+
1660
+
1661
+ def handle_field_debug_change(input_image_debug_data, input_video_debug_data, prompt_debug_data, total_second_length_debug_data):
 
 
 
 
 
 
 
 
 
 
 
 
 
1662
  print("handle_field_debug_change")
1663
  input_image_debug_value[0] = input_image_debug_data
1664
  input_video_debug_value[0] = input_video_debug_data
 
1665
  prompt_debug_value[0] = prompt_debug_data
1666
  total_second_length_debug_value[0] = total_second_length_debug_data
1667
  return []
1668
 
1669
  input_image_debug.upload(
1670
  fn=handle_field_debug_change,
1671
+ inputs=[input_image_debug, input_video_debug, prompt_debug, total_second_length_debug],
1672
  outputs=[]
1673
  )
1674
 
1675
  input_video_debug.upload(
1676
  fn=handle_field_debug_change,
1677
+ inputs=[input_image_debug, input_video_debug, prompt_debug, total_second_length_debug],
 
 
 
 
 
 
1678
  outputs=[]
1679
  )
1680
 
1681
  prompt_debug.change(
1682
  fn=handle_field_debug_change,
1683
+ inputs=[input_image_debug, input_video_debug, prompt_debug, total_second_length_debug],
1684
  outputs=[]
1685
  )
1686
 
1687
  total_second_length_debug.change(
1688
  fn=handle_field_debug_change,
1689
+ inputs=[input_image_debug, input_video_debug, prompt_debug, total_second_length_debug],
1690
  outputs=[]
1691
  )
1692
 
 
1710
  generation_mode.change(
1711
  fn=handle_generation_mode_change,
1712
  inputs=[generation_mode],
1713
+ outputs=[text_to_video_hint, image_position, input_image, input_video, start_button, start_button_video, no_resize, batch, num_clean_frames, vae_batch, prompt_hint, fps_number]
1714
  )
1715
 
1716
  # Update display when the page loads
 
1718
  fn=handle_generation_mode_change, inputs = [
1719
  generation_mode
1720
  ], outputs = [
1721
+ text_to_video_hint, image_position, input_image, input_video, start_button, start_button_video, no_resize, batch, num_clean_frames, vae_batch, prompt_hint, fps_number
1722
  ]
1723
  )
1724