MogensR commited on
Commit
bf99458
·
verified ·
1 Parent(s): 8299fd5

Update ui.py

Browse files
Files changed (1) hide show
  1. ui.py +47 -66
ui.py CHANGED
@@ -1,9 +1,8 @@
1
  #!/usr/bin/env python3
2
  """
3
  Modern UI for Video Background Replacer (PRO)
4
- - Clean, responsive Streamlit layout
5
- - Shows live stage progress and all errors during processing
6
- - Progress bars and visual feedback to keep session alive
7
  """
8
  import streamlit as st
9
  import os
@@ -12,9 +11,12 @@
12
  import numpy as np
13
  import logging
14
  import time
 
 
 
15
 
16
  logger = logging.getLogger("Advanced Video Background Replacer")
17
- UI_BUILD = "ui-2025-10-04-16-00Z"
18
 
19
  def tail_file(path: str, lines: int = 400) -> str:
20
  if not os.path.exists(path):
@@ -107,7 +109,6 @@ def _render_background_settings():
107
 
108
  def render_ui(process_video_func):
109
  try:
110
- # --- Sidebar: System Status & Logs ---
111
  with st.sidebar:
112
  st.subheader("System Status")
113
  st.caption(f"UI build: {UI_BUILD}")
@@ -139,10 +140,8 @@ def render_ui(process_video_func):
139
  log_text = tail_file("/tmp/app.log", st.session_state.get('log_tail_lines', 400))
140
  st.code(log_text, language="text")
141
 
142
- # --- Main UI: Two-Column Layout ---
143
  col1, col2 = st.columns([1, 1], gap="large")
144
 
145
- # --- Column 1: Video Upload ---
146
  with col1:
147
  st.header("1. Upload Video")
148
  uploaded_video = st.file_uploader(
@@ -165,12 +164,10 @@ def render_ui(process_video_func):
165
  else:
166
  video_preview_placeholder.empty()
167
 
168
- # --- Column 2: Background & Processing ---
169
  with col2:
170
  background, bg_type = _render_background_settings()
171
  st.header("3. Process Video")
172
 
173
- # Progress tracking UI elements
174
  progress_container = st.container()
175
  with progress_container:
176
  progress_bar = st.progress(0)
@@ -183,59 +180,10 @@ def render_ui(process_video_func):
183
  and (background is not None)
184
  )
185
 
186
- # Enhanced progress callback with visual updates
187
- progress_state = {"step": 0, "total_steps": 12}
188
-
189
- def progress_callback(msg):
190
- status_text.info(f"**Status:** {msg}")
191
- logger.info(f"[STAGE] {msg}")
192
-
193
- # Update progress based on message content
194
- if "Stage 1 initiated" in msg:
195
- progress_state["step"] = 1
196
- stage_status.markdown("**Current Stage:** Stage 1 - Transparent Video Creation")
197
- elif "GPU engaged" in msg or "SAM2" in msg:
198
- progress_state["step"] = 2
199
- elif "SAM2 processing frame" in msg:
200
- progress_state["step"] = 3
201
- elif "SAM2 complete" in msg or "clearing GPU" in msg:
202
- progress_state["step"] = 4
203
- elif "MatAnyone starting" in msg:
204
- progress_state["step"] = 5
205
- stage_status.markdown("**Current Stage:** Stage 1 - MatAnyone Processing")
206
- elif "MatAnyone processing" in msg:
207
- progress_state["step"] = 6
208
- elif "MatAnyone complete" in msg:
209
- progress_state["step"] = 7
210
- elif "Smoothing" in msg:
211
- progress_state["step"] = 8
212
- elif "transparent video" in msg and "Creating" in msg:
213
- progress_state["step"] = 9
214
- elif "Stage 1 complete" in msg:
215
- progress_state["step"] = 10
216
- elif "Stage 2 begun" in msg:
217
- progress_state["step"] = 10
218
- stage_status.markdown("**Current Stage:** Stage 2 - Background Compositing")
219
- elif "Compositing frames" in msg:
220
- progress_state["step"] = 11
221
- elif "Stage 2 complete" in msg:
222
- progress_state["step"] = 12
223
- stage_status.markdown("**Current Stage:** Complete!")
224
-
225
- # Update progress bar
226
- progress_pct = min(100, int((progress_state["step"] / progress_state["total_steps"]) * 100))
227
- progress_bar.progress(progress_pct)
228
-
229
  if st.button("Process Video", disabled=not can_process, use_container_width=True):
230
  try:
231
  logger.info("Process Video button clicked")
232
 
233
- # Reset progress
234
- progress_state["step"] = 0
235
- progress_bar.progress(0)
236
- status_text.empty()
237
- stage_status.empty()
238
-
239
  import io
240
  class _MemFile:
241
  def __init__(self, name, data):
@@ -250,24 +198,58 @@ def seek(self, pos):
250
  st.session_state.processing = True
251
  mem_video = _MemFile("uploaded.mp4", st.session_state.video_bytes_cache)
252
 
253
- with st.spinner("Processing video..."):
254
- success = process_video_func(mem_video, background, bg_type.lower(), progress_callback)
 
 
 
 
 
255
 
256
- st.session_state.processing = False
257
- if success:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
258
  progress_bar.progress(100)
259
  status_text.success("**Status:** Processing complete!")
260
  st.success("Video processing complete!")
261
  else:
