MogensR commited on
Commit
843b297
·
1 Parent(s): a09952a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +69 -25
app.py CHANGED
@@ -8,7 +8,6 @@
8
  import early_env # <<< must be FIRST to sanitize threading/env before anything else
9
 
10
  import os
11
- import logging
12
  from pathlib import Path
13
  from typing import Optional, Tuple, Dict, Any, Callable
14
 
@@ -36,12 +35,11 @@ def patched_get_type(schema):
36
  except Exception:
37
  pass # No fatal error if Gradio patch fails
38
 
39
- # 3️⃣ Set up logging early for debugging
40
- logging.basicConfig(
41
- level=logging.INFO,
42
- format="%(asctime)s - %(levelname)s - %(name)s - %(message)s"
43
- )
44
- logger = logging.getLogger("BackgroundFX")
45
 
46
  # 4️⃣ Import your modular code (assuming your project structure)
47
  from core.exceptions import ModelLoadingError, VideoProcessingError
@@ -51,8 +49,10 @@ def patched_get_type(schema):
51
  from models.loaders.model_loader import ModelLoader
52
  from processing.video.video_processor import CoreVideoProcessor, ProcessorConfig
53
  from processing.audio.audio_processor import AudioProcessor
54
- from utils.cv_processing import PROFESSIONAL_BACKGROUNDS, validate_video_file
55
- # If you have TwoStage: from processing.two_stage.two_stage_processor import TwoStageProcessor, CHROMA_PRESETS
 
 
56
 
57
  # 5️⃣ CSP-safe fallback model stubs
58
  class CSPSafeSAM2:
