MogensR commited on
Commit
3ec06be
Β·
verified Β·
1 Parent(s): 5ddbef0

Update streamlit_app.py

Browse files
Files changed (1) hide show
  1. streamlit_app.py +67 -40
streamlit_app.py CHANGED
@@ -1,4 +1,6 @@
1
  # streamlit_ui.py
 
 
2
  import streamlit as st
3
  import os
4
  import sys
@@ -10,15 +12,24 @@
10
  from PIL import Image
11
  import logging
12
  import io
 
 
 
13
 
14
- # Add project root to path
15
  sys.path.append(str(Path(__file__).parent.absolute()))
16
 
17
- # Configure logging
18
- logging.basicConfig(level=logging.INFO)
19
  logger = logging.getLogger(__name__)
20
 
21
- # Set page config
 
 
 
 
 
 
22
  st.set_page_config(
23
  page_title="🎬 Advanced Video Background Replacer",
24
  page_icon="πŸŽ₯",
@@ -26,7 +37,7 @@
26
  initial_sidebar_state="expanded"
27
  )
28
 
29
- # Custom CSS for better UI
30
  st.markdown("""
31
  <style>
32
  .main .block-container {
@@ -73,6 +84,7 @@
73
  </style>
74
  """, unsafe_allow_html=True)
75
 
 
76
  def initialize_session_state():
77
  """Initialize all session state variables"""
78
  if 'uploaded_video' not in st.session_state:
@@ -90,16 +102,18 @@ def initialize_session_state():
90
  if 'progress_text' not in st.session_state:
91
  st.session_state.progress_text = "Ready"
92
 
 
93
  def handle_video_upload():
94
  """Handle video file upload"""
95
  uploaded = st.file_uploader(
96
- "πŸ“Ή Upload Video",
97
  type=["mp4", "mov", "avi"],
98
  key="video_uploader"
99
  )
100
  if uploaded is not None:
101
  st.session_state.uploaded_video = uploaded
102
 
 
103
  def show_video_preview():
104
  """Show video preview in the UI"""
105
  st.markdown("### Video Preview")
@@ -108,6 +122,7 @@ def show_video_preview():
108
  st.video(video_bytes)
109
  st.session_state.uploaded_video.seek(0)
110
 
 
111
  def handle_background_selection():
112
  """Handle background selection UI"""
113
  st.markdown("### Background Options")
@@ -127,14 +142,14 @@ def handle_background_selection():
127
  if bg_image is not None:
128
  st.session_state.bg_image = Image.open(bg_image)
129
  st.image(
130
- st.session_state.bg_image,
131
- caption="Selected Background",
132
  use_container_width=True
133
  )
134
 
135
  elif bg_type == "Color":
136
  st.session_state.bg_color = st.color_picker(
137
- "🎨 Choose Background Color",
138
  st.session_state.bg_color
139
  )
140
  color_rgb = tuple(int(st.session_state.bg_color.lstrip('#')[i:i+2], 16) for i in (0, 2, 4))
@@ -144,6 +159,8 @@ def handle_background_selection():
144
 
145
  return bg_type.lower()
146
 
 
 
147
  def process_video(input_file, background, bg_type="image"):
