├── Colab_FramePack.ipynb ├── cloud_gradio.py ├── models.json ├── vibes.txt └── voice.json /Colab_FramePack.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "provenance": [], 7 | "authorship_tag": "ABX9TyMA0AwBoemY19hSCyKChwTQ" 8 | }, 9 | "kernelspec": { 10 | "name": "python3", 11 | "display_name": "Python 3" 12 | }, 13 | "language_info": { 14 | "name": "python" 15 | } 16 | }, 17 | "cells": [ 18 | { 19 | "cell_type": "code", 20 | "execution_count": null, 21 | "metadata": { 22 | "id": "CMQbCUZuDj6L" 23 | }, 24 | "outputs": [], 25 | "source": [ 26 | "\n", 27 | "use_framepack_f1 = False #@param {type: \"boolean\"}\n", 28 | "NGROK_TOKEN = '' #@param {type: \"string\"}\n", 29 | "\n", 30 | "def start_ngrok(port):\n", 31 | " %pip install pyngrok\n", 32 | " import time, socket\n", 33 | " while True:\n", 34 | " time.sleep(0.5)\n", 35 | " with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:\n", 36 | " if sock.connect_ex(('127.0.0.1', port)) == 0:\n", 37 | " break\n", 38 | " config = f'''version: 3\n", 39 | "endpoints:\n", 40 | " - name: gradio\n", 41 | " upstream:\n", 42 | " url: http://localhost:{port}\n", 43 | " traffic_policy:\n", 44 | " inbound:\n", 45 | " - name: \"Remove X-Forwarded-Host\"\n", 46 | " actions:\n", 47 | " - type: remove-headers\n", 48 | " config:\n", 49 | " headers:\n", 50 | " - \"x-forwarded-host\"\n", 51 | "agent:\n", 52 | " authtoken: {NGROK_TOKEN}\n", 53 | "'''\n", 54 | " with open(\"/content/ngrok_config.yaml\", \"w\") as f:\n", 55 | " f.write(config)\n", 56 | " !ngrok start gradio --config /content/ngrok_config.yaml --log=stdout\n", 57 | "\n", 58 | "def setup_python_310():\n", 59 | " !python --version > /content/pyversion\n", 60 | " with open('/content/pyversion') as f:\n", 61 | " if '3.10' in f.read():\n", 62 | " return\n", 63 | " !apt-get update -y\n", 64 | " !apt-get install -y python3.10 python3.10-distutils\n", 65 | " !rm -f /usr/local/bin/python /usr/local/bin/pip\n", 66 | " !update-alternatives --install /usr/local/bin/python python /usr/bin/python3.10 2\n", 67 | " !wget https://bootstrap.pypa.io/get-pip.py && python get-pip.py\n", 68 | "\n", 69 | "def clear_output_screen():\n", 70 | " from IPython.display import clear_output\n", 71 | " clear_output()\n", 72 | "\n", 73 | "from google.colab import userdata\n", 74 | "try:\n", 75 | " NGROK_TOKEN = userdata.get('NGROK')\n", 76 | " print(\"Loaded NGROK token from secrets.\")\n", 77 | "except:\n", 78 | " pass\n", 79 | "\n", 80 | "setup_python_310()\n", 81 | "\n", 82 | "%cd /content/\n", 83 | "!git clone https://github.com/lllyasviel/FramePack\n", 84 | "%cd FramePack\n", 85 | "!pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu126\n", 86 | "!pip install -r requirements.txt\n", 87 | "!pip install sageattention==1.0.6\n", 88 | "\n", 89 | "command = 'PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True'\n", 90 | "command += ' python demo_gradio_f1.py' if use_framepack_f1 else ' python demo_gradio.py'\n", 91 | "\n", 92 | "clear_output_screen()\n", 93 | "\n", 94 | "if NGROK_TOKEN:\n", 95 | " import threading\n", 96 | " port = 7860\n", 97 | " threading.Thread(target=start_ngrok, args=(port,), daemon=True).start()\n", 98 | "else:\n", 99 | " command += ' --share'\n", 100 | "\n", 101 | "print(command)\n", 102 | "!{command}" 103 | ] 104 | } 105 | ] 106 | } 107 | -------------------------------------------------------------------------------- /cloud_gradio.py: -------------------------------------------------------------------------------- 1 | from diffusers_helper.hf_login import login 2 | import requests 3 | import os 4 | 5 | os.environ['HF_HOME'] = os.path.abspath(os.path.realpath(os.path.join(os.path.dirname(__file__), './hf_download'))) 6 | 7 | import gradio as gr 8 | import torch 9 | import traceback 10 | import einops 11 | import safetensors.torch as sf 12 | import numpy as np 13 | import argparse 14 | import math 15 | 16 | from PIL import Image 17 | from diffusers import AutoencoderKLHunyuanVideo 18 | from transformers import LlamaModel, CLIPTextModel, LlamaTokenizerFast, CLIPTokenizer 19 | from diffusers_helper.hunyuan import encode_prompt_conds, vae_decode, vae_encode, vae_decode_fake 20 | 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 21 | from diffusers_helper.models.hunyuan_video_packed import HunyuanVideoTransformer3DModelPacked 22 | from diffusers_helper.pipelines.k_diffusion_hunyuan import sample_hunyuan 23 | 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 24 | from diffusers_helper.thread_utils import AsyncStream, async_run 25 | from diffusers_helper.gradio.progress_bar import make_progress_bar_css, make_progress_bar_html 26 | from transformers import SiglipImageProcessor, SiglipVisionModel 27 | from diffusers_helper.clip_vision import hf_clip_vision_encode 28 | from diffusers_helper.bucket_tools import find_nearest_bucket 29 | import cloudinary 30 | import cloudinary.uploader 31 | api_key="" 32 | api_secret="" 33 | cloud_name="" 34 | 35 | 36 | parser = argparse.ArgumentParser() 37 | parser.add_argument('--share', action='store_true') 38 | parser.add_argument("--server", type=str, default='0.0.0.0') 39 | parser.add_argument("--port", type=int, required=False) 40 | parser.add_argument("--inbrowser", action='store_true') 41 | args = parser.parse_args() 42 | 43 | # for win desktop probably use --server 127.0.0.1 --inbrowser 44 | # For linux server probably use --server 127.0.0.1 or do not use any cmd flags 45 | 46 | print(args) 47 | 48 | free_mem_gb = get_cuda_free_memory_gb(gpu) 49 | high_vram = free_mem_gb > 60 50 | 51 | print(f'Free VRAM {free_mem_gb} GB') 52 | print(f'High-VRAM Mode: {high_vram}') 53 | 54 | text_encoder = LlamaModel.from_pretrained("hunyuanvideo-community/HunyuanVideo", subfolder='text_encoder', torch_dtype=torch.float16).cpu() 55 | text_encoder_2 = CLIPTextModel.from_pretrained("hunyuanvideo-community/HunyuanVideo", subfolder='text_encoder_2', torch_dtype=torch.float16).cpu() 56 | tokenizer = LlamaTokenizerFast.from_pretrained("hunyuanvideo-community/HunyuanVideo", subfolder='tokenizer') 57 | tokenizer_2 = CLIPTokenizer.from_pretrained("hunyuanvideo-community/HunyuanVideo", subfolder='tokenizer_2') 58 | vae = AutoencoderKLHunyuanVideo.from_pretrained("hunyuanvideo-community/HunyuanVideo", subfolder='vae', torch_dtype=torch.float16).cpu() 59 | 60 | feature_extractor = SiglipImageProcessor.from_pretrained("lllyasviel/flux_redux_bfl", subfolder='feature_extractor') 61 | image_encoder = SiglipVisionModel.from_pretrained("lllyasviel/flux_redux_bfl", subfolder='image_encoder', torch_dtype=torch.float16).cpu() 62 | 63 | transformer = HunyuanVideoTransformer3DModelPacked.from_pretrained('lllyasviel/FramePackI2V_HY', torch_dtype=torch.bfloat16).cpu() 64 | 65 | vae.eval() 66 | text_encoder.eval() 67 | text_encoder_2.eval() 68 | image_encoder.eval() 69 | transformer.eval() 70 | 71 | if not high_vram: 72 | vae.enable_slicing() 73 | vae.enable_tiling() 74 | 75 | transformer.high_quality_fp32_output_for_inference = True 76 | print('transformer.high_quality_fp32_output_for_inference = True') 77 | 78 | transformer.to(dtype=torch.bfloat16) 79 | vae.to(dtype=torch.float16) 80 | image_encoder.to(dtype=torch.float16) 81 | text_encoder.to(dtype=torch.float16) 82 | text_encoder_2.to(dtype=torch.float16) 83 | 84 | vae.requires_grad_(False) 85 | text_encoder.requires_grad_(False) 86 | text_encoder_2.requires_grad_(False) 87 | image_encoder.requires_grad_(False) 88 | transformer.requires_grad_(False) 89 | 90 | if not high_vram: 91 | # DynamicSwapInstaller is same as huggingface's enable_sequential_offload but 3x faster 92 | DynamicSwapInstaller.install_model(transformer, device=gpu) 93 | DynamicSwapInstaller.install_model(text_encoder, device=gpu) 94 | else: 95 | text_encoder.to(gpu) 96 | text_encoder_2.to(gpu) 97 | image_encoder.to(gpu) 98 | vae.to(gpu) 99 | transformer.to(gpu) 100 | 101 | stream = AsyncStream() 102 | 103 | outputs_folder = './outputs/' 104 | os.makedirs(outputs_folder, exist_ok=True) 105 | 106 | 107 | @torch.no_grad() 108 | def worker(input_image, prompt, n_prompt, seed, total_second_length, latent_window_size, steps, cfg, gs, rs, gpu_memory_preservation, use_teacache, mp4_crf): 109 | total_latent_sections = (total_second_length * 30) / (latent_window_size * 4) 110 | total_latent_sections = int(max(round(total_latent_sections), 1)) 111 | 112 | job_id = generate_timestamp() 113 | 114 | stream.output_queue.push(('progress', (None, '', make_progress_bar_html(0, 'Starting ...')))) 115 | 116 | try: 117 | # Clean GPU 118 | if not high_vram: 119 | unload_complete_models( 120 | text_encoder, text_encoder_2, image_encoder, vae, transformer 121 | ) 122 | 123 | # Text encoding 124 | 125 | stream.output_queue.push(('progress', (None, '', make_progress_bar_html(0, 'Text encoding ...')))) 126 | 127 | if not high_vram: 128 | 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. 129 | load_model_as_complete(text_encoder_2, target_device=gpu) 130 | 131 | llama_vec, clip_l_pooler = encode_prompt_conds(prompt, text_encoder, text_encoder_2, tokenizer, tokenizer_2) 132 | 133 | if cfg == 1: 134 | llama_vec_n, clip_l_pooler_n = torch.zeros_like(llama_vec), torch.zeros_like(clip_l_pooler) 135 | else: 136 | llama_vec_n, clip_l_pooler_n = encode_prompt_conds(n_prompt, text_encoder, text_encoder_2, tokenizer, tokenizer_2) 137 | 138 | llama_vec, llama_attention_mask = crop_or_pad_yield_mask(llama_vec, length=512) 139 | llama_vec_n, llama_attention_mask_n = crop_or_pad_yield_mask(llama_vec_n, length=512) 140 | 141 | # Processing input image 142 | 143 | stream.output_queue.push(('progress', (None, '', make_progress_bar_html(0, 'Image processing ...')))) 144 | 145 | H, W, C = input_image.shape 146 | height, width = find_nearest_bucket(H, W, resolution=640) 147 | input_image_np = resize_and_center_crop(input_image, target_width=width, target_height=height) 148 | 149 | Image.fromarray(input_image_np).save(os.path.join(outputs_folder, f'{job_id}.png')) 150 | 151 | input_image_pt = torch.from_numpy(input_image_np).float() / 127.5 - 1 152 | input_image_pt = input_image_pt.permute(2, 0, 1)[None, :, None] 153 | 154 | # VAE encoding 155 | 156 | stream.output_queue.push(('progress', (None, '', make_progress_bar_html(0, 'VAE encoding ...')))) 157 | 158 | if not high_vram: 159 | load_model_as_complete(vae, target_device=gpu) 160 | 161 | start_latent = vae_encode(input_image_pt, vae) 162 | 163 | # CLIP Vision 164 | 165 | stream.output_queue.push(('progress', (None, '', make_progress_bar_html(0, 'CLIP Vision encoding ...')))) 166 | 167 | if not high_vram: 168 | load_model_as_complete(image_encoder, target_device=gpu) 169 | 170 | image_encoder_output = hf_clip_vision_encode(input_image_np, feature_extractor, image_encoder) 171 | image_encoder_last_hidden_state = image_encoder_output.last_hidden_state 172 | 173 | # Dtype 174 | 175 | llama_vec = llama_vec.to(transformer.dtype) 176 | llama_vec_n = llama_vec_n.to(transformer.dtype) 177 | clip_l_pooler = clip_l_pooler.to(transformer.dtype) 178 | clip_l_pooler_n = clip_l_pooler_n.to(transformer.dtype) 179 | image_encoder_last_hidden_state = image_encoder_last_hidden_state.to(transformer.dtype) 180 | 181 | # Sampling 182 | 183 | stream.output_queue.push(('progress', (None, '', make_progress_bar_html(0, 'Start sampling ...')))) 184 | 185 | rnd = torch.Generator("cpu").manual_seed(seed) 186 | num_frames = latent_window_size * 4 - 3 187 | 188 | history_latents = torch.zeros(size=(1, 16, 1 + 2 + 16, height // 8, width // 8), dtype=torch.float32).cpu() 189 | history_pixels = None 190 | total_generated_latent_frames = 0 191 | 192 | latent_paddings = reversed(range(total_latent_sections)) 193 | 194 | if total_latent_sections > 4: 195 | # In theory the latent_paddings should follow the above sequence, but it seems that duplicating some 196 | # items looks better than expanding it when total_latent_sections > 4 197 | # One can try to remove below trick and just 198 | # use `latent_paddings = list(reversed(range(total_latent_sections)))` to compare 199 | latent_paddings = [3] + [2] * (total_latent_sections - 3) + [1, 0] 200 | 201 | for latent_padding in latent_paddings: 202 | is_last_section = latent_padding == 0 203 | latent_padding_size = latent_padding * latent_window_size 204 | 205 | if stream.input_queue.top() == 'end': 206 | stream.output_queue.push(('end', None)) 207 | return 208 | 209 | print(f'latent_padding_size = {latent_padding_size}, is_last_section = {is_last_section}') 210 | 211 | indices = torch.arange(0, sum([1, latent_padding_size, latent_window_size, 1, 2, 16])).unsqueeze(0) 212 | 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) 213 | clean_latent_indices = torch.cat([clean_latent_indices_pre, clean_latent_indices_post], dim=1) 214 | 215 | clean_latents_pre = start_latent.to(history_latents) 216 | clean_latents_post, clean_latents_2x, clean_latents_4x = history_latents[:, :, :1 + 2 + 16, :, :].split([1, 2, 16], dim=2) 217 | clean_latents = torch.cat([clean_latents_pre, clean_latents_post], dim=2) 218 | 219 | if not high_vram: 220 | unload_complete_models() 221 | move_model_to_device_with_memory_preservation(transformer, target_device=gpu, preserved_memory_gb=gpu_memory_preservation) 222 | 223 | if use_teacache: 224 | transformer.initialize_teacache(enable_teacache=True, num_steps=steps) 225 | else: 226 | transformer.initialize_teacache(enable_teacache=False) 227 | 228 | def callback(d): 229 | preview = d['denoised'] 230 | preview = vae_decode_fake(preview) 231 | 232 | preview = (preview * 255.0).detach().cpu().numpy().clip(0, 255).astype(np.uint8) 233 | preview = einops.rearrange(preview, 'b c t h w -> (b h) (t w) c') 234 | 235 | if stream.input_queue.top() == 'end': 236 | stream.output_queue.push(('end', None)) 237 | raise KeyboardInterrupt('User ends the task.') 238 | 239 | current_step = d['i'] + 1 240 | percentage = int(100.0 * current_step / steps) 241 | hint = f'Sampling {current_step}/{steps}' 242 | desc = f'Total generated frames: {int(max(0, total_generated_latent_frames * 4 - 3))}, Video length: {max(0, (total_generated_latent_frames * 4 - 3) / 30) :.2f} seconds (FPS-30). The video is being extended now ...' 243 | stream.output_queue.push(('progress', (preview, desc, make_progress_bar_html(percentage, hint)))) 244 | return 245 | 246 | generated_latents = sample_hunyuan( 247 | transformer=transformer, 248 | sampler='unipc', 249 | width=width, 250 | height=height, 251 | frames=num_frames, 252 | real_guidance_scale=cfg, 253 | distilled_guidance_scale=gs, 254 | guidance_rescale=rs, 255 | # shift=3.0, 256 | num_inference_steps=steps, 257 | generator=rnd, 258 | prompt_embeds=llama_vec, 259 | prompt_embeds_mask=llama_attention_mask, 260 | prompt_poolers=clip_l_pooler, 261 | negative_prompt_embeds=llama_vec_n, 262 | negative_prompt_embeds_mask=llama_attention_mask_n, 263 | negative_prompt_poolers=clip_l_pooler_n, 264 | device=gpu, 265 | dtype=torch.bfloat16, 266 | image_embeddings=image_encoder_last_hidden_state, 267 | latent_indices=latent_indices, 268 | clean_latents=clean_latents, 269 | clean_latent_indices=clean_latent_indices, 270 | clean_latents_2x=clean_latents_2x, 271 | clean_latent_2x_indices=clean_latent_2x_indices, 272 | clean_latents_4x=clean_latents_4x, 273 | clean_latent_4x_indices=clean_latent_4x_indices, 274 | callback=callback, 275 | ) 276 | 277 | if is_last_section: 278 | generated_latents = torch.cat([start_latent.to(generated_latents), generated_latents], dim=2) 279 | 280 | total_generated_latent_frames += int(generated_latents.shape[2]) 281 | history_latents = torch.cat([generated_latents.to(history_latents), history_latents], dim=2) 282 | 283 | if not high_vram: 284 | offload_model_from_device_for_memory_preservation(transformer, target_device=gpu, preserved_memory_gb=8) 285 | load_model_as_complete(vae, target_device=gpu) 286 | 287 | real_history_latents = history_latents[:, :, :total_generated_latent_frames, :, :] 288 | 289 | if history_pixels is None: 290 | history_pixels = vae_decode(real_history_latents, vae).cpu() 291 | else: 292 | section_latent_frames = (latent_window_size * 2 + 1) if is_last_section else (latent_window_size * 2) 293 | overlapped_frames = latent_window_size * 4 - 3 294 | 295 | current_pixels = vae_decode(real_history_latents[:, :, :section_latent_frames], vae).cpu() 296 | history_pixels = soft_append_bcthw(current_pixels, history_pixels, overlapped_frames) 297 | 298 | if not high_vram: 299 | unload_complete_models() 300 | 301 | output_filename = os.path.join(outputs_folder, f'{job_id}_{total_generated_latent_frames}.mp4') 302 | 303 | save_bcthw_as_mp4(history_pixels, output_filename, fps=30, crf=mp4_crf) 304 | 305 | print(f'Decoded. Current latent shape {real_history_latents.shape}; pixel shape {history_pixels.shape}') 306 | 307 | stream.output_queue.push(('file', output_filename)) 308 | 309 | if is_last_section: 310 | break 311 | except: 312 | traceback.print_exc() 313 | 314 | if not high_vram: 315 | unload_complete_models( 316 | text_encoder, text_encoder_2, image_encoder, vae, transformer 317 | ) 318 | 319 | stream.output_queue.push(('end', None)) 320 | return 321 | 322 | cloudinary.config( 323 | cloud_name=cloud_name, 324 | api_key=api_key, 325 | api_secret=api_secret, 326 | secure=True 327 | ) 328 | 329 | def process(input_image, prompt, n_prompt, seed, total_second_length, latent_window_size, steps, cfg, gs, rs, gpu_memory_preservation, use_teacache, mp4_crf): 330 | global stream 331 | assert input_image is not None, 'No input image!' 332 | 333 | yield None, None, '', '', gr.update(interactive=False), gr.update(interactive=True) 334 | 335 | stream = AsyncStream() 336 | 337 | async_run(worker, input_image, prompt, n_prompt, seed, total_second_length, latent_window_size, steps, cfg, gs, rs, gpu_memory_preservation, use_teacache, mp4_crf) 338 | 339 | output_filename = None 340 | 341 | while True: 342 | flag, data = stream.output_queue.next() 343 | 344 | if flag == 'file': 345 | output_filename = data 346 | yield output_filename, gr.update(), gr.update(), gr.update(), gr.update(interactive=False), gr.update(interactive=True) 347 | 348 | 349 | 350 | if flag == 'progress': 351 | preview, desc, html = data 352 | yield gr.update(), gr.update(visible=True, value=preview), desc, html, gr.update(interactive=False), gr.update(interactive=True) 353 | 354 | if flag == 'end': 355 | # Upload the final .mp4 to Cloudinary 356 | try: 357 | upload_result = cloudinary.uploader.upload_large(output_filename, resource_type="video", upload_preset="n8n_framepack", folder="n8n_framepack") 358 | video_url = upload_result["secure_url"] 359 | print(f"✅ Uploaded to Cloudinary: {video_url}") 360 | 361 | # Send video URL to Telegram Bot 362 | telegram_bot_token = "" 363 | telegram_chat_id = "" 364 | message = f"✅ Your video is ready!\n{video_url}" 365 | 366 | telegram_url = f"https://api.telegram.org/bot{telegram_bot_token}/sendMessage" 367 | payload = { 368 | "chat_id": telegram_chat_id, 369 | "text": message, 370 | "parse_mode": "HTML" 371 | } 372 | response = requests.post(telegram_url, data=payload) 373 | if response.status_code == 200: 374 | print("✅ Sent to Telegram successfully.") 375 | else: 376 | print(f"❌ Failed to send to Telegram: {response.status_code} - {response.text}") 377 | 378 | 379 | 380 | except Exception as e: 381 | video_url = f"Cloudinary upload failed: {str(e)}" 382 | 383 | yield video_url, gr.update(), gr.update(), gr.update(), gr.update(interactive=False), gr.update(interactive=True) 384 | break 385 | 386 | 387 | def end_process(): 388 | stream.input_queue.push('end') 389 | 390 | 391 | quick_prompts = [ 392 | 'The girl dances gracefully, with clear movements, full of charm.', 393 | 'A character doing some simple body movements.', 394 | ] 395 | quick_prompts = [[x] for x in quick_prompts] 396 | 397 | 398 | css = make_progress_bar_css() 399 | block = gr.Blocks(css=css).queue() 400 | with block: 401 | gr.Markdown('# FramePack') 402 | with gr.Row(): 403 | with gr.Column(): 404 | input_image = gr.Image(sources='upload', type="numpy", label="Image", height=320) 405 | prompt = gr.Textbox(label="Prompt", value='') 406 | example_quick_prompts = gr.Dataset(samples=quick_prompts, label='Quick List', samples_per_page=1000, components=[prompt]) 407 | example_quick_prompts.click(lambda x: x[0], inputs=[example_quick_prompts], outputs=prompt, show_progress=False, queue=False) 408 | 409 | with gr.Row(): 410 | start_button = gr.Button(value="Start Generation") 411 | end_button = gr.Button(value="End Generation", interactive=False) 412 | 413 | with gr.Group(): 414 | use_teacache = gr.Checkbox(label='Use TeaCache', value=True, info='Faster speed, but often makes hands and fingers slightly worse.') 415 | 416 | n_prompt = gr.Textbox(label="Negative Prompt", value="", visible=False) # Not used 417 | seed = gr.Number(label="Seed", value=31337, precision=0) 418 | 419 | total_second_length = gr.Slider(label="Total Video Length (Seconds)", minimum=1, maximum=120, value=5, step=0.1) 420 | latent_window_size = gr.Slider(label="Latent Window Size", minimum=1, maximum=33, value=9, step=1, visible=False) # Should not change 421 | steps = gr.Slider(label="Steps", minimum=1, maximum=100, value=25, step=1, info='Changing this value is not recommended.') 422 | 423 | cfg = gr.Slider(label="CFG Scale", minimum=1.0, maximum=32.0, value=1.0, step=0.01, visible=False) # Should not change 424 | gs = gr.Slider(label="Distilled CFG Scale", minimum=1.0, maximum=32.0, value=10.0, step=0.01, info='Changing this value is not recommended.') 425 | rs = gr.Slider(label="CFG Re-Scale", minimum=0.0, maximum=1.0, value=0.0, step=0.01, visible=False) # Should not change 426 | 427 | gpu_memory_preservation = gr.Slider(label="GPU Inference Preserved Memory (GB) (larger means slower)", minimum=6, maximum=128, value=6, step=0.1, info="Set this number to a larger value if you encounter OOM. Larger value causes slower speed.") 428 | 429 | mp4_crf = gr.Slider(label="MP4 Compression", minimum=0, maximum=100, value=16, step=1, info="Lower means better quality. 0 is uncompressed. Change to 16 if you get black outputs. ") 430 | 431 | with gr.Column(): 432 | preview_image = gr.Image(label="Next Latents", height=200, visible=False) 433 | result_video = gr.Video(label="Finished Frames", autoplay=True, show_share_button=False, height=512, loop=True) 434 | gr.Markdown('Note that the ending actions will be generated before the starting actions due to the inverted sampling. If the starting action is not in the video, you just need to wait, and it will be generated later.') 435 | progress_desc = gr.Markdown('', elem_classes='no-generating-animation') 436 | progress_bar = gr.HTML('', elem_classes='no-generating-animation') 437 | 438 | gr.HTML('