@@ -65,13 +65,22 @@ def predict(self, point_coords=None, point_labels=None, box=None, multimask_outp
65
  return np.ones((n, h, w), dtype=bool), np.array([0.9, 0.8, 0.7][:n]), np.ones((n, h, w), dtype=np.float32)
66
 
67
  class CSPSafeMatAnyone:
68
- def step(self, image_tensor, mask_tensor=None, objects=None, first_frame_pred=False):
69
  import torch
70
- shape = getattr(image_tensor, 'shape', (1, 3, 256, 256))
71
- return torch.ones((shape[0], 1, shape[2], shape[3]))
 
 
 
 
 
 
 
 
 
72
  def output_prob_to_mask(self, output_prob):
73
  return (output_prob > 0.5).float()
74
- def process(self, image, mask):
75
  return mask
76
 
77
  # 6️⃣ Application main processor object
@@ -84,50 +93,78 @@ def __init__(self):
84
  self.audio_proc = AudioProcessor()
85
  self.models_loaded = False
86
  self.core_processor = None
 
87
 
88
  def load_models(self, progress_callback: Optional[Callable]=None) -> str:
89
- logger.info("Loading models (CSP-safe)...")
90
  try:
91
  sam2, matanyone = self.model_loader.load_all_models(progress_callback=progress_callback)
92
  except Exception as e:
93
- logger.warning(f"Model loading failed ({e}) - Using CSP-safe fallbacks")
94
  sam2, matanyone = None, None
 
95
  sam2_model = getattr(sam2, "model", sam2) if sam2 else CSPSafeSAM2()
96
  matanyone_model = getattr(matanyone, "model", matanyone) if matanyone else CSPSafeMatAnyone()
 
 
97
  self.core_processor = CoreVideoProcessor(config=ProcessorConfig(), models=None)
98
  self.core_processor.models = type('FakeModelManager', (), {
99
- 'get_sam2': lambda self: sam2_model,
100
- 'get_matanyone': lambda self: matanyone_model
101
  })()
 
102
  self.models_loaded = True
103
- return "Models loaded (CSP-safe, fallback mode if no AI models loaded)."
 
 
104
 
105
  def process_video(self, video, bg_style, custom_bg_file):
106
  if not self.models_loaded:
107
  return None, "Models not loaded yet"
 
 
 
 
108
  import time
109
  output_path = f"/tmp/output_{int(time.time())}.mp4"
110
- cfg = PROFESSIONAL_BACKGROUNDS.get(bg_style, PROFESSIONAL_BACKGROUNDS["minimalist"])
 
111
  if custom_bg_file:
112
  cfg = {"custom_path": custom_bg_file.name}
113
- ok, msg = validate_video_file(video)
 
 
 
 
 
 
114
  if not ok:
115
- return None, f"Invalid video: {msg}"
 
 
116
  try:
117
  result = self.core_processor.process_video(
118
  input_path=video,
119
  output_path=output_path,
120
  bg_config=cfg
121
  )
 
 
122
  output_with_audio = self.audio_proc.add_audio_to_video(video, output_path)
123
- return output_with_audio, f"Processing complete ({result.get('frames', 'n/a')} frames, {bg_style})"
 
 
 
 
124
  except Exception as e:
 
125
  return None, f"Processing failed: {e}"
126
 
127
  # 7️⃣ Gradio interface CSP-safe
128
  def create_csp_safe_gradio():
129
  import gradio as gr
130
  app = VideoBackgroundApp()
 
131
  with gr.Blocks(
132
  title="BackgroundFX Pro - CSP Safe",
133
  analytics_enabled=False,
@@ -141,9 +178,11 @@ def create_csp_safe_gradio():
141
  with gr.Row():
142
  with gr.Column():
143
  video = gr.Video(label="Upload Video")
 
 
144
  bg_style = gr.Dropdown(
145
- choices=list(PROFESSIONAL_BACKGROUNDS.keys()),
146
- value="minimalist",
147
  label="Background Style"
148
  )
149
  custom_bg = gr.File(label="Custom Background (Optional)", file_types=["image"])
@@ -155,9 +194,14 @@ def create_csp_safe_gradio():
155
  out_video = gr.Video(label="Processed Video")
156
 
157
  def safe_load():
158
- return app.load_models()
 
 
 
159
  def safe_process(vid, style, custom_bg_file):
 
160
  return app.process_video(vid, style, custom_bg_file)
 
161
  btn_load.click(fn=safe_load, outputs=[status])
162
  btn_run.click(fn=safe_process, inputs=[video, bg_style, custom_bg], outputs=[out_video, status])
163
 
 
8
  import early_env # <<< must be FIRST to sanitize threading/env before anything else
9
 
10
  import os
 
11
  from pathlib import Path
12
  from typing import Optional, Tuple, Dict, Any, Callable
13
 
 
35
  except Exception:
36
  pass # No fatal error if Gradio patch fails
37
 
38
+ # 3️⃣ Initialize logging EARLY (before importing modules that emit logs)
39
+ from utils.logging_setup import setup_logging, make_logger
40
+ setup_logging(app_name="backgroundfx") # LOG_LEVEL env var respected; defaults to DEBUG in dev
41
+ logger = make_logger("entrypoint")
42
+ logger.info("Entrypoint starting…")
 
43
 
44
  # 4️⃣ Import your modular code (assuming your project structure)
45
  from core.exceptions import ModelLoadingError, VideoProcessingError
 
49
  from models.loaders.model_loader import ModelLoader
50
  from processing.video.video_processor import CoreVideoProcessor, ProcessorConfig
51
  from processing.audio.audio_processor import AudioProcessor
52
+
53
+ # NOTE: You previously imported from utils.cv_processing; adjust if needed.
54
+ # Here we import from your unified utils (the file you showed me earlier).
55
+ from utils import PROFESSIONAL_BACKGROUNDS, validate_video_file
56
 
57
  # 5️⃣ CSP-safe fallback model stubs
58
  class CSPSafeSAM2:
 
65
  return np.ones((n, h, w), dtype=bool), np.array([0.9, 0.8, 0.7][:n]), np.ones((n, h, w), dtype=np.float32)
66
 
67
  class CSPSafeMatAnyone:
68
+ def step(self, image_tensor, mask_tensor=None, objects=None, first_frame_pred=False, **kwargs):
69
  import torch
70
+ # image_tensor is CHW or NCHW (guard in ModelLoader handles it)
71
+ if hasattr(image_tensor, "shape"):
72
+ if len(image_tensor.shape) == 3:
73
+ _, H, W = image_tensor.shape
74
+ elif len(image_tensor.shape) == 4:
75
+ _, _, H, W = image_tensor.shape
76
+ else:
77
+ H, W = 256, 256
78
+ else:
79
+ H, W = 256, 256
80
+ return torch.ones((1, 1, H, W))
81
  def output_prob_to_mask(self, output_prob):
82
  return (output_prob > 0.5).float()
83
+ def process(self, image, mask, **kwargs):
84
  return mask
85
 
86
  # 6️⃣ Application main processor object
 
93
  self.audio_proc = AudioProcessor()
94
  self.models_loaded = False
95
  self.core_processor = None
96
+ logger.info("VideoBackgroundApp initialized (device=%s)", self.device_mgr.get_optimal_device())
97
 
98
  def load_models(self, progress_callback: Optional[Callable]=None) -> str:
99
+ logger.info("Loading models (CSP-safe)")
100
  try:
101
  sam2, matanyone = self.model_loader.load_all_models(progress_callback=progress_callback)
102
  except Exception as e:
103
+ logger.warning("Model loading failed (%s) - Using CSP-safe fallbacks", e)
104
  sam2, matanyone = None, None
105
+
106
  sam2_model = getattr(sam2, "model", sam2) if sam2 else CSPSafeSAM2()
107
  matanyone_model = getattr(matanyone, "model", matanyone) if matanyone else CSPSafeMatAnyone()
108
+
109
+ # CoreVideoProcessor expects a models manager; provide minimal adapter
110
  self.core_processor = CoreVideoProcessor(config=ProcessorConfig(), models=None)
111
  self.core_processor.models = type('FakeModelManager', (), {
112
+ 'get_sam2': lambda self_: sam2_model,
113
+ 'get_matanyone': lambda self_: matanyone_model
114
  })()
115
+
116
  self.models_loaded = True
117
+ logger.info("Models ready (SAM2=%s, MatAnyOne=%s)",
118
+ type(sam2_model).__name__, type(matanyone_model).__name__)
119
+ return "Models loaded (CSP-safe; fallbacks in use if actual AI models failed)."
120
 
121
  def process_video(self, video, bg_style, custom_bg_file):
122
  if not self.models_loaded:
123
  return None, "Models not loaded yet"
124
+
125
+ logger.info("process_video called (video=%s, bg_style=%s, custom_bg=%s)",
126
+ video, bg_style, getattr(custom_bg_file, "name", None))
127
+
128
  import time
129
  output_path = f"/tmp/output_{int(time.time())}.mp4"
130
+
131
+ # Background config
132
  if custom_bg_file:
133
  cfg = {"custom_path": custom_bg_file.name}
134
+ else:
135
+ # Safe default: ensure value exists in dict
136
+ style = bg_style if bg_style in PROFESSIONAL_BACKGROUNDS else "office"
137
+ cfg = PROFESSIONAL_BACKGROUNDS.get(style, PROFESSIONAL_BACKGROUNDS["office"])
138
+
139
+ # Validate input video (your `validate_video_file` returns bool)
140
+ ok = validate_video_file(video)
141
  if not ok:
142
+ logger.warning("Invalid/unreadable video: %s", video)
143
+ return None, "Invalid or unreadable video file"
144
+
145
  try:
146
  result = self.core_processor.process_video(
147
  input_path=video,
148
  output_path=output_path,
149
  bg_config=cfg
150
  )
151
+ logger.info("Core processing done → %s", output_path)
152
+
153
  output_with_audio = self.audio_proc.add_audio_to_video(video, output_path)
154
+ logger.info("Audio merged %s", output_with_audio)
155
+
156
+ frames = (result.get('frames') if isinstance(result, dict) else None) or "n/a"
157
+ return output_with_audio, f"Processing complete ({frames} frames, style={bg_style})"
158
+
159
  except Exception as e:
160
+ logger.exception("Processing failed")
161
  return None, f"Processing failed: {e}"
162
 
163
  # 7️⃣ Gradio interface CSP-safe
164
  def create_csp_safe_gradio():
165
  import gradio as gr
166
  app = VideoBackgroundApp()
167
+
168
  with gr.Blocks(
169
  title="BackgroundFX Pro - CSP Safe",
170
  analytics_enabled=False,
 
178
  with gr.Row():
179
  with gr.Column():
180
  video = gr.Video(label="Upload Video")
181
+ # Ensure default choice exists in PROFESSIONAL_BACKGROUNDS (use 'office')
182
+ choices = list(PROFESSIONAL_BACKGROUNDS.keys())
183
  bg_style = gr.Dropdown(
184
+ choices=choices,
185
+ value="office",
186
  label="Background Style"
187
  )
188
  custom_bg = gr.File(label="Custom Background (Optional)", file_types=["image"])
 
194
  out_video = gr.Video(label="Processed Video")
195
 
196
  def safe_load():
197
+ msg = app.load_models()
198
+ logger.info("UI: models loaded")
199
+ return msg
200
+
201
  def safe_process(vid, style, custom_bg_file):
202
+ logger.info("UI: starting processing (style=%s)", style)
203
  return app.process_video(vid, style, custom_bg_file)
204
+
205
  btn_load.click(fn=safe_load, outputs=[status])
206
  btn_run.click(fn=safe_process, inputs=[video, bg_style, custom_bg], outputs=[out_video, status])
207