KingNish commited on
Commit
0791cf5
1 Parent(s): 9eb650c

refactored and added schedule

Browse files
Files changed (1) hide show
  1. app.py +100 -51
app.py CHANGED
@@ -11,6 +11,10 @@ import numpy as np
11
  import os
12
  import tempfile
13
  import uuid
 
 
 
 
14
 
15
  torch.set_float32_matmul_precision("medium")
16
 
@@ -29,64 +33,116 @@ transform_image = transforms.Compose(
29
  )
30
 
31
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  @spaces.GPU
33
- def fn(vid, bg_type="Color", bg_image=None, bg_video=None, color="#00FF00", fps=0, video_handling="slow_down"):
 
 
34
  try:
35
  # Load the video using moviepy
36
- video = mp.VideoFileClip(vid)
37
 
38
  # Load original fps if fps value is equal to 0
39
- if fps == 0:
40
- fps = video.fps
41
 
42
  # Extract audio from the video
43
  audio = video.audio
44
 
45
  # Extract frames at the specified FPS
46
- frames = video.iter_frames(fps=fps)
47
 
48
  # Process each frame for background removal
49
  processed_frames = []
50
- yield gr.update(visible=True), gr.update(visible=False)
51
 
52
  if bg_type == "Video":
53
- background_video = mp.VideoFileClip(bg_video)
54
  if background_video.duration < video.duration:
55
- if video_handling == "slow_down":
56
  background_video = background_video.fx(mp.vfx.speedx, factor=video.duration / background_video.duration)
57
- else: # video_handling == "loop"
58
  background_video = mp.concatenate_videoclips([background_video] * int(video.duration / background_video.duration + 1))
59
- background_frames = list(background_video.iter_frames(fps=fps)) # Convert to list
60
  else:
61
  background_frames = None
62
 
63
  bg_frame_index = 0 # Initialize background frame index
64
-
65
- for i, frame in enumerate(frames):
66
- pil_image = Image.fromarray(frame)
67
- if bg_type == "Color":
68
- processed_image = process(pil_image, color)
69
- elif bg_type == "Image":
70
- processed_image = process(pil_image, bg_image)
71
- elif bg_type == "Video":
72
- if video_handling == "slow_down":
73
- background_frame = background_frames[bg_frame_index % len(background_frames)]
74
- bg_frame_index += 1
75
- background_image = Image.fromarray(background_frame)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
  processed_image = process(pil_image, background_image)
77
- else: # video_handling == "loop"
78
- background_frame = background_frames[bg_frame_index % len(background_frames)]
79
- bg_frame_index += 1
80
- background_image = Image.fromarray(background_frame)
81
- processed_image = process(pil_image, background_image)
82
- else:
83
- processed_image = pil_image # Default to original image if no background is selected
84
 
85
- processed_frames.append(np.array(processed_image))
86
- yield processed_image, None
 
87
 
88
  # Create a new video from the processed frames
89
- processed_video = mp.ImageSequenceClip(processed_frames, fps=fps)
90
 
91
  # Add the original audio back to the processed video
92
  processed_video = processed_video.set_audio(audio)
@@ -98,15 +154,15 @@ def fn(vid, bg_type="Color", bg_image=None, bg_video=None, color="#00FF00", fps=
98
  temp_filepath = os.path.join(temp_dir, unique_filename)
99
  processed_video.write_videofile(temp_filepath, codec="libx264")
100
 
101
- yield gr.update(visible=False), gr.update(visible=True)
102
  # Return the path to the temporary file
103
- yield processed_image, temp_filepath
104
 
105
  except Exception as e:
106
- print(f"Error: {e}")
107
- yield gr.update(visible=False), gr.update(visible=True)
108
- yield None, f"Error processing video: {e}"
109
-
110
 
111
 
112
  def process(image, bg):
@@ -119,16 +175,8 @@ def process(image, bg):
119
  pred_pil = transforms.ToPILImage()(pred)
120
  mask = pred_pil.resize(image_size)
121
 
122
- if isinstance(bg, str) and bg.startswith("#"):
123
- color_rgb = tuple(int(bg[i:i+2], 16) for i in (1, 3, 5))
124
- background = Image.new("RGBA", image_size, color_rgb + (255,))
125
- elif isinstance(bg, Image.Image):
126
- background = bg.convert("RGBA").resize(image_size)
127
- else:
128
- background = Image.open(bg).convert("RGBA").resize(image_size)
129
-
130
  # Composite the image onto the background using the mask
131
- image = Image.composite(image, background, mask)
132
 
133
  return image
134
 
@@ -140,6 +188,7 @@ with gr.Blocks(theme=gr.themes.Ocean()) as demo:
140
  stream_image = gr.Image(label="Streaming Output", visible=False)
141
  out_video = gr.Video(label="Final Output Video")
142
  submit_button = gr.Button("Change Background", interactive=True)
 
143
  with gr.Row():
144
  fps_slider = gr.Slider(
145
  minimum=0,
@@ -177,17 +226,17 @@ with gr.Blocks(theme=gr.themes.Ocean()) as demo:
177
  ["rickroll-2sec.mp4", "Color", None, None],
178
  ],
179
  inputs=[in_video, bg_type, bg_image, bg_video],
180
- outputs=[stream_image, out_video],
181
- fn=fn,
182
  cache_examples=True,
183
  cache_mode="eager",
184
  )
