ethan-decart commited on
Commit
94439e4
·
1 Parent(s): b5d7d70

Add refined examples

Browse files
Files changed (3) hide show
  1. app.py +29 -30
  2. examples/neon.mp4 +3 -0
  3. examples/painter.mp4 +3 -0
app.py CHANGED
@@ -18,20 +18,20 @@ def calculate_resolution(input_width, input_height, min_dimension=480, max_dimen
18
  # Ensure dimensions are multiples of the compatible rounding
19
  def round_to(x, compatible_round):
20
  return max(min_dimension, min(max_dimension, int(round(x / compatible_round) * compatible_round)))
21
-
22
  # Get aspect ratio
23
  aspect_ratio = input_width / input_height
24
-
25
  # Square videos (aspect ratio close to 1:1)
26
  if 0.98 <= aspect_ratio <= 1.02:
27
  return 640, 640
28
-
29
  # Landscape videos (width > height)
30
  elif aspect_ratio > 1:
31
  # Try to use max width
32
  new_width = max_dimension
33
  new_height = new_width / aspect_ratio
34
-
35
  # If height would be too small, use min height
36
  if new_height < min_dimension:
37
  new_height = min_dimension
@@ -39,15 +39,15 @@ def calculate_resolution(input_width, input_height, min_dimension=480, max_dimen
39
  # If width exceeds max, clamp it
40
  if new_width > max_dimension:
41
  new_width = max_dimension
42
-
43
  return round_to(new_width, compatible_round), round_to(new_height, compatible_round)
44
-
45
  # Portrait videos (height > width)
46
  else:
47
  # Try to use max height
48
  new_height = max_dimension
49
  new_width = new_height * aspect_ratio
50
-
51
  # If width would be too small, use min width
52
  if new_width < min_dimension:
53
  new_width = min_dimension
@@ -55,7 +55,7 @@ def calculate_resolution(input_width, input_height, min_dimension=480, max_dimen
55
  # If height exceeds max, clamp it
56
  if new_height > max_dimension:
57
  new_height = max_dimension
58
-
59
  return round_to(new_width, compatible_round), round_to(new_height, compatible_round)
60
 
61
 
@@ -73,13 +73,13 @@ def process_video(
73
  ):
74
  # Load and preprocess video
75
  progress(0.2, desc="Loading video...")
76
-
77
  # Get video dimensions
78
  temp_video = load_video(video_path)
79
  print(len(temp_video))
80
  if temp_video and len(temp_video) > 0:
81
  original_width, original_height = temp_video[0].size
82
-
83
  # Calculate dimensions
84
  if auto_resize:
85
  width, height = calculate_resolution(original_width, original_height)
@@ -87,7 +87,7 @@ def process_video(
87
  width, height = manual_width, manual_height
88
  else:
89
  raise gr.Error("Could not load video or video is empty")
90
-
91
  # Convert video function
92
  def convert_video(video: List[Image.Image]) -> List[Image.Image]:
93
  # Ensure we don't exceed the video length
@@ -96,14 +96,14 @@ def process_video(
96
  # Resize frames
97
  video_frames = [frame.resize((width, height)) for frame in video_frames]
98
  return video_frames
99
-
100
  # Load video from file path
101
  video = load_video(video_path, convert_method=convert_video)
102
-
103
  # Ensure we have the right number of frames
104
  if len(video) < num_frames:
105
  num_frames = len(video)
106
-
107
  # Generate edited video
108
  progress(0.5, desc="Generating edited video...")
109
  output = pipe(
@@ -115,14 +115,14 @@ def process_video(
115
  num_frames=num_frames,
116
  guidance_scale=guidance_scale,
117
  ).frames[0]
118
-
119
  # Export to temporary file
120
  progress(0.9, desc="Exporting video...")
121
  with tempfile.NamedTemporaryFile(delete=False, suffix=".mp4") as tmp_file:
122
  output_path = tmp_file.name
123
-
124
  export_to_video(output, output_path, fps=24)
125
-
126
  progress(1.0, desc="Complete!")
127
  return output_path
128
 
@@ -141,18 +141,18 @@ with gr.Blocks(title="Lucy Edit - Video Editing with Text", css=css) as demo:
141
  &nbsp;|&nbsp; 📑 <a href="#">arXiv (Coming soon)</a>
142
  &nbsp;|&nbsp; 💬 <a href="https://discord.gg/decart">Discord</a>
143
  </p>""")
144
-
145
  with gr.Row():
146
  with gr.Column(scale=1):
147
  # Input controls
148
  video_input = gr.Video(label="Input Video")
149
-
150
  prompt = gr.Textbox(
151
  label="Edit Prompt",
152
  placeholder="Describe what you want to change in the video...",
153
  lines=3
154
  )
155
-
156
  with gr.Accordion("Advanced Settings", open=False):
157
  negative_prompt = gr.Textbox(
158
  label="Negative Prompt (optional)",
@@ -164,7 +164,7 @@ with gr.Blocks(title="Lucy Edit - Video Editing with Text", css=css) as demo:
164
  value=True,
165
  info="Automatically calculate dimensions based on input video"
166
  )
167
-
168
  num_frames = gr.Slider(
169
  label="Number of Frames",
170
  minimum=1,
@@ -173,7 +173,7 @@ with gr.Blocks(title="Lucy Edit - Video Editing with Text", css=css) as demo:
173
  step=1,
174
  info="More frames = longer processing time"
175
  )
176
-
177
  with gr.Row():
178
  manual_height = gr.Slider(
179
  label="Height (when auto-resize is off)",
@@ -189,7 +189,7 @@ with gr.Blocks(title="Lucy Edit - Video Editing with Text", css=css) as demo:
189
  value=832,
190
  step=32
191
  )
192
-
193
  guidance_scale = gr.Slider(
194
  label="Guidance Scale",
195
  minimum=1.0,
@@ -198,24 +198,23 @@ with gr.Blocks(title="Lucy Edit - Video Editing with Text", css=css) as demo:
198
  step=0.5,
199
  info="Higher values follow the prompt more strictly"
200
  )
201
-
202
  generate_btn = gr.Button("Edit Video", variant="primary")
203
-
204
  with gr.Column(scale=1):
205
  video_output = gr.Video(label="Edited Video")
206
 
207
  gr.Examples(
208
  examples=[
209
- ["examples/man_walking.mp4", "make the man into an alien"],
210
- ["examples/leopard.mp4", "make the leopard into a lion"],
211
- ["examples/woman.mp4", "make the woman's coat blue"],
212
  ],
213
  inputs=[video_input, prompt],
214
  outputs=video_output,
215
  fn=process_video,
216
  cache_examples="lazy",
217
  )
218
-
219
  # Event handlers
220
  generate_btn.click(
221
  fn=process_video,
@@ -233,4 +232,4 @@ with gr.Blocks(title="Lucy Edit - Video Editing with Text", css=css) as demo:
233
  )
234
 
235
  if __name__ == "__main__":
236
- demo.launch(share=True)
 
18
  # Ensure dimensions are multiples of the compatible rounding
19
  def round_to(x, compatible_round):
20
  return max(min_dimension, min(max_dimension, int(round(x / compatible_round) * compatible_round)))
21
+
22
  # Get aspect ratio
23
  aspect_ratio = input_width / input_height
24
+
25
  # Square videos (aspect ratio close to 1:1)
26
  if 0.98 <= aspect_ratio <= 1.02:
27
  return 640, 640
28
+
29
  # Landscape videos (width > height)
30
  elif aspect_ratio > 1:
31
  # Try to use max width
32
  new_width = max_dimension
33
  new_height = new_width / aspect_ratio
34
+
35
  # If height would be too small, use min height
36
  if new_height < min_dimension:
37
  new_height = min_dimension
 
39
  # If width exceeds max, clamp it
40
  if new_width > max_dimension:
41
  new_width = max_dimension
42
+
43
  return round_to(new_width, compatible_round), round_to(new_height, compatible_round)
44
+
45
  # Portrait videos (height > width)
46
  else:
47
  # Try to use max height
48
  new_height = max_dimension
49
  new_width = new_height * aspect_ratio
50
+
51
  # If width would be too small, use min width
52
  if new_width < min_dimension:
53
  new_width = min_dimension
 
55
  # If height exceeds max, clamp it
56
  if new_height > max_dimension:
57
  new_height = max_dimension
58
+
59
  return round_to(new_width, compatible_round), round_to(new_height, compatible_round)
60
 
61
 
 
73
  ):
74
  # Load and preprocess video
75
  progress(0.2, desc="Loading video...")
76
+
77
  # Get video dimensions
78
  temp_video = load_video(video_path)
79
  print(len(temp_video))
80
  if temp_video and len(temp_video) > 0:
81
  original_width, original_height = temp_video[0].size
82
+
83
  # Calculate dimensions
84
  if auto_resize:
85
  width, height = calculate_resolution(original_width, original_height)
 
87
  width, height = manual_width, manual_height
88
  else:
89
  raise gr.Error("Could not load video or video is empty")
90
+
91
  # Convert video function
92
  def convert_video(video: List[Image.Image]) -> List[Image.Image]:
93
  # Ensure we don't exceed the video length
 
96
  # Resize frames
97
  video_frames = [frame.resize((width, height)) for frame in video_frames]
98
  return video_frames
99
+
100
  # Load video from file path
101
  video = load_video(video_path, convert_method=convert_video)
102
+
103
  # Ensure we have the right number of frames
104
  if len(video) < num_frames:
105
  num_frames = len(video)
106
+
107
  # Generate edited video
108
  progress(0.5, desc="Generating edited video...")
109
  output = pipe(
 
115
  num_frames=num_frames,
116
  guidance_scale=guidance_scale,
117
  ).frames[0]
118
+
119
  # Export to temporary file
120
  progress(0.9, desc="Exporting video...")
121
  with tempfile.NamedTemporaryFile(delete=False, suffix=".mp4") as tmp_file:
122
  output_path = tmp_file.name
123
+
124
  export_to_video(output, output_path, fps=24)
125
+
126
  progress(1.0, desc="Complete!")
127
  return output_path
128
 
 
141
  &nbsp;|&nbsp; 📑 <a href="#">arXiv (Coming soon)</a>
142
  &nbsp;|&nbsp; 💬 <a href="https://discord.gg/decart">Discord</a>
143
  </p>""")
144
+
145
  with gr.Row():
146
  with gr.Column(scale=1):
147
  # Input controls
148
  video_input = gr.Video(label="Input Video")
149
+
150
  prompt = gr.Textbox(
151
  label="Edit Prompt",
152
  placeholder="Describe what you want to change in the video...",
153
  lines=3
154
  )
155
+
156
  with gr.Accordion("Advanced Settings", open=False):
157
  negative_prompt = gr.Textbox(
158
  label="Negative Prompt (optional)",
 
164
  value=True,
165
  info="Automatically calculate dimensions based on input video"
166
  )
167
+
168
  num_frames = gr.Slider(
169
  label="Number of Frames",
170
  minimum=1,
 
173
  step=1,
174
  info="More frames = longer processing time"
175
  )
176
+
177
  with gr.Row():
178
  manual_height = gr.Slider(
179
  label="Height (when auto-resize is off)",
 
189
  value=832,
190
  step=32
191
  )
192
+
193
  guidance_scale = gr.Slider(
194
  label="Guidance Scale",
195
  minimum=1.0,
 
198
  step=0.5,
199
  info="Higher values follow the prompt more strictly"
200
  )
201
+
202
  generate_btn = gr.Button("Edit Video", variant="primary")
203
+
204
  with gr.Column(scale=1):
205
  video_output = gr.Video(label="Edited Video")
206
 
207
  gr.Examples(
208
  examples=[
209
+ ["examples/neon.mp4", "Add a colorful scarlet macaw parrot perched on the man's left shoulder, bright red and blue wing feathers with yellow accents, curved black beak, intelligent dark eyes, talons gripping fabric naturally, long tail feathers extending downward, glossy plumage catching light, slight wing adjustment for balance, natural weight distribution, soft shadow beneath bird."],
210
+ ["examples/painter.mp4", "Change the hair color to platinum blonde with natural highlights, subtle root shadowing, silky texture, gentle waves, soft shine, dimensional tones, strand definition, natural movement, professional color treatment, salon-quality finish, light-catching shimmer, varied blonde shades from honey to ash, realistic color gradation, healthy glossy appearance, volumetric lighting interaction."],
 
211
  ],
212
  inputs=[video_input, prompt],
213
  outputs=video_output,
214
  fn=process_video,
215
  cache_examples="lazy",
216
  )
217
+
218
  # Event handlers
219
  generate_btn.click(
220
  fn=process_video,
 
232
  )
233
 
234
  if __name__ == "__main__":
235
+ demo.launch(share=True)
examples/neon.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e62dc89173956d4d22defac1d24f0835c8d8d0490f7969dd13b38429d69165ca
3
+ size 3182890
examples/painter.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:37b385068db4c25d8f29104580b3267a4fafc2afbd4235f57a206a587a16e56f
3
+ size 2941421