148
  """
149
  Process video with the selected background using SAM2 and MatAnyone pipeline.
@@ -156,8 +173,12 @@ def process_video(input_file, background, bg_type="image"):
156
 
157
  # Save the uploaded video to a temporary file
158
  input_path = str(temp_dir / "input.mp4")
 
159
  with open(input_path, "wb") as f:
160
- f.write(input_file.getvalue())
 
 
 
161
 
162
  # Prepare background
163
  bg_path = None
@@ -173,43 +194,53 @@ def process_video(input_file, background, bg_type="image"):
173
  bg_path = str(temp_dir / "background.jpg")
174
  cv2.imwrite(bg_path, np.ones((100, 100, 3), dtype=np.uint8) * color_rgb[::-1])
175
 
176
- # Set up progress callback
177
- progress_bar = st.progress(0)
178
- status_text = st.empty()
179
 
180
  def progress_callback(progress, message):
181
  progress = max(0, min(1, float(progress)))
182
- progress_bar.progress(progress)
183
- status_text.text(f"Status: {message}")
184
- st.session_state.progress = int(progress * 100)
185
- st.session_state.progress_text = message
 
 
186
 
187
  # Process the video
188
  output_path = str(temp_dir / "output.mp4")
189
-
190
- # Mock click points (center of the frame)
191
  click_points = [[0.5, 0.5]]
192
-
193
- # Import the pipeline processor
194
  from pipeline.integrated_pipeline import TwoStageProcessor
195
 
196
- # Initialize the processor
197
- processor = TwoStageProcessor(temp_dir=str(temp_dir))
 
 
 
198
 
199
- # Process the video
200
- success = processor.process_video(
201
- input_video=input_path,
202
- background_video=bg_path if bg_type == "image" else "",
203
- click_points=click_points,
204
- output_path=output_path,
205
- use_matanyone=True,
206
- progress_callback=progress_callback
207
- )
 
 
 
 
 
 
 
 
 
 
208
 
209
  if not success:
210
  raise RuntimeError("Video processing failed")
211
 
212
- # Return the path to the processed video
213
  return output_path
214
 
215
  except Exception as e:
@@ -217,6 +248,7 @@ def progress_callback(progress, message):
217
  st.error(f"An error occurred during processing: {str(e)}")
218
  return None
219
 
 
220
  def main():
221
  st.title("🎬 Advanced Video Background Replacer")
222
  st.markdown("---")
@@ -235,7 +267,6 @@ def main():
235
  with col2:
236
  st.header("2. Background Settings")
237
  bg_type = handle_background_selection()
238
-
239
  st.header("3. Process & Download")
240
  # ------- FORM WRAP START --------
241
  with st.form("process_form"):
@@ -243,7 +274,6 @@ def main():
243
  "πŸš€ Process Video",
244
  disabled=not st.session_state.uploaded_video or st.session_state.processing
245
  )
246
-
247
  process_status = st.empty()
248
  if submitted and not st.session_state.processing:
249
  st.session_state.processing = True
@@ -255,27 +285,23 @@ def main():
255
  background = st.session_state.bg_image
256
  elif bg_type == "color" and 'bg_color' in st.session_state:
257
  background = st.session_state.bg_color
258
-
259
  # Process the video
260
  output_path = process_video(
261
  st.session_state.uploaded_video,
262
  background,
263
  bg_type=bg_type
264
  )
265
-
266
  if output_path and os.path.exists(output_path):
267
  st.session_state.processed_video_path = output_path
268
  process_status.success("βœ… Video processing complete!")
269
  else:
270
  process_status.error("❌ Failed to process video. Please check the logs for details.")
271
-
272
  except Exception as e:
273
  process_status.error(f"❌ An error occurred: {str(e)}")
274
  logger.exception("Video processing failed")
275
  finally:
276
  st.session_state.processing = False
277
  # ------- FORM WRAP END --------
278
-
279
  # Show processed video if available (outside form, stable)
280
  if 'processed_video_path' in st.session_state and st.session_state.processed_video_path:
281
  st.markdown("### Processed Video")
@@ -294,5 +320,6 @@ def main():
294
  st.error(f"Error displaying video: {str(e)}")
295
  logger.error(f"Error displaying video: {str(e)}", exc_info=True)
296
 
 
297
  if __name__ == "__main__":
298
- main()
 
1
  # streamlit_ui.py
2
+
3
+ # --- Imports ---
4
  import streamlit as st
5
  import os
6
  import sys
 
12
  from PIL import Image
13
  import logging
14
  import io
15
+ import torch
16
+ import traceback
17
+ from concurrent.futures import ThreadPoolExecutor
18
 
19
+ # --- Project Setup ---
20
  sys.path.append(str(Path(__file__).parent.absolute()))
21
 
22
+ # --- Logging Configuration ---
23
+ logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
24
  logger = logging.getLogger(__name__)
25
 
26
+ # --- Global Exception Hook ---
27
+ def custom_excepthook(type, value, tb):
28
+ logger.error(f"Unhandled: {type.__name__}: {value}\n{''.join(traceback.format_tb(tb))}", exc_info=True)
29
+ sys.excepthook = custom_excepthook
30
+ threading.excepthook = custom_excepthook # Python 3.10+
31
+
32
+ # --- Streamlit Page Config ---
33
  st.set_page_config(
34
  page_title="🎬 Advanced Video Background Replacer",
35
  page_icon="πŸŽ₯",
 
37
  initial_sidebar_state="expanded"
38
  )
39
 
40
+ # --- Custom CSS ---
41
  st.markdown("""