185
 
186
 
187
  submit_button.click(
188
- fn,
189
  inputs=[in_video, bg_type, bg_image, bg_video, color_picker, fps_slider, video_handling_radio],
190
- outputs=[stream_image, out_video],
191
  )
192
 
193
  if __name__ == "__main__":
 
11
  import os
12
  import tempfile
13
  import uuid
14
+ import schedule
15
+ import time
16
+ import threading
17
+ import shutil
18
 
19
  torch.set_float32_matmul_precision("medium")
20
 
 
33
  )
34
 
35
 
36
+ def load_background_image(bg, image_size):
37
+ """Loads and resizes the background image based on the provided input."""
38
+ try:
39
+ if isinstance(bg, str) and bg.startswith("#"):
40
+ color_rgb = tuple(int(bg[i:i+2], 16) for i in (1, 3, 5))
41
+ return Image.new("RGBA", image_size, color_rgb + (255,))
42
+ elif isinstance(bg, Image.Image):
43
+ return bg.convert("RGBA").resize(image_size)
44
+ else:
45
+ return Image.open(bg).convert("RGBA").resize(image_size)
46
+ except Exception as e:
47
+ print(f"Error opening background image: {e}")
48
+ return None
49
+
50
+ def clear_temp_directory():
51
+ temp_dir = "temp"
52
+ if os.path.exists(temp_dir):
53
+ for filename in os.listdir(temp_dir):
54
+ file_path = os.path.join(temp_dir, filename)
55
+ try:
56
+ if os.path.isfile(file_path) or os.path.islink(file_path):
57
+ os.unlink(file_path)
58
+ elif os.path.isdir(file_path):
59
+ shutil.rmtree(file_path)
60
+ except Exception as e:
61
+ print(f"Failed to delete {file_path}. Reason: {e}")
62
+
63
+ def run_scheduler():
64
+ schedule.every(10).minutes.do(clear_temp_directory)
65
+ while True:
66
+ schedule.run_pending()
67
+ time.sleep(1)
68
+
69
+ # Start the scheduler in a separate thread
70
+ scheduler_thread = threading.Thread(target=run_scheduler)
71
+ scheduler_thread.daemon = True # Allow the main thread to exit even if the scheduler is running
72
+ scheduler_thread.start()
73
+
74
  @spaces.GPU
75
+ def process_video(input_video_path, bg_type="Color", bg_image_path=None, bg_video_path=None,
76
+ bg_color="#00FF00", output_fps=0, video_handling_mode="slow_down"):
77
+ """Processes the input video and replaces the background."""
78
  try:
79
  # Load the video using moviepy
80
+ video = mp.VideoFileClip(input_video_path)
81
 
82
  # Load original fps if fps value is equal to 0
83
+ if output_fps == 0:
84
+ output_fps = video.fps
85
 
86
  # Extract audio from the video
87
  audio = video.audio
88
 
89
  # Extract frames at the specified FPS
90
+ frames = video.iter_frames(fps=output_fps)
91
 
92
  # Process each frame for background removal
93
  processed_frames = []
94
+ yield gr.update(visible=True), gr.update(visible=False), gr.update(value=0)
95
 
96
  if bg_type == "Video":
97
+ background_video = mp.VideoFileClip(bg_video_path)
98
  if background_video.duration < video.duration:
