68ed8100 commited on
Commit
afbf058
·
1 Parent(s): 0e9a299
Files changed (2) hide show
  1. app.py +102 -79
  2. appold.py +364 -0
app.py CHANGED
@@ -2,6 +2,7 @@ import os
2
  import gc
3
  import torch
4
  import gradio as gr
 
5
 
6
  from diffusers import WanAnimatePipeline
7
  from diffusers.utils import load_image, load_video, export_to_video
@@ -16,6 +17,8 @@ MODEL_ID = "Wan-AI/Wan2.2-Animate-14B-Diffusers"
16
  OUTPUT_DIR = "/tmp/outputs"
17
  os.makedirs(OUTPUT_DIR, exist_ok=True)
18
 
 
 
19
 
20
  # ============================================================
21
  # PRESETS
@@ -24,10 +27,10 @@ os.makedirs(OUTPUT_DIR, exist_ok=True)
24
  PRESETS = {
25
  "Realistic": {
26
  "prompt": (
27
- "A highly realistic video of the reference character performing "
28
- "the movements from the input motion video. Preserve identity, "
29
- "facial appearance, hairstyle and clothing. Natural body motion, "
30
- "realistic lighting and physics."
31
  ),
32
  "steps": 20,
33
  "guidance": 1.0,
@@ -69,34 +72,34 @@ PRESETS = {
69
 
70
 
71
  # ============================================================
72
- # LOAD MODEL
73
  # ============================================================
74
 
75
- print("Loading Wan2.2 Animate...")
76
 
77
- if not torch.cuda.is_available():
78
- raise RuntimeError(
79
- "CUDA GPU is required. "
80
- "Use a GPU-enabled Hugging Face Space."
81
- )
82
 
83
- print("GPU:", torch.cuda.get_device_name(0))
84
 
85
- pipe = WanAnimatePipeline.from_pretrained(
86
- MODEL_ID,
87
- torch_dtype=torch.bfloat16,
88
- )
 
 
 
 
89
 
90
- # Important for limited VRAM
91
- pipe.enable_model_cpu_offload()
92
 
93
- print("Model loaded.")
94
 
95
 
96
  # ============================================================
97
  # GENERATION
98
  # ============================================================
99
 
 
100
  def generate_video(
101
  prompt,
102
  reference_image,
@@ -109,54 +112,83 @@ def generate_video(
109
  ):
110
 
111
  if reference_image is None:
112
- raise gr.Error("Please upload a reference image.")
 
 
113
 
114
  if motion_video is None:
115
- raise gr.Error("Please upload a motion video.")
 
 
 
 
 
 
 
 
 
 
 
 
 
116
 
117
  # --------------------------------------------------------
118
  # PRESET
119
  # --------------------------------------------------------
120
 
121
- preset_config = PRESETS[preset]
122
 
123
  if not prompt or not prompt.strip():
124
- prompt = preset_config["prompt"]
125
 
126
  # --------------------------------------------------------
127
  # LOAD INPUTS
128
  # --------------------------------------------------------
129
 
130
- progress(0.1, desc="Loading reference image...")
 
 
 
131
 
132
- image = load_image(reference_image)
 
 
133
 
134
- progress(0.2, desc="Loading motion video...")
 
 
 
135
 
136
- motion = load_video(motion_video)
 
 
137
 
138
  # --------------------------------------------------------
139
- # CONDITIONING
140
  #
141
- # For the basic workflow we use the motion video as
142
- # both pose and face conditioning.
143
- #
144
- # For best results, replace this with Wan Animate's
145
- # official preprocessing pipeline.
146
  # --------------------------------------------------------
147
 
148
  pose_video = motion
149
  face_video = motion
150
 
151
  # --------------------------------------------------------
152
- # GENERATION
153
  # --------------------------------------------------------
154
 
155
- progress(0.3, desc="Generating video...")
 
 
 
156
 
157
  generator = torch.Generator(
158
  device="cuda"
159
- ).manual_seed(int(seed))
 
 
160
 
161
  with torch.inference_mode():
162
 
@@ -168,20 +200,27 @@ def generate_video(
168
  mode="animate",
169
  segment_frame_length=77,
170
  prev_segment_conditioning_frames=1,
171
- guidance_scale=float(guidance_scale),
172
- num_inference_steps=int(inference_steps),
 
 
 
 
173
  generator=generator,
174
  ).frames[0]
175
 
176
- progress(0.9, desc="Encoding output video...")
177
-
178
  # --------------------------------------------------------
179
- # SAVE
180
  # --------------------------------------------------------
181
 
 
 
 
 
 
182
  output_path = os.path.join(
183
  OUTPUT_DIR,
184
- f"generated_{int(seed)}.mp4"
185
  )
186
 
187
  export_to_video(
@@ -190,20 +229,18 @@ def generate_video(
190
  fps=30,
191
  )
192
 
193
- # --------------------------------------------------------
194
- # CLEANUP
195
- # --------------------------------------------------------
 
196
 
197
  gc.collect()
198
- torch.cuda.empty_cache()
199
-
200
- progress(1.0, desc="Done")
201
 
202
  return output_path
203
 
204
 
205
  # ============================================================
206
- # PRESET HANDLER
207
  # ============================================================
208
 
209
  def update_preset(preset):
@@ -229,39 +266,35 @@ with gr.Blocks(
229
  """
230
  # 🎬 Wan2.2 Character Animation
231
 
232
- Generate a video using:
233
 
234
- **Reference Photo + Motion Video + Prompt → Generated Video**
235
-
236
- The reference image provides the character identity.
237
  The motion video provides the movement.
238
  """
239
  )
240
 
241
  with gr.Row():
242
 
243
- # ----------------------------------------------------
244
- # LEFT
245
- # ----------------------------------------------------
246
-
247
  with gr.Column():
248
 
249
  prompt = gr.Textbox(
250
  label="Prompt",
 
251
  placeholder=(
252
  "Describe the generated video..."
253
  ),
254
- lines=5,
255
  )
256
 
257
  preset = gr.Dropdown(
258
- choices=list(PRESETS.keys()),
 
 
259
  value="Realistic",
260
  label="Style Preset",
261
  )
262
 
263
  reference_image = gr.Image(
264
- label="Reference Photo / Character",
265
  type="filepath",
266
  )
267
 
@@ -270,10 +303,6 @@ with gr.Blocks(
270
  sources=["upload"],
271
  )
272
 
273
- # ----------------------------------------------------
274
- # RIGHT
275
- # ----------------------------------------------------
276
-
277
  with gr.Column():
278
 
279
  output_video = gr.Video(
@@ -282,12 +311,12 @@ with gr.Blocks(
282
  )
283
 
284
  generate_button = gr.Button(
285
- "🎬 Generate Video",
286
  variant="primary",
287
  )
288
 
289
  # ========================================================
290
- # ADVANCED SETTINGS
291
  # ========================================================
292
 
293
  with gr.Accordion(
@@ -318,12 +347,12 @@ with gr.Blocks(
318
  )
319
 
320
  # ========================================================
321
- # PRESET EVENT
322
  # ========================================================
323
 
324
  preset.change(
325
  fn=update_preset,
326
- inputs=[preset],
327
  outputs=[
328
  prompt,
329
  inference_steps,
@@ -331,10 +360,6 @@ with gr.Blocks(
331
  ],
332
  )
333
 
334
- # ========================================================
335
- # GENERATE EVENT
336
- # ========================================================
337
-
338
  generate_button.click(
339
  fn=generate_video,
340
  inputs=[
@@ -354,11 +379,9 @@ with gr.Blocks(
354
  # LAUNCH
355
  # ============================================================
356
 
357
- if __name__ == "__main__":
358
-
359
- demo.queue(
360
- max_size=10,
361
- default_concurrency_limit=1,
362
- )
363
 
364
- demo.launch()
 
2
  import gc
3
  import torch
4
  import gradio as gr
5
+ import spaces
6
 
7
  from diffusers import WanAnimatePipeline
8
  from diffusers.utils import load_image, load_video, export_to_video
 
17
  OUTPUT_DIR = "/tmp/outputs"
18
  os.makedirs(OUTPUT_DIR, exist_ok=True)
19
 
20
+ pipe = None
21
+
22
 
23
  # ============================================================
24
  # PRESETS
 
27
  PRESETS = {
28
  "Realistic": {
29
  "prompt": (
30
+ "A highly realistic video of the reference character "
31
+ "performing the movements from the input motion video. "
32
+ "Preserve identity, facial appearance, hairstyle and clothing. "
33
+ "Natural body motion, realistic lighting and physics."
34
  ),
35
  "steps": 20,
36
  "guidance": 1.0,
 
72
 
73
 
74
  # ============================================================
75
+ # MODEL LOADING
76
  # ============================================================
77
 
78
+ def get_pipeline():
79
 
80
+ global pipe
 
 
 
 
81
 
82
+ if pipe is None:
83
 
84
+ print("Loading Wan2.2 Animate...")
85
+
86
+ pipe = WanAnimatePipeline.from_pretrained(
87
+ MODEL_ID,
88
+ torch_dtype=torch.bfloat16,
89
+ )
90
+
91
+ pipe.enable_model_cpu_offload()
92
 
93
+ print("Wan2.2 Animate loaded.")
 
94
 
95
+ return pipe
96
 
97
 
98
  # ============================================================
99
  # GENERATION
100
  # ============================================================
101
 
102
+ @spaces.GPU
103
  def generate_video(
104
  prompt,
105
  reference_image,
 
112
  ):
113
 
114
  if reference_image is None:
115
+ raise gr.Error(
116
+ "Please upload a reference image."
117
+ )
118
 
119
  if motion_video is None:
120
+ raise gr.Error(
121
+ "Please upload a motion video."
122
+ )
123
+
124
+ # --------------------------------------------------------
125
+ # LOAD MODEL AFTER ZERO GPU ALLOCATION
126
+ # --------------------------------------------------------
127
+
128
+ progress(
129
+ 0.05,
130
+ desc="Loading Wan2.2 Animate..."
131
+ )
132
+
133
+ pipe = get_pipeline()
134
 
135
  # --------------------------------------------------------
136
  # PRESET
137
  # --------------------------------------------------------
138
 
139
+ config = PRESETS[preset]
140
 
141
  if not prompt or not prompt.strip():
142
+ prompt = config["prompt"]
143
 
144
  # --------------------------------------------------------
145
  # LOAD INPUTS
146
  # --------------------------------------------------------
147
 
148
+ progress(
149
+ 0.15,
150
+ desc="Loading reference image..."
151
+ )
152
 
153
+ image = load_image(
154
+ reference_image
155
+ )
156
 
157
+ progress(
158
+ 0.25,
159
+ desc="Loading motion video..."
160
+ )
161
 
162
+ motion = load_video(
163
+ motion_video
164
+ )
165
 
166
  # --------------------------------------------------------
167
+ # TEMPORARY CONDITIONING
168
  #
169
+ # NOTE:
170
+ # For the real Wan2.2 Animate workflow, the motion video
171
+ # should be processed into dedicated pose/face inputs.
172
+ # This is the basic prototype.
 
173
  # --------------------------------------------------------
174
 
175
  pose_video = motion
176
  face_video = motion
177
 
178
  # --------------------------------------------------------
179
+ # GENERATE
180
  # --------------------------------------------------------
181
 
182
+ progress(
183
+ 0.35,
184
+ desc="Generating video..."
185
+ )
186
 
187
  generator = torch.Generator(
188
  device="cuda"
189
+ ).manual_seed(
190
+ int(seed)
191
+ )
192
 
193
  with torch.inference_mode():
194
 
 
200
  mode="animate",
201
  segment_frame_length=77,
202
  prev_segment_conditioning_frames=1,
203
+ guidance_scale=float(
204
+ guidance_scale
205
+ ),
206
+ num_inference_steps=int(
207
+ inference_steps
208
+ ),
209
  generator=generator,
210
  ).frames[0]
211
 
 
 
212
  # --------------------------------------------------------
213
+ # EXPORT
214
  # --------------------------------------------------------
215
 
216
+ progress(
217
+ 0.9,
218
+ desc="Encoding video..."
219
+ )
220
+
221
  output_path = os.path.join(
222
  OUTPUT_DIR,
223
+ f"output_{int(seed)}.mp4"
224
  )
225
 
226
  export_to_video(
 
229
  fps=30,
230
  )
231
 
232
+ progress(
233
+ 1.0,
234
+ desc="Done"
235
+ )
236
 
237
  gc.collect()
 
 
 
238
 
239
  return output_path
240
 
241
 
242
  # ============================================================
243
+ # PRESET UPDATE
244
  # ============================================================
245
 
246
  def update_preset(preset):
 
266
  """
267
  # 🎬 Wan2.2 Character Animation
268
 
269
+ **Reference Photo + Motion Video + Prompt → Video**
270
 
271
+ The reference photo provides the character identity.
 
 
272
  The motion video provides the movement.
273
  """
274
  )
275
 
276
  with gr.Row():
277
 
 
 
 
 
278
  with gr.Column():
279
 
280
  prompt = gr.Textbox(
281
  label="Prompt",
282
+ lines=5,
283
  placeholder=(
284
  "Describe the generated video..."
285
  ),
 
286
  )
287
 
288
  preset = gr.Dropdown(
289
+ choices=list(
290
+ PRESETS.keys()
291
+ ),
292
  value="Realistic",
293
  label="Style Preset",
294
  )
295
 
296
  reference_image = gr.Image(
297
+ label="Reference Photo",
298
  type="filepath",
299
  )
300
 
 
303
  sources=["upload"],
304
  )
305
 
 
 
 
 
306
  with gr.Column():
307
 
308
  output_video = gr.Video(
 
311
  )
312
 
313
  generate_button = gr.Button(
314
+ "🎬 Generate",
315
  variant="primary",
316
  )
317
 
318
  # ========================================================
319
+ # ADVANCED
320
  # ========================================================
321
 
322
  with gr.Accordion(
 
347
  )
348
 
349
  # ========================================================
350
+ # EVENTS
351
  # ========================================================
352
 
353
  preset.change(
354
  fn=update_preset,
355
+ inputs=preset,
356
  outputs=[
357
  prompt,
358
  inference_steps,
 
360
  ],
361
  )
362
 
 
 
 
 
363
  generate_button.click(
364
  fn=generate_video,
365
  inputs=[
 
379
  # LAUNCH
380
  # ============================================================
381
 
382
+ demo.queue(
383
+ max_size=10,
384
+ default_concurrency_limit=1,
385
+ )
 
 
386
 
387
+ demo.launch()
appold.py ADDED
@@ -0,0 +1,364 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import gc
3
+ import torch
4
+ import gradio as gr
5
+
6
+ from diffusers import WanAnimatePipeline
7
+ from diffusers.utils import load_image, load_video, export_to_video
8
+
9
+
10
+ # ============================================================
11
+ # CONFIG
12
+ # ============================================================
13
+
14
+ MODEL_ID = "Wan-AI/Wan2.2-Animate-14B-Diffusers"
15
+
16
+ OUTPUT_DIR = "/tmp/outputs"
17
+ os.makedirs(OUTPUT_DIR, exist_ok=True)
18
+
19
+
20
+ # ============================================================
21
+ # PRESETS
22
+ # ============================================================
23
+
24
+ PRESETS = {
25
+ "Realistic": {
26
+ "prompt": (
27
+ "A highly realistic video of the reference character performing "
28
+ "the movements from the input motion video. Preserve identity, "
29
+ "facial appearance, hairstyle and clothing. Natural body motion, "
30
+ "realistic lighting and physics."
31
+ ),
32
+ "steps": 20,
33
+ "guidance": 1.0,
34
+ },
35
+
36
+ "Cinematic": {
37
+ "prompt": (
38
+ "A cinematic photorealistic video of the character performing "
39
+ "the exact movements and actions from the reference motion video. "
40
+ "Natural facial expressions, realistic skin, detailed clothing, "
41
+ "cinematic lighting, shallow depth of field, professional camera."
42
+ ),
43
+ "steps": 20,
44
+ "guidance": 1.0,
45
+ },
46
+
47
+ "Portrait": {
48
+ "prompt": (
49
+ "A photorealistic portrait video of the reference character. "
50
+ "Preserve the character's identity and facial features while "
51
+ "accurately following the body and facial motion from the input video. "
52
+ "Natural expression, realistic skin and cinematic portrait lighting."
53
+ ),
54
+ "steps": 20,
55
+ "guidance": 1.0,
56
+ },
57
+
58
+ "Anime": {
59
+ "prompt": (
60
+ "An anime-style cinematic video featuring the reference character, "
61
+ "accurately reproducing the movement and performance from the input "
62
+ "motion video. Consistent character identity, expressive animation, "
63
+ "detailed anime background."
64
+ ),
65
+ "steps": 20,
66
+ "guidance": 1.0,
67
+ },
68
+ }
69
+
70
+
71
+ # ============================================================
72
+ # LOAD MODEL
73
+ # ============================================================
74
+
75
+ print("Loading Wan2.2 Animate...")
76
+
77
+ if not torch.cuda.is_available():
78
+ raise RuntimeError(
79
+ "CUDA GPU is required. "
80
+ "Use a GPU-enabled Hugging Face Space."
81
+ )
82
+
83
+ print("GPU:", torch.cuda.get_device_name(0))
84
+
85
+ pipe = WanAnimatePipeline.from_pretrained(
86
+ MODEL_ID,
87
+ torch_dtype=torch.bfloat16,
88
+ )
89
+
90
+ # Important for limited VRAM
91
+ pipe.enable_model_cpu_offload()
92
+
93
+ print("Model loaded.")
94
+
95
+
96
+ # ============================================================
97
+ # GENERATION
98
+ # ============================================================
99
+
100
+ def generate_video(
101
+ prompt,
102
+ reference_image,
103
+ motion_video,
104
+ preset,
105
+ seed,
106
+ inference_steps,
107
+ guidance_scale,
108
+ progress=gr.Progress(),
109
+ ):
110
+
111
+ if reference_image is None:
112
+ raise gr.Error("Please upload a reference image.")
113
+
114
+ if motion_video is None:
115
+ raise gr.Error("Please upload a motion video.")
116
+
117
+ # --------------------------------------------------------
118
+ # PRESET
119
+ # --------------------------------------------------------
120
+
121
+ preset_config = PRESETS[preset]
122
+
123
+ if not prompt or not prompt.strip():
124
+ prompt = preset_config["prompt"]
125
+
126
+ # --------------------------------------------------------
127
+ # LOAD INPUTS
128
+ # --------------------------------------------------------
129
+
130
+ progress(0.1, desc="Loading reference image...")
131
+
132
+ image = load_image(reference_image)
133
+
134
+ progress(0.2, desc="Loading motion video...")
135
+
136
+ motion = load_video(motion_video)
137
+
138
+ # --------------------------------------------------------
139
+ # CONDITIONING
140
+ #
141
+ # For the basic workflow we use the motion video as
142
+ # both pose and face conditioning.
143
+ #
144
+ # For best results, replace this with Wan Animate's
145
+ # official preprocessing pipeline.
146
+ # --------------------------------------------------------
147
+
148
+ pose_video = motion
149
+ face_video = motion
150
+
151
+ # --------------------------------------------------------
152
+ # GENERATION
153
+ # --------------------------------------------------------
154
+
155
+ progress(0.3, desc="Generating video...")
156
+
157
+ generator = torch.Generator(
158
+ device="cuda"
159
+ ).manual_seed(int(seed))
160
+
161
+ with torch.inference_mode():
162
+
163
+ result = pipe(
164
+ image=image,
165
+ pose_video=pose_video,
166
+ face_video=face_video,
167
+ prompt=prompt,
168
+ mode="animate",
169
+ segment_frame_length=77,
170
+ prev_segment_conditioning_frames=1,
171
+ guidance_scale=float(guidance_scale),
172
+ num_inference_steps=int(inference_steps),
173
+ generator=generator,
174
+ ).frames[0]
175
+
176
+ progress(0.9, desc="Encoding output video...")
177
+
178
+ # --------------------------------------------------------
179
+ # SAVE
180
+ # --------------------------------------------------------
181
+
182
+ output_path = os.path.join(
183
+ OUTPUT_DIR,
184
+ f"generated_{int(seed)}.mp4"
185
+ )
186
+
187
+ export_to_video(
188
+ result,
189
+ output_path,
190
+ fps=30,
191
+ )
192
+
193
+ # --------------------------------------------------------
194
+ # CLEANUP
195
+ # --------------------------------------------------------
196
+
197
+ gc.collect()
198
+ torch.cuda.empty_cache()
199
+
200
+ progress(1.0, desc="Done")
201
+
202
+ return output_path
203
+
204
+
205
+ # ============================================================
206
+ # PRESET HANDLER
207
+ # ============================================================
208
+
209
+ def update_preset(preset):
210
+
211
+ config = PRESETS[preset]
212
+
213
+ return (
214
+ config["prompt"],
215
+ config["steps"],
216
+ config["guidance"],
217
+ )
218
+
219
+
220
+ # ============================================================
221
+ # GRADIO UI
222
+ # ============================================================
223
+
224
+ with gr.Blocks(
225
+ title="Wan2.2 Character Animation"
226
+ ) as demo:
227
+
228
+ gr.Markdown(
229
+ """
230
+ # 🎬 Wan2.2 Character Animation
231
+
232
+ Generate a video using:
233
+
234
+ **Reference Photo + Motion Video + Prompt → Generated Video**
235
+
236
+ The reference image provides the character identity.
237
+ The motion video provides the movement.
238
+ """
239
+ )
240
+
241
+ with gr.Row():
242
+
243
+ # ----------------------------------------------------
244
+ # LEFT
245
+ # ----------------------------------------------------
246
+
247
+ with gr.Column():
248
+
249
+ prompt = gr.Textbox(
250
+ label="Prompt",
251
+ placeholder=(
252
+ "Describe the generated video..."
253
+ ),
254
+ lines=5,
255
+ )
256
+
257
+ preset = gr.Dropdown(
258
+ choices=list(PRESETS.keys()),
259
+ value="Realistic",
260
+ label="Style Preset",
261
+ )
262
+
263
+ reference_image = gr.Image(
264
+ label="Reference Photo / Character",
265
+ type="filepath",
266
+ )
267
+
268
+ motion_video = gr.Video(
269
+ label="Motion Video",
270
+ sources=["upload"],
271
+ )
272
+
273
+ # ----------------------------------------------------
274
+ # RIGHT
275
+ # ----------------------------------------------------
276
+
277
+ with gr.Column():
278
+
279
+ output_video = gr.Video(
280
+ label="Generated Video",
281
+ autoplay=True,
282
+ )
283
+
284
+ generate_button = gr.Button(
285
+ "🎬 Generate Video",
286
+ variant="primary",
287
+ )
288
+
289
+ # ========================================================
290
+ # ADVANCED SETTINGS
291
+ # ========================================================
292
+
293
+ with gr.Accordion(
294
+ "Advanced Settings",
295
+ open=False,
296
+ ):
297
+
298
+ seed = gr.Number(
299
+ label="Seed",
300
+ value=42,
301
+ precision=0,
302
+ )
303
+
304
+ inference_steps = gr.Slider(
305
+ minimum=5,
306
+ maximum=50,
307
+ value=20,
308
+ step=1,
309
+ label="Inference Steps",
310
+ )
311
+
312
+ guidance_scale = gr.Slider(
313
+ minimum=0.5,
314
+ maximum=5.0,
315
+ value=1.0,
316
+ step=0.1,
317
+ label="Guidance Scale",
318
+ )
319
+
320
+ # ========================================================
321
+ # PRESET EVENT
322
+ # ========================================================
323
+
324
+ preset.change(
325
+ fn=update_preset,
326
+ inputs=[preset],
327
+ outputs=[
328
+ prompt,
329
+ inference_steps,
330
+ guidance_scale,
331
+ ],
332
+ )
333
+
334
+ # ========================================================
335
+ # GENERATE EVENT
336
+ # ========================================================
337
+
338
+ generate_button.click(
339
+ fn=generate_video,
340
+ inputs=[
341
+ prompt,
342
+ reference_image,
343
+ motion_video,
344
+ preset,
345
+ seed,
346
+ inference_steps,
347
+ guidance_scale,
348
+ ],
349
+ outputs=output_video,
350
+ )
351
+
352
+
353
+ # ============================================================
354
+ # LAUNCH
355
+ # ============================================================
356
+
357
+ if __name__ == "__main__":
358
+
359
+ demo.queue(
360
+ max_size=10,
361
+ default_concurrency_limit=1,
362
+ )
363
+
364
+ demo.launch()