Sergidev commited on
Commit
eb9cf96
·
1 Parent(s): 5dfd9f8
Files changed (3) hide show
  1. demo_app.py +70 -173
  2. requirements.txt +7 -8
  3. utils.py +2 -18
demo_app.py CHANGED
@@ -1,12 +1,11 @@
1
  import spaces
2
  import gradio as gr
3
  import numpy as np
4
- import os
5
  import torch
6
- from PIL import Image
7
- from pathlib import Path
8
  from diffusers import HunyuanVideoPipeline
9
  from huggingface_hub import snapshot_download
 
 
10
 
11
  # Configuration
12
  LORA_CHOICES = [
@@ -27,32 +26,18 @@ pipe = HunyuanVideoPipeline.from_pretrained(
27
  torch_dtype=torch.float16
28
  ).to("cuda")
29
 
30
- # Load all available LoRAs
31
  for lora_file in LORA_CHOICES:
32
- try:
33
- pipe.load_lora_weights(
34
- "Sergidev/TTV4ME",
35
- weight_name=lora_file,
36
- adapter_name=lora_file.split('.')[0],
37
- token=os.environ.get("HF_TOKEN")
38
- )
39
- except Exception as e:
40
- print(f"Error loading {lora_file}: {str(e)}")
41
 
42
  @spaces.GPU(duration=300)
43
- def generate(
44
- prompt,
45
- image_input,
46
- height,
47
- width,
48
- num_frames,
49
- num_inference_steps,
50
- seed_value,
51
- fps,
52
- selected_loras,
53
- lora_weights,
54
- progress=gr.Progress(track_tqdm=True)
55
- ):
56
  # Image validation
57
  if image_input is not None:
58
  img = Image.open(image_input)
@@ -68,157 +53,69 @@ def generate(
68
  active_adapters.append(LORA_CHOICES[idx].split('.')[0])
69
  adapter_weights.append(lora_weights[idx])
70
 
71
- if active_adapters:
72
- pipe.set_adapters(active_adapters, adapter_weights)
73
-
74
- # Generation logic
75
- torch.cuda.empty_cache()
76
- if seed_value == -1:
77
- seed_value = torch.randint(0, MAX_SEED, (1,)).item()
78
-
79
- generator = torch.Generator('cuda').manual_seed(seed_value)
80
-
81
- try:
82
- if image_input:
83
- output = pipe.image_to_video(
84
- Image.open(image_input).convert("RGB"),
85
- prompt=prompt,
86
- height=height,
87
- width=width,
88
- num_frames=num_frames,
89
- num_inference_steps=num_inference_steps,
90
- generator=generator,
91
- )
92
- else:
93
- output = pipe.text_to_video(
94
- prompt=prompt,
95
- height=height,
96
- width=width,
97
- num_frames=num_frames,
98
- num_inference_steps=num_inference_steps,
99
- generator=generator,
100
- )
101
-
102
- return output.video
103
- finally:
104
- torch.cuda.empty_cache()
105
-
106
- def apply_preset(preset_name):
107
- if preset_name == "Higher Resolution":
108
- return [608, 448, 24, 29, 12]
109
- elif preset_name == "More Frames":
110
- return [512, 320, 42, 27, 14]
111
- return [512, 512, 24, 25, 12]
112
-
113
- css = """
114
- /* Existing CSS remains unchanged */
115
- """
116
-
117
- with gr.Blocks(css=css, theme="dark") as demo:
118
- with gr.Column(elem_id="col-container"):
119
- gr.Markdown("# 🎬 Hunyuan Studio", elem_classes=["title"])
120
- gr.Markdown(
121
- """Text-to-Video & Image-to-Video generation with multiple LoRA adapters.<br>
122
- Ensure image resolution matches selected video dimensions.""",
123
- elem_classes=["description"]
124
- )
125
 
126
- with gr.Column(elem_classes=["prompt-container"]):
127
- prompt = gr.Textbox(
128
- label="Prompt",
129
- placeholder="Enter text prompt or describe the image...",
130
- elem_classes=["prompt-textbox"],
131
- lines=3
132
- )
133
- image_input = gr.Image(
134
- label="Upload Reference Image (Optional)",
135
- type="filepath",
136
- visible=True
137
- )
138
 
139
- with gr.Row():
140
- run_button = gr.Button("🎬 Generate Video", variant="primary", size="lg")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
141
 
142
- with gr.Row(elem_classes=["preset-buttons"]):
143
- preset_high_res = gr.Button("📺 Resolution Preset")
144
- preset_more_frames = gr.Button("🎞️ Frames Preset")
 
 
145
 
146
  with gr.Row():
147
- result = gr.Video(label="Generated Video")
148
-
149
- with gr.Accordion("⚙️ Advanced Settings", open=False):
150
- with gr.Row():
151
- seed = gr.Slider(
152
- label="Seed (-1 for random)",
153
- minimum=-1,
154
- maximum=MAX_SEED,
155
- step=1,
156
- value=-1,
157
- )
158
-
159
- with gr.Row():
160
- height = gr.Slider(
161
- label="Height",
162
- minimum=256,
163
- maximum=MAX_IMAGE_SIZE,
164
- step=16,
165
- value=512,
166
- )
167
- width = gr.Slider(
168
- label="Width",
169
- minimum=256,
170
- maximum=MAX_IMAGE_SIZE,
171
- step=16,
172
- value=512,
173
- )
174
-
175
- with gr.Row():
176
- num_frames = gr.Slider(
177
- label="Frame Count",
178
- minimum=1,
179
- maximum=257,
180
- step=1,
181
- value=24,
182
- )
183
- num_inference_steps = gr.Slider(
184
- label="Inference Steps",
185
- minimum=1,
186
- maximum=50,
187
- step=1,
188
- value=25,
189
- )
190
- fps = gr.Slider(
191
- label="FPS",
192
- minimum=1,
193
- maximum=60,
194
- step=1,
195
- value=12,
196
- )
197
-
198
- with gr.Accordion("🧩 LoRA Configuration", open=False):
199
- lora_checkboxes = []
200
- lora_sliders = []
201
- for lora in LORA_CHOICES:
202
- with gr.Row():
203
- cb = gr.Checkbox(label=f"Enable {lora}", value=False)
204
- sl = gr.Slider(0.0, 1.0, value=0.8, label=f"{lora} Weight")
205
- lora_checkboxes.append(cb)
206
- lora_sliders.append(sl)
207
-
208
- # Event handling
209
- run_button.click(
210
  fn=generate,
211
- inputs=[prompt, image_input, height, width, num_frames,
212
- num_inference_steps, seed, fps, lora_checkboxes, lora_sliders],
213
- outputs=result
214
- )
215
-
216
- preset_high_res.click(
217
- fn=lambda: apply_preset("Higher Resolution"),
218
- outputs=[height, width, num_frames, num_inference_steps, fps]
219
- )
220
-
221
- preset_more_frames.click(
222
- fn=lambda: apply_preset("More Frames"),
223
- outputs=[height, width, num_frames, num_inference_steps, fps]
224
  )
 
1
  import spaces
2
  import gradio as gr
3
  import numpy as np
 
4
  import torch
 
 
5
  from diffusers import HunyuanVideoPipeline
6
  from huggingface_hub import snapshot_download
7
+ from PIL import Image
8
+ import os
9
 
10
  # Configuration
11
  LORA_CHOICES = [
 
26
  torch_dtype=torch.float16
27
  ).to("cuda")
28
 
29
+ # Load LoRA adapters
30
  for lora_file in LORA_CHOICES:
31
+ pipe.load_lora_weights(
32
+ "Sergidev/TTV4ME",
33
+ weight_name=lora_file,
34
+ adapter_name=lora_file.split('.')[0],
35
+ token=os.environ.get("HF_TOKEN")
36
+ )
 
 
 
37
 
38
  @spaces.GPU(duration=300)
39
+ def generate(prompt, image_input, height, width, num_frames,
40
+ num_inference_steps, seed_value, fps, selected_loras, lora_weights):
 
 
 
 
 
 
 
 
 
 
 
41
  # Image validation
42
  if image_input is not None:
43
  img = Image.open(image_input)
 
53
  active_adapters.append(LORA_CHOICES[idx].split('.')[0])
54
  adapter_weights.append(lora_weights[idx])
55
 
56
+ pipe.set_adapters(active_adapters, adapter_weights)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
 
58
+ # Generate video
59
+ generator = torch.Generator('cuda').manual_seed(seed_value if seed_value != -1 else torch.seed())
 
 
 
 
 
 
 
 
 
 
60
 
61
+ if image_input:
62
+ output = pipe.image_to_video(
63
+ Image.open(image_input).convert("RGB"),
64
+ prompt=prompt,
65
+ height=height,
66
+ width=width,
67
+ num_frames=num_frames,
68
+ num_inference_steps=num_inference_steps,
69
+ generator=generator,
70
+ )
71
+ else:
72
+ output = pipe.text_to_video(
73
+ prompt=prompt,
74
+ height=height,
75
+ width=width,
76
+ num_frames=num_frames,
77
+ num_inference_steps=num_inference_steps,
78
+ generator=generator,
79
+ )
80
 
81
+ return output.frames[0]
82
+
83
+ with gr.Blocks(theme="dark") as demo:
84
+ with gr.Column():
85
+ gr.Markdown("# 🎬 Hunyuan Studio")
86
 
87
  with gr.Row():
88
+ with gr.Column():
89
+ prompt = gr.Textbox(label="Prompt")
90
+ image_input = gr.Image(label="Input Image", type="filepath")
91
+
92
+ with gr.Accordion("Advanced Settings"):
93
+ resolution = gr.Dropdown(
94
+ choices=["512x512", "768x768", "1024x1024"],
95
+ value="512x512",
96
+ label="Output Resolution"
97
+ )
98
+ seed = gr.Slider(-1, MAX_SEED, value=-1, label="Seed")
99
+ num_frames = gr.Slider(1, 257, 24, label="Frame Count")
100
+ num_inference_steps = gr.Slider(1, 50, 25, label="Inference Steps")
101
+ fps = gr.Slider(1, 60, 12, label="FPS")
102
+
103
+ with gr.Accordion("LoRA Configuration"):
104
+ lora_components = []
105
+ for lora in LORA_CHOICES:
106
+ lora_components.append(gr.Checkbox(label=f"Enable {lora}"))
107
+ lora_components.append(gr.Slider(0.0, 1.0, 0.8, label=f"{lora} Weight"))
108
+
109
+ generate_btn = gr.Button("Generate Video")
110
+
111
+ with gr.Column():
112
+ output_video = gr.Video(label="Result")
113
+
114
+ generate_btn.click(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115
  fn=generate,
116
+ inputs=[prompt, image_input,
117
+ gr.Number(512), gr.Number(512), # Height/width from resolution
118
+ num_frames, num_inference_steps, seed, fps,
119
+ *lora_components],
120
+ outputs=output_video
 
 
 
 
 
 
 
 
121
  )
requirements.txt CHANGED
@@ -1,12 +1,11 @@
1
  --extra-index-url https://download.pytorch.org/whl/cu124
2
- diffusers==0.29.0
3
- transformers==4.41.0
4
- gradio>=4.0.0
5
  torch>=2.4.0,<2.6.0
6
- safetensors>=0.4.2
7
- huggingface_hub>=0.23.0
8
- imageio>=2.34.0
9
- opencv-python-headless>=4.9.0
 
10
  Pillow>=10.2.0
11
  numpy<2.0
12
- accelerate>=0.30.0
 
1
  --extra-index-url https://download.pytorch.org/whl/cu124
2
+ git+https://github.com/huggingface/diffusers.git@main
3
+ git+https://github.com/huggingface/transformers.git@main
 
4
  torch>=2.4.0,<2.6.0
5
+ gradio>=4.0.0
6
+ safetensors
7
+ huggingface_hub
8
+ imageio
9
+ opencv-python-headless
10
  Pillow>=10.2.0
11
  numpy<2.0
 
utils.py CHANGED
@@ -1,25 +1,9 @@
1
  def install_packages():
2
  import subprocess
3
  import sys
4
- import importlib
5
-
6
- required = [
7
- 'torch>=2.4.0,<2.6.0',
8
- 'diffusers',
9
- 'transformers',
10
- 'gradio',
11
- 'safetensors',
12
- 'huggingface_hub',
13
- 'imageio',
14
- 'opencv-python-headless',
15
- 'Pillow'
16
- ]
17
 
18
  subprocess.run([
19
  sys.executable, "-m", "pip", "install",
20
- "--upgrade", "pip", "setuptools", "wheel"
 
21
  ], check=True)
22
-
23
- subprocess.run([
24
- sys.executable, "-m", "pip", "install"
25
- ] + required, check=True)
 
1
  def install_packages():
2
  import subprocess
3
  import sys
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
  subprocess.run([
6
  sys.executable, "-m", "pip", "install",
7
+ "-r", "requirements.txt",
8
+ "--upgrade"
9
  ], check=True)