42
  <style>
43
  .main .block-container {
 
84
  </style>
85
  """, unsafe_allow_html=True)
86
 
87
+ # --- Session State Initialization ---
88
  def initialize_session_state():
89
  """Initialize all session state variables"""
90
  if 'uploaded_video' not in st.session_state:
 
102
  if 'progress_text' not in st.session_state:
103
  st.session_state.progress_text = "Ready"
104
 
105
+ # --- Video Upload Handling ---
106
  def handle_video_upload():
107
  """Handle video file upload"""
108
  uploaded = st.file_uploader(
109
+ "πŸ“Ή Upload Video",
110
  type=["mp4", "mov", "avi"],
111
  key="video_uploader"
112
  )
113
  if uploaded is not None:
114
  st.session_state.uploaded_video = uploaded
115
 
116
+ # --- Video Preview ---
117
  def show_video_preview():
118
  """Show video preview in the UI"""
119
  st.markdown("### Video Preview")
 
122
  st.video(video_bytes)
123
  st.session_state.uploaded_video.seek(0)
124
 
125
+ # --- Background Selection ---
126
  def handle_background_selection():
127
  """Handle background selection UI"""
128
  st.markdown("### Background Options")
 
142
  if bg_image is not None:
143
  st.session_state.bg_image = Image.open(bg_image)
144
  st.image(
145
+ st.session_state.bg_image,
146
+ caption="Selected Background",
147
  use_container_width=True
148
  )
149
 
150
  elif bg_type == "Color":
151
  st.session_state.bg_color = st.color_picker(
152
+ "🎨 Choose Background Color",
153
  st.session_state.bg_color
154
  )
155
  color_rgb = tuple(int(st.session_state.bg_color.lstrip('#')[i:i+2], 16) for i in (0, 2, 4))
 
159
 
160
  return bg_type.lower()
161
 
162
+ # --- Video Processing ---
163
+ @st.fragment(run_if=lambda: st.session_state.processing)
164
  def process_video(input_file, background, bg_type="image"):
165
  """
166
  Process video with the selected background using SAM2 and MatAnyone pipeline.
 
173
 
174
  # Save the uploaded video to a temporary file
175
  input_path = str(temp_dir / "input.mp4")
176
+ logger.info(f"Writing video to {input_path}")
177
  with open(input_path, "wb") as f:
178
+ written = f.write(input_file.getvalue())
179
+ logger.info(f"Wrote {written/1e6:.2f}MB")
180
+ if not os.path.exists(input_path):
181
+ raise FileNotFoundError(f"Input video not saved: {input_path}")
182
 
183
  # Prepare background
184
  bg_path = None
 
194
  bg_path = str(temp_dir / "background.jpg")
195
  cv2.imwrite(bg_path, np.ones((100, 100, 3), dtype=np.uint8) * color_rgb[::-1])
196
 
197
+ # Set up progress placeholders
198
+ progress_placeholder = st.empty()
199
+ status_placeholder = st.empty()
200
 
201
  def progress_callback(progress, message):
202
  progress = max(0, min(1, float(progress)))
203
+ progress_placeholder.progress(progress)
204
+ status_placeholder.text(f"Status: {message}")
205
+
206
+ # Log GPU state
207
+ logger.info(f"CUDA Available: {torch.cuda.is_available()}, Device: {torch.cuda.get_device_name(0)}")
208
+ logger.info(f"GPU Mem Before: {torch.cuda.memory_allocated()/1e9:.2f}GB")
209
 
210
  # Process the video
211
  output_path = str(temp_dir / "output.mp4")
 
 
212
  click_points = [[0.5, 0.5]]
 
 
213
  from pipeline.integrated_pipeline import TwoStageProcessor
214
 
215
+ # Cache processor
216
+ @st.cache_resource
217
+ def load_processor(temp_dir):
218
+ return TwoStageProcessor(temp_dir=temp_dir)
219
+ processor = load_processor(str(temp_dir))
220
 
221
+ # Run in thread to catch exceptions
222
+ with ThreadPoolExecutor(max_workers=1) as executor:
223
+ future = executor.submit(
224
+ processor.process_video,
225
+ input_video=input_path,
226
+ background_video=bg_path if bg_type == "image" else "",
227
+ click_points=click_points,
228
+ output_path=output_path,
229
+ use_matanyone=True,
230
+ progress_callback=progress_callback
231
+ )
232
+ try:
233
+ success = future.result(timeout=300) # 5min timeout
234
+ except Exception as e:
235
+ logger.error(f"Pipeline thread fail: {traceback.format_exc()}", exc_info=True)
236
+ raise
237
+
238
+ logger.info(f"GPU Mem After: {torch.cuda.memory_allocated()/1e9:.2f}GB")
239
+ torch.cuda.empty_cache() # Free memory
240
 
241
  if not success:
242
  raise RuntimeError("Video processing failed")
243
 
 
244
  return output_path
245
 
246
  except Exception as e:
 
248
  st.error(f"An error occurred during processing: {str(e)}")
249
  return None
250
 
251
+ # --- Main Application ---
252
  def main():
253
  st.title("🎬 Advanced Video Background Replacer")
254
  st.markdown("---")
 
267
  with col2:
268
  st.header("2. Background Settings")
269
  bg_type = handle_background_selection()
 
270
  st.header("3. Process & Download")
271
  # ------- FORM WRAP START --------
272
  with st.form("process_form"):
 
274
  "πŸš€ Process Video",
275
  disabled=not st.session_state.uploaded_video or st.session_state.processing
276
  )
 