99
+ if video_handling_mode == "slow_down":
100
  background_video = background_video.fx(mp.vfx.speedx, factor=video.duration / background_video.duration)
101
+ else: # video_handling_mode == "loop"
102
  background_video = mp.concatenate_videoclips([background_video] * int(video.duration / background_video.duration + 1))
103
+ background_frames = list(background_video.iter_frames(fps=output_fps)) # Convert to list
104
  else:
105
  background_frames = None
106
 
107
  bg_frame_index = 0 # Initialize background frame index
108
+ total_frames = len(list(frames))
109
+ frames = video.iter_frames(fps=output_fps)
110
+ batch_size = 4
111
+
112
+ for i in range(0, total_frames, batch_size):
113
+ batch_frames = list(frames)[i:i+batch_size]
114
+ processed_batch = []
115
+ for frame in batch_frames:
116
+ pil_image = Image.fromarray(frame)
117
+ if bg_type == "Color":
118
+ background_image = load_background_image(bg_color, pil_image.size)
119
+ elif bg_type == "Image":
120
+ background_image = load_background_image(bg_image_path, pil_image.size)
121
+ elif bg_type == "Video":
122
+ if video_handling_mode == "slow_down":
123
+ background_frame = background_frames[bg_frame_index % len(background_frames)]
124
+ bg_frame_index += 1
125
+ background_image = Image.fromarray(background_frame)
126
+ else: # video_handling_mode == "loop"
127
+ background_frame = background_frames[bg_frame_index % len(background_frames)]
128
+ bg_frame_index += 1
129
+ background_image = Image.fromarray(background_frame)
130
+ else:
131
+ background_image = None # Default to original image if no background is selected
132
+
133
+ if background_image is not None:
134
  processed_image = process(pil_image, background_image)
135
+ else:
136
+ processed_image = pil_image
137
+
138
+ processed_batch.append(np.array(processed_image))
 
 
 
139
 
140
+ processed_frames.extend(processed_batch)
141
+ progress = (i + len(batch_frames)) / total_frames
142
+ yield processed_batch[-1], None, gr.update(value=progress) # Update progress bar
143
 
144
  # Create a new video from the processed frames
145
+ processed_video = mp.ImageSequenceClip(processed_frames, fps=output_fps)
146
 
147
  # Add the original audio back to the processed video
148
  processed_video = processed_video.set_audio(audio)
 
154
  temp_filepath = os.path.join(temp_dir, unique_filename)
155
  processed_video.write_videofile(temp_filepath, codec="libx264")
156
 
157
+ yield gr.update(visible=False), gr.update(visible=True), gr.update(value=1)
158
  # Return the path to the temporary file
159
+ yield processed_batch[-1], temp_filepath
160
 
161
  except Exception as e:
162
+ error_message = f"Error processing video: {e}"
163
+ print(error_message)
164
+ yield gr.update(visible=False), gr.update(visible=True), gr.update(value=0)
165
+ yield None, error_message
166
 
167
 
168
  def process(image, bg):
 
175
  pred_pil = transforms.ToPILImage()(pred)
176
  mask = pred_pil.resize(image_size)
177
 
 
 
 
 
 
 
 
 
178
  # Composite the image onto the background using the mask
179
+ image = Image.composite(image, bg, mask)
180
 
181
  return image
182
 
 
188
  stream_image = gr.Image(label="Streaming Output", visible=False)
189
  out_video = gr.Video(label="Final Output Video")
190
  submit_button = gr.Button("Change Background", interactive=True)
191
+ progress_bar = gr.ProgressBar(label="Processing Progress")
192
  with gr.Row():
193
  fps_slider = gr.Slider(
194
  minimum=0,
 
226
  ["rickroll-2sec.mp4", "Color", None, None],
227
  ],
228
  inputs=[in_video, bg_type, bg_image, bg_video],
229
+ outputs=[stream_image, out_video, progress_bar],
230
+ fn=process_video,
231
  cache_examples=True,
232
  cache_mode="eager",
233
  )
234
 
235
 
236
  submit_button.click(
237
+ process_video,
238
  inputs=[in_video, bg_type, bg_image, bg_video, color_picker, fps_slider, video_handling_radio],
239
+ outputs=[stream_image, out_video, progress_bar],
240
  )
241
 
242
  if __name__ == "__main__":