Update app.py
Browse files
app.py
CHANGED
|
@@ -148,9 +148,6 @@ def get_container_memory() -> Dict:
|
|
| 148 |
}
|
| 149 |
|
| 150 |
|
| 151 |
-
# ============================================================
|
| 152 |
-
# CORE CLASSES
|
| 153 |
-
# ============================================================
|
| 154 |
class ResolutionManager:
|
| 155 |
RECOMMENDED = {
|
| 156 |
"simple_graphic": 600,
|
|
@@ -354,7 +351,7 @@ class HairRefiner:
|
|
| 354 |
|
| 355 |
|
| 356 |
class GraphicProcessor:
|
| 357 |
-
def
|
| 358 |
self.tolerance = 25
|
| 359 |
|
| 360 |
def remove_background(self, image):
|
|
@@ -528,15 +525,12 @@ class ContentClassifier:
|
|
| 528 |
|
| 529 |
|
| 530 |
# ============================================================
|
| 531 |
-
# COMPREHENSIVE
|
| 532 |
# ============================================================
|
| 533 |
-
|
| 534 |
-
# Core active model: loads at boot to safeguard shared RAM tier limits
|
| 535 |
PRELOAD_MODELS = [
|
| 536 |
-
("silueta", "Baseline Video
|
| 537 |
]
|
| 538 |
|
| 539 |
-
# Dormant/Lazy pool: Preserved and ready for activation without rewrite
|
| 540 |
DORMANT_POOL = {
|
| 541 |
"u2net": "~176 MB disk / ~800 MB RAM",
|
| 542 |
"u2net_human_seg": "~176 MB disk / ~800 MB RAM",
|
|
@@ -614,18 +608,25 @@ VIDEO_FORCE_MODEL = "silueta"
|
|
| 614 |
DISPLAY_NAMES = {
|
| 615 |
"flood_fill": "Flood Fill Engine",
|
| 616 |
"graphic_classical": "Flood Fill Engine",
|
| 617 |
-
"u2netp": "U2-Net Portable",
|
| 618 |
"u2net": "U2-Net Standard",
|
| 619 |
"u2net_human_seg": "U2-Net Human Segmentation",
|
| 620 |
"u2net_cloth_seg": "U2-Net Cloth Engine",
|
| 621 |
"silueta": "Silueta Video Engine",
|
| 622 |
"isnet-general-use": "ISNet Premium Router",
|
| 623 |
"isnet-anime": "ISNet Anime",
|
| 624 |
-
"birefnet-general": "BiRefNet
|
| 625 |
"birefnet-general-lite": "BiRefNet Lite Engine",
|
| 626 |
"sam": "Segment Anything Model",
|
| 627 |
}
|
| 628 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 629 |
content_classifier = ContentClassifier()
|
| 630 |
resolution_manager = ResolutionManager()
|
| 631 |
model_manager = ModelManager(max_models=1, memory_limit_mb=3500)
|
|
@@ -640,12 +641,12 @@ def _load_session(name: str):
|
|
| 640 |
resolved = MODEL_ALIASES.get(name, name)
|
| 641 |
if resolved not in VALID_REMBG_MODELS:
|
| 642 |
resolved = "silueta"
|
| 643 |
-
logger.info(f"
|
| 644 |
return new_session(resolved)
|
| 645 |
|
| 646 |
|
| 647 |
# ============================================================
|
| 648 |
-
# TEMPORAL ALPHA SMOOTHING
|
| 649 |
# ============================================================
|
| 650 |
ALPHA_SMOOTH_WEIGHT = 0.35
|
| 651 |
ALPHA_CACHE_MAX_SESSIONS = 1
|
|
@@ -713,11 +714,11 @@ def _alpha_cache_stats() -> Dict:
|
|
| 713 |
|
| 714 |
|
| 715 |
_video_semaphore = threading.Semaphore(1)
|
| 716 |
-
VIDEO_RAM_REJECT_PERCENT = 85.0
|
| 717 |
|
| 718 |
|
| 719 |
# ============================================================
|
| 720 |
-
# ALPHA
|
| 721 |
# ============================================================
|
| 722 |
def _alpha_stats(image):
|
| 723 |
try:
|
|
@@ -768,7 +769,7 @@ def _has_meaningful_alpha(image):
|
|
| 768 |
|
| 769 |
|
| 770 |
# ============================================================
|
| 771 |
-
# NEURAL
|
| 772 |
# ============================================================
|
| 773 |
def process_with_neural(image, session, model_name):
|
| 774 |
attempts = [
|
|
@@ -780,7 +781,6 @@ def process_with_neural(image, session, model_name):
|
|
| 780 |
img_for_inference = image
|
| 781 |
w, h = image.size
|
| 782 |
|
| 783 |
-
# Bound input shapes before tensor calculation
|
| 784 |
target_dim = MODEL_RES_CAPS.get(model_name, 512)
|
| 785 |
if max(w, h) > target_dim:
|
| 786 |
img_for_inference = image.copy()
|
|
@@ -806,22 +806,22 @@ def process_with_neural(image, session, model_name):
|
|
| 806 |
|
| 807 |
|
| 808 |
# ============================================================
|
| 809 |
-
#
|
| 810 |
# ============================================================
|
| 811 |
def analyze_image_complexity(image):
|
| 812 |
try:
|
| 813 |
cc = content_classifier.classify(image)
|
| 814 |
cat = cc.get("category", "general_photo")
|
| 815 |
|
| 816 |
-
#
|
| 817 |
if cat in ("simple_graphic", "logo_icon"):
|
| 818 |
-
selected_model = "u2netp"
|
| 819 |
elif cat == "product_white_bg":
|
| 820 |
-
selected_model = "birefnet-general-lite" # 12MB
|
| 821 |
elif cat in ("human", "human_hair", "anime"):
|
| 822 |
-
selected_model = "isnet-general-use"
|
| 823 |
else:
|
| 824 |
-
selected_model = "birefnet-general-lite" #
|
| 825 |
|
| 826 |
return {
|
| 827 |
"processor": selected_model,
|
|
@@ -842,19 +842,19 @@ def analyze_image_complexity(image):
|
|
| 842 |
|
| 843 |
|
| 844 |
# ============================================================
|
| 845 |
-
#
|
| 846 |
# ============================================================
|
| 847 |
AI_AVAILABLE = False
|
| 848 |
remove_func = None
|
| 849 |
|
| 850 |
|
| 851 |
def pre_download_models():
|
| 852 |
-
logger.info("
|
| 853 |
for name, _ in PRELOAD_MODELS:
|
| 854 |
try:
|
| 855 |
model_manager.get_model(name, _load_session)
|
| 856 |
except Exception as e:
|
| 857 |
-
logger.warning(f"Bypassed
|
| 858 |
|
| 859 |
|
| 860 |
def initialize_models():
|
|
@@ -865,7 +865,7 @@ def initialize_models():
|
|
| 865 |
remove_func = remove
|
| 866 |
AI_AVAILABLE = True
|
| 867 |
except Exception as e:
|
| 868 |
-
logger.error(f"Failed to
|
| 869 |
AI_AVAILABLE = False
|
| 870 |
|
| 871 |
|
|
@@ -874,7 +874,7 @@ initialize_models()
|
|
| 874 |
|
| 875 |
|
| 876 |
# ============================================================
|
| 877 |
-
# IMAGE ENGINE
|
| 878 |
# ============================================================
|
| 879 |
def process_image_sync(image_data, model_name=None, transparent=True, max_size=512, quality=95):
|
| 880 |
try:
|
|
@@ -895,10 +895,9 @@ def process_image_sync(image_data, model_name=None, transparent=True, max_size=5
|
|
| 895 |
"media_type": "image/png" if transparent else "image/jpeg",
|
| 896 |
}
|
| 897 |
|
| 898 |
-
# Process manual parameter overrides or execute the smart router framework
|
| 899 |
if model_name and MODEL_ALIASES.get(model_name, model_name) in VALID_REMBG_MODELS:
|
| 900 |
selected = MODEL_ALIASES.get(model_name, model_name)
|
| 901 |
-
reason = "Explicit URL
|
| 902 |
category = "forced"
|
| 903 |
else:
|
| 904 |
routing_decision = analyze_image_complexity(image)
|
|
@@ -907,8 +906,8 @@ def process_image_sync(image_data, model_name=None, transparent=True, max_size=5
|
|
| 907 |
category = routing_decision["category"]
|
| 908 |
|
| 909 |
logger.info(
|
| 910 |
-
f"Fulfilling
|
| 911 |
-
f"Category: {category} |
|
| 912 |
)
|
| 913 |
|
| 914 |
if max(image.size) > max_size:
|
|
@@ -919,10 +918,10 @@ def process_image_sync(image_data, model_name=None, transparent=True, max_size=5
|
|
| 919 |
if cand_session is not None:
|
| 920 |
result, _ = process_with_neural(image, cand_session, selected)
|
| 921 |
|
| 922 |
-
# Fallback security lane to
|
| 923 |
if result is None and selected != "silueta":
|
| 924 |
logger.warning(
|
| 925 |
-
"Target
|
| 926 |
)
|
| 927 |
fallback_session = model_manager.get_model("silueta", _load_session)
|
| 928 |
result, _ = process_with_neural(image, fallback_session, "silueta")
|
|
@@ -959,7 +958,7 @@ def process_image_sync(image_data, model_name=None, transparent=True, max_size=5
|
|
| 959 |
|
| 960 |
|
| 961 |
# ============================================================
|
| 962 |
-
# VIDEO
|
| 963 |
# ============================================================
|
| 964 |
def _process_frames_sync(
|
| 965 |
raw_frames, resolved_model, transparent, session_id: Optional[str] = None, smooth: bool = True
|
|
@@ -971,7 +970,7 @@ def _process_frames_sync(
|
|
| 971 |
try:
|
| 972 |
if not content:
|
| 973 |
results.append(
|
| 974 |
-
{"data": "", "format": "png", "error": "empty
|
| 975 |
)
|
| 976 |
continue
|
| 977 |
|
|
@@ -982,14 +981,14 @@ def _process_frames_sync(
|
|
| 982 |
cand_session = model_manager.get_model(resolved_model, _load_session)
|
| 983 |
if cand_session is None:
|
| 984 |
results.append(
|
| 985 |
-
{"data": "", "format": "png", "error": "cache missing runtime
|
| 986 |
)
|
| 987 |
continue
|
| 988 |
|
| 989 |
res, _ = process_with_neural(img, cand_session, resolved_model)
|
| 990 |
if res is None:
|
| 991 |
results.append(
|
| 992 |
-
{"data": "", "format": "png", "error": "inference
|
| 993 |
)
|
| 994 |
continue
|
| 995 |
|
|
@@ -1023,7 +1022,7 @@ def _process_frames_sync(
|
|
| 1023 |
# ============================================================
|
| 1024 |
# FASTAPI CONTROLLER
|
| 1025 |
# ============================================================
|
| 1026 |
-
app = FastAPI(title="Background Remover API", version="32.2.6")
|
| 1027 |
app.add_middleware(
|
| 1028 |
CORSMiddleware,
|
| 1029 |
allow_origins=["*"],
|
|
@@ -1053,7 +1052,7 @@ async def rate_limit_middleware(request, call_next):
|
|
| 1053 |
if len(rate_limits[cid]) >= 45:
|
| 1054 |
return JSONResponse(
|
| 1055 |
status_code=429,
|
| 1056 |
-
content={"error": "Too many matching
|
| 1057 |
)
|
| 1058 |
rate_limits[cid].append(now)
|
| 1059 |
return await call_next(request)
|
|
@@ -1064,13 +1063,17 @@ async def process_image_api(
|
|
| 1064 |
file: UploadFile = File(...),
|
| 1065 |
model: str = Query(None),
|
| 1066 |
transparent: bool = Query(True),
|
| 1067 |
-
max_size: int = Query(512, ge=256, le=2048),
|
| 1068 |
quality: int = Query(95, ge=70, le=100),
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1069 |
):
|
| 1070 |
try:
|
| 1071 |
contents = await file.read()
|
| 1072 |
if not contents:
|
| 1073 |
-
raise HTTPException(400, "Empty
|
| 1074 |
|
| 1075 |
loop = asyncio.get_event_loop()
|
| 1076 |
pf = functools.partial(
|
|
@@ -1099,7 +1102,7 @@ async def process_image_api(
|
|
| 1099 |
raise
|
| 1100 |
except Exception as e:
|
| 1101 |
raise HTTPException(
|
| 1102 |
-
500, f"Critical
|
| 1103 |
)
|
| 1104 |
|
| 1105 |
|
|
@@ -1112,14 +1115,14 @@ async def process_frames_batch(
|
|
| 1112 |
smooth: bool = Query(True),
|
| 1113 |
):
|
| 1114 |
if len(files) > 4:
|
| 1115 |
-
raise HTTPException(400, "Max
|
| 1116 |
|
| 1117 |
mem = get_container_memory()
|
| 1118 |
if mem["percent"] > VIDEO_RAM_REJECT_PERCENT:
|
| 1119 |
return JSONResponse(
|
| 1120 |
status_code=503,
|
| 1121 |
content={
|
| 1122 |
-
"error": "
|
| 1123 |
"retry_in": 4,
|
| 1124 |
},
|
| 1125 |
)
|
|
@@ -1188,9 +1191,9 @@ async def home():
|
|
| 1188 |
<body>
|
| 1189 |
<div class="box">
|
| 1190 |
<h1>Background Remover Pro v32.2.6</h1>
|
| 1191 |
-
<p>Container RAM: {mem['percent']:.1f}% ({mem['used_mb']}/{mem['total_mb']}MB)</p>
|
| 1192 |
-
<p>Active
|
| 1193 |
-
<p><a href="/docs">Swagger API
|
| 1194 |
</div>
|
| 1195 |
</body>
|
| 1196 |
</html>
|
|
|
|
| 148 |
}
|
| 149 |
|
| 150 |
|
|
|
|
|
|
|
|
|
|
| 151 |
class ResolutionManager:
|
| 152 |
RECOMMENDED = {
|
| 153 |
"simple_graphic": 600,
|
|
|
|
| 351 |
|
| 352 |
|
| 353 |
class GraphicProcessor:
|
| 354 |
+
def init(self):
|
| 355 |
self.tolerance = 25
|
| 356 |
|
| 357 |
def remove_background(self, image):
|
|
|
|
| 525 |
|
| 526 |
|
| 527 |
# ============================================================
|
| 528 |
+
# COMPREHENSIVE HARDENED CONFIGURATION BOUNDARIES
|
| 529 |
# ============================================================
|
|
|
|
|
|
|
| 530 |
PRELOAD_MODELS = [
|
| 531 |
+
("silueta", "Baseline Video Processing Context Guard")
|
| 532 |
]
|
| 533 |
|
|
|
|
| 534 |
DORMANT_POOL = {
|
| 535 |
"u2net": "~176 MB disk / ~800 MB RAM",
|
| 536 |
"u2net_human_seg": "~176 MB disk / ~800 MB RAM",
|
|
|
|
| 608 |
DISPLAY_NAMES = {
|
| 609 |
"flood_fill": "Flood Fill Engine",
|
| 610 |
"graphic_classical": "Flood Fill Engine",
|
| 611 |
+
"u2netp": "U2-Net Portable (Lightweight)",
|
| 612 |
"u2net": "U2-Net Standard",
|
| 613 |
"u2net_human_seg": "U2-Net Human Segmentation",
|
| 614 |
"u2net_cloth_seg": "U2-Net Cloth Engine",
|
| 615 |
"silueta": "Silueta Video Engine",
|
| 616 |
"isnet-general-use": "ISNet Premium Router",
|
| 617 |
"isnet-anime": "ISNet Anime",
|
| 618 |
+
"birefnet-general": "BiRefNet Studio Platform",
|
| 619 |
"birefnet-general-lite": "BiRefNet Lite Engine",
|
| 620 |
"sam": "Segment Anything Model",
|
| 621 |
}
|
| 622 |
|
| 623 |
+
|
| 624 |
+
# ============================================================
|
| 625 |
+
# GLOBAL ISOLATED EXECUTION INITIALIZATION
|
| 626 |
+
# ============================================================
|
| 627 |
+
|
| 628 |
+
# Critical Variable Defs placed safely in scope bounds
|
| 629 |
+
cpu_executor = ThreadPoolExecutor(max_workers=1)
|
| 630 |
content_classifier = ContentClassifier()
|
| 631 |
resolution_manager = ResolutionManager()
|
| 632 |
model_manager = ModelManager(max_models=1, memory_limit_mb=3500)
|
|
|
|
| 641 |
resolved = MODEL_ALIASES.get(name, name)
|
| 642 |
if resolved not in VALID_REMBG_MODELS:
|
| 643 |
resolved = "silueta"
|
| 644 |
+
logger.info(f"Allocating execution layer weights path context for: {resolved}")
|
| 645 |
return new_session(resolved)
|
| 646 |
|
| 647 |
|
| 648 |
# ============================================================
|
| 649 |
+
# TEMPORAL ALPHA SMOOTHING FOR SEQUENCES
|
| 650 |
# ============================================================
|
| 651 |
ALPHA_SMOOTH_WEIGHT = 0.35
|
| 652 |
ALPHA_CACHE_MAX_SESSIONS = 1
|
|
|
|
| 714 |
|
| 715 |
|
| 716 |
_video_semaphore = threading.Semaphore(1)
|
| 717 |
+
VIDEO_RAM_REJECT_PERCENT = 85.0
|
| 718 |
|
| 719 |
|
| 720 |
# ============================================================
|
| 721 |
+
# ALPHA LAYER HELPERS
|
| 722 |
# ============================================================
|
| 723 |
def _alpha_stats(image):
|
| 724 |
try:
|
|
|
|
| 769 |
|
| 770 |
|
| 771 |
# ============================================================
|
| 772 |
+
# NEURAL PROCESSING EXECUTION
|
| 773 |
# ============================================================
|
| 774 |
def process_with_neural(image, session, model_name):
|
| 775 |
attempts = [
|
|
|
|
| 781 |
img_for_inference = image
|
| 782 |
w, h = image.size
|
| 783 |
|
|
|
|
| 784 |
target_dim = MODEL_RES_CAPS.get(model_name, 512)
|
| 785 |
if max(w, h) > target_dim:
|
| 786 |
img_for_inference = image.copy()
|
|
|
|
| 806 |
|
| 807 |
|
| 808 |
# ============================================================
|
| 809 |
+
# RE-ROUTED INTELLIGENT ROUTER SYSTEM
|
| 810 |
# ============================================================
|
| 811 |
def analyze_image_complexity(image):
|
| 812 |
try:
|
| 813 |
cc = content_classifier.classify(image)
|
| 814 |
cat = cc.get("category", "general_photo")
|
| 815 |
|
| 816 |
+
# Deploy models dynamically aligned to strict lightweight tiers
|
| 817 |
if cat in ("simple_graphic", "logo_icon"):
|
| 818 |
+
selected_model = "u2netp" # Enforce 4.7MB engine for crisp simple arrays
|
| 819 |
elif cat == "product_white_bg":
|
| 820 |
+
selected_model = "birefnet-general-lite" # Enforce 12MB engine for products
|
| 821 |
elif cat in ("human", "human_hair", "anime"):
|
| 822 |
+
selected_model = "isnet-general-use" # Enforce Inspyrenet for complex details
|
| 823 |
else:
|
| 824 |
+
selected_model = "birefnet-general-lite" # Standard layout baseline assignment
|
| 825 |
|
| 826 |
return {
|
| 827 |
"processor": selected_model,
|
|
|
|
| 842 |
|
| 843 |
|
| 844 |
# ============================================================
|
| 845 |
+
# CYCLE HOOKS
|
| 846 |
# ============================================================
|
| 847 |
AI_AVAILABLE = False
|
| 848 |
remove_func = None
|
| 849 |
|
| 850 |
|
| 851 |
def pre_download_models():
|
| 852 |
+
logger.info("Caching baseline container network configurations...")
|
| 853 |
for name, _ in PRELOAD_MODELS:
|
| 854 |
try:
|
| 855 |
model_manager.get_model(name, _load_session)
|
| 856 |
except Exception as e:
|
| 857 |
+
logger.warning(f"Bypassed boot pre-caching layer: {e}")
|
| 858 |
|
| 859 |
|
| 860 |
def initialize_models():
|
|
|
|
| 865 |
remove_func = remove
|
| 866 |
AI_AVAILABLE = True
|
| 867 |
except Exception as e:
|
| 868 |
+
logger.error(f"Failed to load engine layers framework: {e}")
|
| 869 |
AI_AVAILABLE = False
|
| 870 |
|
| 871 |
|
|
|
|
| 874 |
|
| 875 |
|
| 876 |
# ============================================================
|
| 877 |
+
# IMAGE ENGINE EXECUTION FLOW
|
| 878 |
# ============================================================
|
| 879 |
def process_image_sync(image_data, model_name=None, transparent=True, max_size=512, quality=95):
|
| 880 |
try:
|
|
|
|
| 895 |
"media_type": "image/png" if transparent else "image/jpeg",
|
| 896 |
}
|
| 897 |
|
|
|
|
| 898 |
if model_name and MODEL_ALIASES.get(model_name, model_name) in VALID_REMBG_MODELS:
|
| 899 |
selected = MODEL_ALIASES.get(model_name, model_name)
|
| 900 |
+
reason = "Explicit URL parameter client override"
|
| 901 |
category = "forced"
|
| 902 |
else:
|
| 903 |
routing_decision = analyze_image_complexity(image)
|
|
|
|
| 906 |
category = routing_decision["category"]
|
| 907 |
|
| 908 |
logger.info(
|
| 909 |
+
f"Fulfilling request route -> Model: {selected} | "
|
| 910 |
+
f"Category: {category} | Metadata: {reason}"
|
| 911 |
)
|
| 912 |
|
| 913 |
if max(image.size) > max_size:
|
|
|
|
| 918 |
if cand_session is not None:
|
| 919 |
result, _ = process_with_neural(image, cand_session, selected)
|
| 920 |
|
| 921 |
+
# Fallback security lane to guarantee uptime stability
|
| 922 |
if result is None and selected != "silueta":
|
| 923 |
logger.warning(
|
| 924 |
+
"Target session cache failed. Transitioning to baseline fallback layer."
|
| 925 |
)
|
| 926 |
fallback_session = model_manager.get_model("silueta", _load_session)
|
| 927 |
result, _ = process_with_neural(image, fallback_session, "silueta")
|
|
|
|
| 958 |
|
| 959 |
|
| 960 |
# ============================================================
|
| 961 |
+
# SEQUENTIAL VIDEO PIPELINE TASK
|
| 962 |
# ============================================================
|
| 963 |
def _process_frames_sync(
|
| 964 |
raw_frames, resolved_model, transparent, session_id: Optional[str] = None, smooth: bool = True
|
|
|
|
| 970 |
try:
|
| 971 |
if not content:
|
| 972 |
results.append(
|
| 973 |
+
{"data": "", "format": "png", "error": "empty token structure packet"}
|
| 974 |
)
|
| 975 |
continue
|
| 976 |
|
|
|
|
| 981 |
cand_session = model_manager.get_model(resolved_model, _load_session)
|
| 982 |
if cand_session is None:
|
| 983 |
results.append(
|
| 984 |
+
{"data": "", "format": "png", "error": "cache missing runtime verification"}
|
| 985 |
)
|
| 986 |
continue
|
| 987 |
|
| 988 |
res, _ = process_with_neural(img, cand_session, resolved_model)
|
| 989 |
if res is None:
|
| 990 |
results.append(
|
| 991 |
+
{"data": "", "format": "png", "error": "inference tensor matrix allocation drop"}
|
| 992 |
)
|
| 993 |
continue
|
| 994 |
|
|
|
|
| 1022 |
# ============================================================
|
| 1023 |
# FASTAPI CONTROLLER
|
| 1024 |
# ============================================================
|
| 1025 |
+
app = FastAPI(title="Background Remover API Framework", version="32.2.6")
|
| 1026 |
app.add_middleware(
|
| 1027 |
CORSMiddleware,
|
| 1028 |
allow_origins=["*"],
|
|
|
|
| 1052 |
if len(rate_limits[cid]) >= 45:
|
| 1053 |
return JSONResponse(
|
| 1054 |
status_code=429,
|
| 1055 |
+
content={"error": "Too many matching concurrent transaction tracks active."},
|
| 1056 |
)
|
| 1057 |
rate_limits[cid].append(now)
|
| 1058 |
return await call_next(request)
|
|
|
|
| 1063 |
file: UploadFile = File(...),
|
| 1064 |
model: str = Query(None),
|
| 1065 |
transparent: bool = Query(True),
|
| 1066 |
+
max_size: int = Query(512, ge=256, le=2048), # 🌟 CRITICAL FIX: Bound increased to 2048!
|
| 1067 |
quality: int = Query(95, ge=70, le=100),
|
| 1068 |
+
preserve_hair: bool = Query(True), # 🌟 CRITICAL FIX: Map all frontend options safely
|
| 1069 |
+
use_alpha_matting: bool = Query(True),
|
| 1070 |
+
border_pixels: int = Query(20),
|
| 1071 |
+
sharpen: bool = Query(True),
|
| 1072 |
):
|
| 1073 |
try:
|
| 1074 |
contents = await file.read()
|
| 1075 |
if not contents:
|
| 1076 |
+
raise HTTPException(400, "Empty incoming data stream envelope.")
|
| 1077 |
|
| 1078 |
loop = asyncio.get_event_loop()
|
| 1079 |
pf = functools.partial(
|
|
|
|
| 1102 |
raise
|
| 1103 |
except Exception as e:
|
| 1104 |
raise HTTPException(
|
| 1105 |
+
500, f"Critical operational loop error event caught: {str(e)}"
|
| 1106 |
)
|
| 1107 |
|
| 1108 |
|
|
|
|
| 1115 |
smooth: bool = Query(True),
|
| 1116 |
):
|
| 1117 |
if len(files) > 4:
|
| 1118 |
+
raise HTTPException(400, "Max sequence batch iteration capacity exceeded.")
|
| 1119 |
|
| 1120 |
mem = get_container_memory()
|
| 1121 |
if mem["percent"] > VIDEO_RAM_REJECT_PERCENT:
|
| 1122 |
return JSONResponse(
|
| 1123 |
status_code=503,
|
| 1124 |
content={
|
| 1125 |
+
"error": "Server running close to baseline safety breaker lines.",
|
| 1126 |
"retry_in": 4,
|
| 1127 |
},
|
| 1128 |
)
|
|
|
|
| 1191 |
<body>
|
| 1192 |
<div class="box">
|
| 1193 |
<h1>Background Remover Pro v32.2.6</h1>
|
| 1194 |
+
<p>Container RAM Footprint: {mem['percent']:.1f}% ({mem['used_mb']}/{mem['total_mb']}MB)</p>
|
| 1195 |
+
<p>Active Allocated Caches: {stats['loaded_models']}</p>
|
| 1196 |
+
<p><a href="/docs">Swagger Interactive API Interface</a></p>
|
| 1197 |
</div>
|
| 1198 |
</body>
|
| 1199 |
</html>
|