277
  process_status = st.empty()
278
  if submitted and not st.session_state.processing:
279
  st.session_state.processing = True
 
285
  background = st.session_state.bg_image
286
  elif bg_type == "color" and 'bg_color' in st.session_state:
287
  background = st.session_state.bg_color
 
288
  # Process the video
289
  output_path = process_video(
290
  st.session_state.uploaded_video,
291
  background,
292
  bg_type=bg_type
293
  )
 
294
  if output_path and os.path.exists(output_path):
295
  st.session_state.processed_video_path = output_path
296
  process_status.success("βœ… Video processing complete!")
297
  else:
298
  process_status.error("❌ Failed to process video. Please check the logs for details.")
 
299
  except Exception as e:
300
  process_status.error(f"❌ An error occurred: {str(e)}")
301
  logger.exception("Video processing failed")
302
  finally:
303
  st.session_state.processing = False
304
  # ------- FORM WRAP END --------
 
305
  # Show processed video if available (outside form, stable)
306
  if 'processed_video_path' in st.session_state and st.session_state.processed_video_path:
307
  st.markdown("### Processed Video")
 
320
  st.error(f"Error displaying video: {str(e)}")
321
  logger.error(f"Error displaying video: {str(e)}", exc_info=True)
322
 
323
+ # --- Entry Point ---
324
  if __name__ == "__main__":
325
+ main()