MogensR commited on
Commit
8420d76
·
verified ·
1 Parent(s): 3c73a70

Update ui.py

Browse files
Files changed (1) hide show
  1. ui.py +56 -74
ui.py CHANGED
@@ -3,7 +3,6 @@
3
  Modern UI for Video Background Replacer (PRO)
4
  - Clean, responsive Streamlit layout
5
  - Shows live stage progress and all errors during processing
6
- - Robust to missing stock images (won't crash the app)
7
  """
8
  import streamlit as st
9
  import os
@@ -15,8 +14,6 @@
15
 
16
  logger = logging.getLogger("Advanced Video Background Replacer")
17
 
18
- LOG_PATH = "/tmp/app.log"
19
-
20
  def tail_file(path: str, lines: int = 400) -> str:
21
  if not os.path.exists(path):
22
  return "(log file not found)"
@@ -37,22 +34,20 @@ def read_file_bytes(path: str) -> bytes:
37
  return b""
38
 
39
  def _render_background_settings():
40
- """
41
- Returns:
42
- background: PIL.Image (RGB) for 'Image'/'Stock', or "#RRGGBB" for 'Color', or generated PIL for 'AI Prompt'
43
- bg_type: one of {'Image','Color','Stock','AI Prompt'}
44
- """
 
45
  st.header("2. Background Settings")
46
-
47
  bg_type = st.radio(
48
  "Select Background Type:",
49
  ["Image", "Color", "Stock", "AI Prompt"],
50
  horizontal=True,
51
  key="bg_type_radio"
52
  )
53
-
54
  background = None
55
- app_dir = Path(__file__).resolve().parent
56
 
57
  if bg_type == "Image":
58
  bg_image = st.file_uploader(
@@ -61,69 +56,49 @@ def _render_background_settings():
61
  key="bg_image_uploader"
62
  )
63
  if bg_image is not None:
64
- try:
65
- bg_image.seek(0)
66
- background = Image.open(bg_image).convert("RGB")
67
- st.image(background, caption="Selected Background", use_column_width=True)
68
- except Exception as e:
69
- logger.error(f"[UI] Failed to open uploaded background: {e}", exc_info=True)
70
- st.error(f"Could not open uploaded image: {e}")
71
 
72
  elif bg_type == "Color":
73
- default_color = st.session_state.get('bg_color', "#00FF00")
74
- selected_color = st.color_picker("Choose Background Color", default_color, key="color_picker")
 
 
 
75
  background = selected_color
76
- try:
77
- rgb = tuple(int(selected_color.lstrip('#')[i:i+2], 16) for i in (0, 2, 4))
78
- color_preview = np.full((100, 100, 3), rgb, dtype=np.uint8)
79
- st.image(color_preview, caption="Selected Color", width=200)
80
- except Exception as e:
81
- logger.error(f"[UI] Color preview error: {e}", exc_info=True)
82
- st.warning("Invalid color value.")
83
 
84
  elif bg_type == "Stock":
85
- # Resolve stock image paths relative to this file; filter to ones that actually exist.
86
- stock_dir = app_dir / "stock_images"
87
- stock_candidates = {
88
- "Sunset Beach": stock_dir / "sunset_beach.jpg",
89
- "Urban Office": stock_dir / "urban_office.jpg",
90
- "Studio Lighting": stock_dir / "studio_light.jpg",
91
- }
92
- available = {k: v for k, v in stock_candidates.items() if v.exists()}
93
-
94
- if not stock_dir.exists():
95
- st.warning(f"Stock images folder not found: {stock_dir}")
96
- if not available:
97
- st.info("No stock images found on disk. Upload an image, choose a Color, or use AI Prompt.")
98
- else:
99
- stock_choice = st.selectbox(
100
- "Choose a professional stock background:",
101
- list(available.keys()),
102
- key="stock_image_select"
103
- )
104
- selected_path = available.get(stock_choice)
105
- if selected_path is not None:
106
- try:
107
- background = Image.open(selected_path).convert("RGB")
108
- st.image(background, caption=stock_choice, use_column_width=True)
109
- except Exception as e:
110
- logger.error(f"[UI] Failed to open stock image '{selected_path}': {e}", exc_info=True)
111
- st.error(f"Could not open stock image: {selected_path}")
112
 
113
  elif bg_type == "AI Prompt":
114
  prompt = st.text_input("Describe the background to generate (AI):", key="ai_bg_prompt")
115
  ai_ready = False
116
  if st.button("Generate Background", key="gen_bg_btn") and prompt:
117
  # TODO: Plug in real AI image generator
118
- try:
119
- background = Image.new("RGB", (512, 320), (64, 32, 96))
120
- st.session_state.generated_bg = background
121
- st.success("AI-generated background (stub). Replace with your generator!")
122
- ai_ready = True
123
- except Exception as e:
124
- logger.error(f"[UI] AI generator stub failed: {e}", exc_info=True)
125
- st.error(f"AI generation failed: {e}")
126
- elif "generated_bg" in st.session_state and isinstance(st.session_state.generated_bg, Image.Image):
127
  background = st.session_state.generated_bg
128
  ai_ready = True
129
  if ai_ready and background is not None:
@@ -136,9 +111,7 @@ def render_ui(process_video_func):
136
  # --- Sidebar: System Status & Logs ---
137
  with st.sidebar:
138
  st.subheader("System Status")
139
- st.markdown(f"**Log file:** `{LOG_PATH}`")
140
-
141
- # GPU status (best-effort)
142
  if st.session_state.get('gpu_available', False):
143
  try:
144
  import torch
@@ -149,10 +122,12 @@ def render_ui(process_video_func):
149
  else:
150
  st.error("GPU: Not Available")
151
 
 
152
  st.checkbox("Auto-refresh log tail (every 2s)", key="auto_refresh_logs")
153
  st.number_input("Tail last N lines", min_value=50, max_value=5000, step=50, key="log_tail_lines")
154
 
155
- log_bytes = read_file_bytes(LOG_PATH)
 
156
  st.download_button(
157
  "Download Logs",
158
  data=log_bytes if log_bytes else b"Log file not available yet.",
@@ -162,13 +137,18 @@ def render_ui(process_video_func):
162
  disabled=not bool(log_bytes)
163
  )
164
 
 
165
  with st.expander("View Log Tail", expanded=True):
166
- if st.session_state.get('auto_refresh_logs', False):
 
 
 
167
  time.sleep(2)
168
  st.rerun()
169
- log_text = tail_file(LOG_PATH, st.session_state.get('log_tail_lines', 400))
170
- # Use a text_area to ensure scrolling works consistently in Spaces
171
- st.text_area("Log tail", value=log_text, height=400, label_visibility="collapsed")
 
172
 
173
  # --- Main UI: Two-Column Layout ---
174
  col1, col2 = st.columns([1, 1], gap="large")
@@ -198,10 +178,8 @@ def render_ui(process_video_func):
198
  # --- Column 2: Background & Processing ---
199
  with col2:
200
  background, bg_type = _render_background_settings()
201
-
202
  st.header("3. Process Video")
203
  status_box = st.empty() # <--- Status/progress area
204
-
205
  can_process = (
206
  uploaded_video is not None
207
  and not st.session_state.get('processing', False)
@@ -212,6 +190,11 @@ def progress_callback(msg):
212
  status_box.info(msg)
213
  logger.info(f"[STAGE] {msg}")
214
 
 
 
 
 
 
215
  if st.button("Process Video", disabled=not can_process, use_container_width=True):
216
  try:
217
  logger.info("Process Video button clicked")
@@ -256,7 +239,6 @@ def progress_callback(msg):
256
  if st.button("Clear Error"):
257
  st.session_state.last_error = None
258
  st.rerun()
259
-
260
  except Exception as e:
261
  logger.error(f"[UI] Render UI error: {e}", exc_info=True)
262
  st.error(f"UI rendering error: {str(e)}. Check logs for details.")
 
3
  Modern UI for Video Background Replacer (PRO)
4
  - Clean, responsive Streamlit layout
5
  - Shows live stage progress and all errors during processing
 
6
  """
7
  import streamlit as st
8
  import os
 
14
 
15
  logger = logging.getLogger("Advanced Video Background Replacer")
16
 
 
 
17
  def tail_file(path: str, lines: int = 400) -> str:
18
  if not os.path.exists(path):
19
  return "(log file not found)"
 
34
  return b""
35
 
36
  def _render_background_settings():
37
+ # Available stock images (replace with your real logic or API)
38
+ stock_images = {
39
+ "Sunset Beach": "stock_images/sunset_beach.jpg",
40
+ "Urban Office": "stock_images/urban_office.jpg",
41
+ "Studio Lighting": "stock_images/studio_light.jpg",
42
+ }
43
  st.header("2. Background Settings")
 
44
  bg_type = st.radio(
45
  "Select Background Type:",
46
  ["Image", "Color", "Stock", "AI Prompt"],
47
  horizontal=True,
48
  key="bg_type_radio"
49
  )
 
50
  background = None
 
51
 
52
  if bg_type == "Image":
53
  bg_image = st.file_uploader(
 
56
  key="bg_image_uploader"
57
  )
58
  if bg_image is not None:
59
+ bg_image.seek(0)
60
+ background = Image.open(bg_image).convert("RGB")
61
+ st.image(background, caption="Selected Background", use_column_width=True)
 
 
 
 
62
 
63
  elif bg_type == "Color":
64
+ selected_color = st.color_picker(
65
+ "Choose Background Color",
66
+ st.session_state.get('bg_color', "#00FF00"),
67
+ key="color_picker"
68
+ )
69
  background = selected_color
70
+ color_preview = np.full(
71
+ (100, 100, 3),
72
+ tuple(int(selected_color.lstrip('#')[i:i+2], 16) for i in (0, 2, 4)),
73
+ dtype=np.uint8
74
+ )
75
+ st.image(color_preview, caption="Selected Color", width=200)
 
76
 
77
  elif bg_type == "Stock":
78
+ stock_choice = st.selectbox(
79
+ "Choose a professional stock background:",
80
+ list(stock_images.keys()),
81
+ key="stock_image_select"
82
+ )
83
+ stock_img_path = stock_images[stock_choice]
84
+ try:
85
+ background = Image.open(stock_img_path).convert("RGB")
86
+ st.image(background, caption=stock_choice, use_column_width=True)
87
+ except FileNotFoundError:
88
+ st.warning(f"Stock image not found: {stock_img_path}. Upload your own image or choose another.")
89
+ background = None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
 
91
  elif bg_type == "AI Prompt":
92
  prompt = st.text_input("Describe the background to generate (AI):", key="ai_bg_prompt")
93
  ai_ready = False
94
  if st.button("Generate Background", key="gen_bg_btn") and prompt:
95
  # TODO: Plug in real AI image generator
96
+ # For now, stub with a purple placeholder
97
+ background = Image.new("RGB", (512, 320), (64, 32, 96))
98
+ st.session_state.generated_bg = background
99
+ st.success("AI-generated background (stub). Replace with your generator!")
100
+ ai_ready = True
101
+ elif "generated_bg" in st.session_state:
 
 
 
102
  background = st.session_state.generated_bg
103
  ai_ready = True
104
  if ai_ready and background is not None:
 
111
  # --- Sidebar: System Status & Logs ---
112
  with st.sidebar:
113
  st.subheader("System Status")
114
+ st.markdown("**Log file:** `/tmp/app.log`")
 
 
115
  if st.session_state.get('gpu_available', False):
116
  try:
117
  import torch
 
122
  else:
123
  st.error("GPU: Not Available")
124
 
125
+ # Controls
126
  st.checkbox("Auto-refresh log tail (every 2s)", key="auto_refresh_logs")
127
  st.number_input("Tail last N lines", min_value=50, max_value=5000, step=50, key="log_tail_lines")
128
 
129
+ # Download logs
130
+ log_bytes = read_file_bytes("/tmp/app.log")
131
  st.download_button(
132
  "Download Logs",
133
  data=log_bytes if log_bytes else b"Log file not available yet.",
 
137
  disabled=not bool(log_bytes)
138
  )
139
 
140
+ # Log tail
141
  with st.expander("View Log Tail", expanded=True):
142
+ # IMPORTANT: do NOT rerun while a job is active
143
+ if st.session_state.get('auto_refresh_logs', False) and st.session_state.get('processing', False):
144
+ st.info("⏸ Auto-refresh paused while processing…")
145
+ elif st.session_state.get('auto_refresh_logs', False):
146
  time.sleep(2)
147
  st.rerun()
148
+
149
+ log_text = tail_file("/tmp/app.log", st.session_state.get('log_tail_lines', 400))
150
+ # Make sure this area scrolls and doesn't expand the page infinitely
151
+ st.code(log_text, language="text")
152
 
153
  # --- Main UI: Two-Column Layout ---
154
  col1, col2 = st.columns([1, 1], gap="large")
 
178
  # --- Column 2: Background & Processing ---
179
  with col2:
180
  background, bg_type = _render_background_settings()
 
181
  st.header("3. Process Video")
182
  status_box = st.empty() # <--- Status/progress area
 
183
  can_process = (
184
  uploaded_video is not None
185
  and not st.session_state.get('processing', False)
 
190
  status_box.info(msg)
191
  logger.info(f"[STAGE] {msg}")
192
 
193
+ # Don’t allow starting if auto-refresh is on (optional safety)
194
+ if st.session_state.get('auto_refresh_logs', False):
195
+ st.warning("Disable **Auto-refresh log tail** in the sidebar before processing.")
196
+ can_process = False
197
+
198
  if st.button("Process Video", disabled=not can_process, use_container_width=True):
199
  try:
200
  logger.info("Process Video button clicked")
 
239
  if st.button("Clear Error"):
240
  st.session_state.last_error = None
241
  st.rerun()
 
242
  except Exception as e:
243
  logger.error(f"[UI] Render UI error: {e}", exc_info=True)
244
  st.error(f"UI rendering error: {str(e)}. Check logs for details.")