262
- status_text.error("**Status:** Processing failed. Check logs for details.")
263
- st.error("Video processing failed. Check logs for details.")
 
264
  except Exception as e:
265
  st.session_state.processing = False
266
  logger.error(f"[UI] Process video error: {e}", exc_info=True)
267
  status_text.error(f"**Status:** Error - {str(e)}")
268
  st.error(f"Processing error: {str(e)}. Check logs for details.")
269
 
270
- # --- Results Display ---
271
  if st.session_state.get('processed_video_bytes') is not None:
272
  st.markdown("---")
273
  st.markdown("### Processed Video")
@@ -284,7 +266,6 @@ def seek(self, pos):
284
  logger.error(f"[UI] Display error: {e}", exc_info=True)
285
  st.error(f"Display error: {e}")
286
 
287
- # --- Error Display ---
288
  if st.session_state.get('last_error'):
289
  with st.expander("Last Error", expanded=True):
290
  st.error(st.session_state.last_error)
 
1
  #!/usr/bin/env python3
2
  """
3
  Modern UI for Video Background Replacer (PRO)
4
+ - File-based progress polling to keep session alive
5
+ - Real-time progress updates during long-running operations
 
6
  """
7
  import streamlit as st
8
  import os
 
11
  import numpy as np
12
  import logging
13
  import time
14
+ import threading
15
+
16
+ from utils.progress_tracker import get_progress
17
 
18
  logger = logging.getLogger("Advanced Video Background Replacer")
19
+ UI_BUILD = "ui-2025-10-04-17-00Z"
20
 
21
  def tail_file(path: str, lines: int = 400) -> str:
22
  if not os.path.exists(path):
 
109
 
110
  def render_ui(process_video_func):
111
  try:
 
112
  with st.sidebar:
113
  st.subheader("System Status")
114
  st.caption(f"UI build: {UI_BUILD}")
 
140
  log_text = tail_file("/tmp/app.log", st.session_state.get('log_tail_lines', 400))
141
  st.code(log_text, language="text")
142
 
 
143
  col1, col2 = st.columns([1, 1], gap="large")
144
 
 
145
  with col1:
146
  st.header("1. Upload Video")
147
  uploaded_video = st.file_uploader(
 
164
  else:
165
  video_preview_placeholder.empty()
166
 
 
167
  with col2:
168
  background, bg_type = _render_background_settings()
169
  st.header("3. Process Video")
170
 
 
171
  progress_container = st.container()
172
  with progress_container:
173
  progress_bar = st.progress(0)
 
180
  and (background is not None)
181
  )
182
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
183
  if st.button("Process Video", disabled=not can_process, use_container_width=True):
184
  try:
185
  logger.info("Process Video button clicked")
186
 
 
 
 
 
 
 
187
  import io
188
  class _MemFile:
189
  def __init__(self, name, data):
 
198
  st.session_state.processing = True
199
  mem_video = _MemFile("uploaded.mp4", st.session_state.video_bytes_cache)
200
 
201
+ # Start processing in background thread
202
+ thread = threading.Thread(
203
+ target=process_video_func,
204
+ args=(mem_video, background, bg_type.lower()),
205
+ daemon=True
206
+ )
207
+ thread.start()
208
 
209
+ # Poll for progress updates
210
+ while thread.is_alive() or st.session_state.get('processing', False):
211
+ status = get_progress()
212
+
213
+ if status.get('active') or not status.get('complete'):
214
+ # Update UI
215
+ progress_bar.progress(status.get('progress', 0))
216
+ status_text.info(f"**Status:** {status.get('message', 'Processing...')}")
217
+ stage_status.markdown(f"**Current Stage:** {status.get('stage', 'Unknown')}")
218
+
219
+ # Check for errors
220
+ if status.get('error'):
221
+ status_text.error(f"**Error:** {status['error']}")
222
+ break
223
+
224
+ # Check if complete
225
+ if status.get('complete'):
226
+ break
227
+
228
+ time.sleep(1) # Poll every second
229
+
230
+ # Wait for thread to finish
231
+ thread.join(timeout=5)
232
+
233
+ # Final status check
234
+ final_status = get_progress()
235
+ if final_status.get('error'):
236
+ progress_bar.progress(final_status.get('progress', 0))
237
+ status_text.error(f"**Status:** Processing failed - {final_status['error']}")
238
+ st.error(f"Processing failed: {final_status['error']}")
239
+ elif st.session_state.get('processed_video_bytes'):
240
  progress_bar.progress(100)
241
  status_text.success("**Status:** Processing complete!")
242
  st.success("Video processing complete!")
243
  else:
244
+ status_text.error("**Status:** Processing failed. Check logs.")
245
+ st.error("Processing failed. Check logs for details.")
246
+
247
  except Exception as e:
248
  st.session_state.processing = False
249
  logger.error(f"[UI] Process video error: {e}", exc_info=True)
250
  status_text.error(f"**Status:** Error - {str(e)}")
251
  st.error(f"Processing error: {str(e)}. Check logs for details.")
252
 
 
253
  if st.session_state.get('processed_video_bytes') is not None:
254
  st.markdown("---")
255
  st.markdown("### Processed Video")
 
266
  logger.error(f"[UI] Display error: {e}", exc_info=True)
267
  st.error(f"Display error: {e}")
268
 
 
269
  if st.session_state.get('last_error'):
270
  with st.expander("Last Error", expanded=True):
271
  st.error(st.session_state.last_error)