Update app.py
Browse files
app.py
CHANGED
|
@@ -5,7 +5,6 @@
|
|
| 5 |
NEW: Added automatic device detection for Hugging Face Spaces compatibility,
|
| 6 |
improved error handling, and better resource management
|
| 7 |
"""
|
| 8 |
-
import sys
|
| 9 |
import cv2
|
| 10 |
import numpy as np
|
| 11 |
from pathlib import Path
|
|
@@ -18,6 +17,7 @@
|
|
| 18 |
from typing import Optional, Tuple, Dict, Any
|
| 19 |
import logging
|
| 20 |
from huggingface_hub import hf_hub_download
|
|
|
|
| 21 |
|
| 22 |
# Import utilities - CRITICAL: Use these functions, don't duplicate!
|
| 23 |
from utilities import (
|
|
@@ -61,7 +61,7 @@
|
|
| 61 |
models_loaded = False
|
| 62 |
loading_lock = threading.Lock()
|
| 63 |
two_stage_processor = None
|
| 64 |
-
PROCESS_CANCELLED =
|
| 65 |
|
| 66 |
# ============================================================================ #
|
| 67 |
# DEVICE DETECTION FOR HUGGING FACE SPACES
|
|
@@ -115,7 +115,7 @@ def _prog(pct: float, desc: str):
|
|
| 115 |
|
| 116 |
# Download checkpoint with caching
|
| 117 |
checkpoint_path = hf_hub_download(
|
| 118 |
-
repo_id="
|
| 119 |
filename="sam2_hiera_large.pt",
|
| 120 |
cache_dir=str(CACHE_DIR / "sam2_checkpoint"),
|
| 121 |
force_download=False
|
|
@@ -223,11 +223,11 @@ def load_models_with_validation(progress_callback: Optional[callable] = None) ->
|
|
| 223 |
global sam2_predictor, matanyone_model, models_loaded, two_stage_processor, PROCESS_CANCELLED
|
| 224 |
|
| 225 |
with loading_lock:
|
| 226 |
-
if models_loaded and not PROCESS_CANCELLED:
|
| 227 |
return "Models already loaded and validated"
|
| 228 |
|
| 229 |
try:
|
| 230 |
-
PROCESS_CANCELLED
|
| 231 |
start_time = time.time()
|
| 232 |
logger.info(f"Starting model loading on {DEVICE}")
|
| 233 |
|
|
@@ -237,13 +237,13 @@ def load_models_with_validation(progress_callback: Optional[callable] = None) ->
|
|
| 237 |
# Load SAM2 with validation
|
| 238 |
sam2_predictor = load_sam2_predictor_fixed(device=DEVICE, progress_callback=progress_callback)
|
| 239 |
|
| 240 |
-
if PROCESS_CANCELLED:
|
| 241 |
return "Model loading cancelled by user"
|
| 242 |
|
| 243 |
# Load MatAnyone with validation
|
| 244 |
matanyone_model = load_matanyone_fixed(progress_callback=progress_callback)
|
| 245 |
|
| 246 |
-
if PROCESS_CANCELLED:
|
| 247 |
return "Model loading cancelled by user"
|
| 248 |
|
| 249 |
models_loaded = True
|
|
@@ -282,7 +282,7 @@ def process_video_fixed(
|
|
| 282 |
"""Optimized video processing using proper functions from utilities"""
|
| 283 |
global PROCESS_CANCELLED
|
| 284 |
|
| 285 |
-
if PROCESS_CANCELLED:
|
| 286 |
return None, "Processing cancelled by user"
|
| 287 |
|
| 288 |
if not models_loaded:
|
|
@@ -297,7 +297,7 @@ def process_video_fixed(
|
|
| 297 |
return None, f"Invalid video: {validation_msg}"
|
| 298 |
|
| 299 |
def _prog(pct: float, desc: str):
|
| 300 |
-
if PROCESS_CANCELLED:
|
| 301 |
raise Exception("Processing cancelled by user")
|
| 302 |
|
| 303 |
if progress_callback:
|
|
@@ -376,7 +376,7 @@ def _prog(pct: float, desc: str):
|
|
| 376 |
progress_callback=_prog
|
| 377 |
)
|
| 378 |
|
| 379 |
-
if PROCESS_CANCELLED:
|
| 380 |
return None, "Processing cancelled by user"
|
| 381 |
|
| 382 |
if result is None:
|
|
@@ -391,7 +391,7 @@ def _prog(pct: float, desc: str):
|
|
| 391 |
f'ffmpeg -y -i "{final_output}" -i "{video_path}" '
|
| 392 |
f'-c:v libx264 -crf 18 -preset medium '
|
| 393 |
f'-c:a aac -b:a 192k -ac 2 -ar 48000 '
|
| 394 |
-
f'-map 0:v:0 -map 1:a:0? -shortest "{final_with_audio}"'
|
| 395 |
)
|
| 396 |
os.system(audio_cmd)
|
| 397 |
if os.path.exists(final_with_audio):
|
|
@@ -479,7 +479,7 @@ def _prog(pct: float, desc: str):
|
|
| 479 |
start_time = time.time()
|
| 480 |
|
| 481 |
while True:
|
| 482 |
-
if PROCESS_CANCELLED:
|
| 483 |
cap.release()
|
| 484 |
final_writer.release()
|
| 485 |
if os.path.exists(final_path):
|
|
@@ -568,7 +568,7 @@ def _prog(pct: float, desc: str):
|
|
| 568 |
cap.release()
|
| 569 |
final_writer.release()
|
| 570 |
|
| 571 |
-
if PROCESS_CANCELLED:
|
| 572 |
if os.path.exists(final_path):
|
| 573 |
os.remove(final_path)
|
| 574 |
return None, "Processing cancelled by user"
|
|
@@ -594,7 +594,7 @@ def _prog(pct: float, desc: str):
|
|
| 594 |
f'ffmpeg -y -i "{final_path}" -i "{video_path}" '
|
| 595 |
f'-c:v libx264 -crf 18 -preset medium '
|
| 596 |
f'-c:a aac -b:a 192k -ac 2 -ar 48000 '
|
| 597 |
-
f'-map 0:v:0 -map 1:a:0? -shortest "{final_output}"'
|
| 598 |
)
|
| 599 |
result = os.system(audio_cmd)
|
| 600 |
if result != 0 or not os.path.exists(final_output):
|
|
@@ -667,4 +667,4 @@ def main():
|
|
| 667 |
print(f"Startup failed: {e}")
|
| 668 |
|
| 669 |
if __name__ == "__main__":
|
| 670 |
-
main()
|
|
|
|
| 5 |
NEW: Added automatic device detection for Hugging Face Spaces compatibility,
|
| 6 |
improved error handling, and better resource management
|
| 7 |
"""
|
|
|
|
| 8 |
import cv2
|
| 9 |
import numpy as np
|
| 10 |
from pathlib import Path
|
|
|
|
| 17 |
from typing import Optional, Tuple, Dict, Any
|
| 18 |
import logging
|
| 19 |
from huggingface_hub import hf_hub_download
|
| 20 |
+
import os
|
| 21 |
|
| 22 |
# Import utilities - CRITICAL: Use these functions, don't duplicate!
|
| 23 |
from utilities import (
|
|
|
|
| 61 |
models_loaded = False
|
| 62 |
loading_lock = threading.Lock()
|
| 63 |
two_stage_processor = None
|
| 64 |
+
PROCESS_CANCELLED = threading.Event()
|
| 65 |
|
| 66 |
# ============================================================================ #
|
| 67 |
# DEVICE DETECTION FOR HUGGING FACE SPACES
|
|
|
|
| 115 |
|
| 116 |
# Download checkpoint with caching
|
| 117 |
checkpoint_path = hf_hub_download(
|
| 118 |
+
repo_id="facebookresearch/sam2",
|
| 119 |
filename="sam2_hiera_large.pt",
|
| 120 |
cache_dir=str(CACHE_DIR / "sam2_checkpoint"),
|
| 121 |
force_download=False
|
|
|
|
| 223 |
global sam2_predictor, matanyone_model, models_loaded, two_stage_processor, PROCESS_CANCELLED
|
| 224 |
|
| 225 |
with loading_lock:
|
| 226 |
+
if models_loaded and not PROCESS_CANCELLED.is_set():
|
| 227 |
return "Models already loaded and validated"
|
| 228 |
|
| 229 |
try:
|
| 230 |
+
PROCESS_CANCELLED.clear()
|
| 231 |
start_time = time.time()
|
| 232 |
logger.info(f"Starting model loading on {DEVICE}")
|
| 233 |
|
|
|
|
| 237 |
# Load SAM2 with validation
|
| 238 |
sam2_predictor = load_sam2_predictor_fixed(device=DEVICE, progress_callback=progress_callback)
|
| 239 |
|
| 240 |
+
if PROCESS_CANCELLED.is_set():
|
| 241 |
return "Model loading cancelled by user"
|
| 242 |
|
| 243 |
# Load MatAnyone with validation
|
| 244 |
matanyone_model = load_matanyone_fixed(progress_callback=progress_callback)
|
| 245 |
|
| 246 |
+
if PROCESS_CANCELLED.is_set():
|
| 247 |
return "Model loading cancelled by user"
|
| 248 |
|
| 249 |
models_loaded = True
|
|
|
|
| 282 |
"""Optimized video processing using proper functions from utilities"""
|
| 283 |
global PROCESS_CANCELLED
|
| 284 |
|
| 285 |
+
if PROCESS_CANCELLED.is_set():
|
| 286 |
return None, "Processing cancelled by user"
|
| 287 |
|
| 288 |
if not models_loaded:
|
|
|
|
| 297 |
return None, f"Invalid video: {validation_msg}"
|
| 298 |
|
| 299 |
def _prog(pct: float, desc: str):
|
| 300 |
+
if PROCESS_CANCELLED.is_set():
|
| 301 |
raise Exception("Processing cancelled by user")
|
| 302 |
|
| 303 |
if progress_callback:
|
|
|
|
| 376 |
progress_callback=_prog
|
| 377 |
)
|
| 378 |
|
| 379 |
+
if PROCESS_CANCELLED.is_set():
|
| 380 |
return None, "Processing cancelled by user"
|
| 381 |
|
| 382 |
if result is None:
|
|
|
|
| 391 |
f'ffmpeg -y -i "{final_output}" -i "{video_path}" '
|
| 392 |
f'-c:v libx264 -crf 18 -preset medium '
|
| 393 |
f'-c:a aac -b:a 192k -ac 2 -ar 48000 '
|
| 394 |
+
f'-map 0:v:0 -map 1:a:0? -shortest "{final_with_audio}" -loglevel error'
|
| 395 |
)
|
| 396 |
os.system(audio_cmd)
|
| 397 |
if os.path.exists(final_with_audio):
|
|
|
|
| 479 |
start_time = time.time()
|
| 480 |
|
| 481 |
while True:
|
| 482 |
+
if PROCESS_CANCELLED.is_set():
|
| 483 |
cap.release()
|
| 484 |
final_writer.release()
|
| 485 |
if os.path.exists(final_path):
|
|
|
|
| 568 |
cap.release()
|
| 569 |
final_writer.release()
|
| 570 |
|
| 571 |
+
if PROCESS_CANCELLED.is_set():
|
| 572 |
if os.path.exists(final_path):
|
| 573 |
os.remove(final_path)
|
| 574 |
return None, "Processing cancelled by user"
|
|
|
|
| 594 |
f'ffmpeg -y -i "{final_path}" -i "{video_path}" '
|
| 595 |
f'-c:v libx264 -crf 18 -preset medium '
|
| 596 |
f'-c:a aac -b:a 192k -ac 2 -ar 48000 '
|
| 597 |
+
f'-map 0:v:0 -map 1:a:0? -shortest "{final_output}" -loglevel error'
|
| 598 |
)
|
| 599 |
result = os.system(audio_cmd)
|
| 600 |
if result != 0 or not os.path.exists(final_output):
|
|
|
|
| 667 |
print(f"Startup failed: {e}")
|
| 668 |
|
| 669 |
if __name__ == "__main__":
|
| 670 |
+
main()
|