Spaces:
Sleeping
Sleeping
Commit ·
931edec
1
Parent(s): 745b47a
Forced Redirecting pretrained weights to temp/cache
Browse files- Dockerfile +27 -21
- backend/app.py +39 -33
Dockerfile
CHANGED
|
@@ -1,38 +1,44 @@
|
|
| 1 |
-
# ---------- Stage 1: Build Next.js frontend
|
| 2 |
FROM node:18 AS frontend-builder
|
| 3 |
WORKDIR /frontend
|
| 4 |
COPY frontend/ .
|
| 5 |
-
# Install and build
|
| 6 |
RUN npm install && npm run build
|
| 7 |
|
| 8 |
-
# ---------- Stage 2:
|
| 9 |
FROM python:3.10-slim
|
| 10 |
-
ENV PYTHONDONTWRITEBYTECODE=1 \
|
| 11 |
-
PYTHONUNBUFFERED=1
|
| 12 |
|
| 13 |
-
# System deps
|
| 14 |
RUN apt-get update && apt-get install -y --no-install-recommends \
|
| 15 |
-
ffmpeg \
|
| 16 |
-
|
| 17 |
|
| 18 |
WORKDIR /app
|
| 19 |
|
| 20 |
-
#
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
|
| 25 |
-
|
| 26 |
-
# The Next.js export outputs to frontend/out by default
|
| 27 |
-
COPY --from=frontend-builder /frontend/out ./backend/static
|
| 28 |
|
| 29 |
-
#
|
| 30 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
|
| 32 |
-
#
|
| 33 |
-
|
| 34 |
-
PYTHONPATH=/app
|
| 35 |
|
| 36 |
-
# Start with gunicorn for production
|
| 37 |
WORKDIR /app/backend
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 38 |
CMD ["gunicorn", "app:app", "--bind", "0.0.0.0:7860", "--workers", "2", "--timeout", "180"]
|
|
|
|
| 1 |
+
# ---------- Stage 1: Build Next.js / React frontend (adjust if using CRA) ----------
|
| 2 |
FROM node:18 AS frontend-builder
|
| 3 |
WORKDIR /frontend
|
| 4 |
COPY frontend/ .
|
|
|
|
| 5 |
RUN npm install && npm run build
|
| 6 |
|
| 7 |
+
# ---------- Stage 2: Backend (Flask + Gunicorn) ----------
|
| 8 |
FROM python:3.10-slim
|
|
|
|
|
|
|
| 9 |
|
| 10 |
+
# System deps (add more if needed: libgl1 etc. for opencv)
|
| 11 |
RUN apt-get update && apt-get install -y --no-install-recommends \
|
| 12 |
+
build-essential git wget curl ffmpeg libglib2.0-0 libsm6 libxext6 libxrender1 \
|
| 13 |
+
&& rm -rf /var/lib/apt/lists/*
|
| 14 |
|
| 15 |
WORKDIR /app
|
| 16 |
|
| 17 |
+
# Writable cache locations to avoid PermissionError: '/.cache'
|
| 18 |
+
ENV HF_HOME=/tmp/.cache/huggingface \
|
| 19 |
+
TORCH_HOME=/tmp/.cache/torch \
|
| 20 |
+
TIMM_CACHE_DIR=/tmp/.cache/timm \
|
| 21 |
+
XDG_CACHE_HOME=/tmp/.cache \
|
| 22 |
+
HF_HUB_CACHE=/tmp/.cache/huggingface \
|
| 23 |
+
TRANSFORMERS_CACHE=/tmp/.cache/huggingface \
|
| 24 |
+
NO_ALBUMENTATIONS_UPDATE=1
|
| 25 |
|
| 26 |
+
RUN mkdir -p /tmp/.cache/huggingface /tmp/.cache/torch /tmp/.cache/timm
|
|
|
|
|
|
|
| 27 |
|
| 28 |
+
# Copy backend requirements first for better layer caching
|
| 29 |
+
COPY backend/requirements.txt ./backend/requirements.txt
|
| 30 |
+
RUN pip install --no-cache-dir -r backend/requirements.txt
|
| 31 |
+
|
| 32 |
+
# Copy backend code
|
| 33 |
+
COPY backend/ ./backend
|
| 34 |
|
| 35 |
+
# Copy built frontend output into backend static (adjust path if build folder differs)
|
| 36 |
+
COPY --from=frontend-builder /frontend/dist ./backend/static
|
|
|
|
| 37 |
|
|
|
|
| 38 |
WORKDIR /app/backend
|
| 39 |
+
|
| 40 |
+
# Expose Space port (Hugging Face uses 7860)
|
| 41 |
+
EXPOSE 7860
|
| 42 |
+
|
| 43 |
+
# Start with gunicorn
|
| 44 |
CMD ["gunicorn", "app:app", "--bind", "0.0.0.0:7860", "--workers", "2", "--timeout", "180"]
|
backend/app.py
CHANGED
|
@@ -3,51 +3,57 @@ from flask_cors import CORS
|
|
| 3 |
from werkzeug.utils import secure_filename
|
| 4 |
import os
|
| 5 |
import sys
|
| 6 |
-
import torch
|
| 7 |
-
import re
|
| 8 |
-
import numpy as np
|
| 9 |
-
from PIL import Image
|
| 10 |
-
import gc
|
| 11 |
import tempfile
|
| 12 |
import traceback
|
|
|
|
|
|
|
| 13 |
|
| 14 |
def _ensure_writable_caches():
|
| 15 |
-
"""
|
| 16 |
-
tmp
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
|
|
|
|
|
|
| 27 |
}
|
| 28 |
-
for
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
except Exception:
|
| 37 |
-
pass
|
| 38 |
|
| 39 |
_ensure_writable_caches()
|
| 40 |
|
| 41 |
-
# Add
|
| 42 |
sys.path.append('dfdc_model')
|
| 43 |
|
| 44 |
-
|
| 45 |
-
from dfdc_model.
|
| 46 |
-
from
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 47 |
|
| 48 |
-
app = Flask(__name__
|
| 49 |
CORS(app)
|
| 50 |
-
|
|
|
|
|
|
|
|
|
|
| 51 |
|
| 52 |
# Choose an upload folder that is writable in container environments.
|
| 53 |
# Prefer environment override, then /tmp/uploads, then a tempdir fallback.
|
|
|
|
| 3 |
from werkzeug.utils import secure_filename
|
| 4 |
import os
|
| 5 |
import sys
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6 |
import tempfile
|
| 7 |
import traceback
|
| 8 |
+
import logging
|
| 9 |
+
from PIL import Image
|
| 10 |
|
| 11 |
def _ensure_writable_caches():
|
| 12 |
+
"""
|
| 13 |
+
Redirect all model / hub caches to writable tmp directories to avoid
|
| 14 |
+
PermissionError inside container (e.g. attempts to write to '/.cache').
|
| 15 |
+
Safe to call multiple times.
|
| 16 |
+
"""
|
| 17 |
+
tmp_root = os.environ.get("TMPDIR") or tempfile.gettempdir()
|
| 18 |
+
base_cache = os.path.join(tmp_root, ".cache")
|
| 19 |
+
subdirs = {
|
| 20 |
+
"HF_HOME": "huggingface",
|
| 21 |
+
"HF_HUB_CACHE": "huggingface",
|
| 22 |
+
"TRANSFORMERS_CACHE": "huggingface",
|
| 23 |
+
"TORCH_HOME": "torch",
|
| 24 |
+
"TIMM_CACHE_DIR": "timm",
|
| 25 |
+
"XDG_CACHE_HOME": "", # root of the cache tree
|
| 26 |
}
|
| 27 |
+
for var, sub in subdirs.items():
|
| 28 |
+
path = os.environ.get(var)
|
| 29 |
+
if not path:
|
| 30 |
+
path = os.path.join(base_cache, sub) if sub else base_cache
|
| 31 |
+
os.environ[var] = path
|
| 32 |
+
os.makedirs(path, exist_ok=True)
|
| 33 |
+
# Quiet albumentations update check noise
|
| 34 |
+
os.environ.setdefault("NO_ALBUMENTATIONS_UPDATE", "1")
|
|
|
|
|
|
|
| 35 |
|
| 36 |
_ensure_writable_caches()
|
| 37 |
|
| 38 |
+
# Add model directory before importing model utilities
|
| 39 |
sys.path.append('dfdc_model')
|
| 40 |
|
| 41 |
+
try:
|
| 42 |
+
from dfdc_model.kernel_utils import VideoReader, FaceExtractor, confident_strategy, predict_on_video
|
| 43 |
+
from dfdc_model.training.zoo.classifiers import DeepFakeClassifier
|
| 44 |
+
except Exception as e:
|
| 45 |
+
traceback.print_exc()
|
| 46 |
+
with open(os.path.join(tempfile.gettempdir(), "startup_error.log"), "w", encoding="utf-8") as f:
|
| 47 |
+
f.write(traceback.format_exc())
|
| 48 |
+
VideoReader = FaceExtractor = confident_strategy = predict_on_video = None
|
| 49 |
+
DeepFakeClassifier = None
|
| 50 |
|
| 51 |
+
app = Flask(__name__)
|
| 52 |
CORS(app)
|
| 53 |
+
|
| 54 |
+
# Choose a writable upload folder
|
| 55 |
+
app.config["UPLOAD_FOLDER"] = os.environ.get("UPLOAD_FOLDER") or os.path.join(tempfile.gettempdir(), "uploads")
|
| 56 |
+
os.makedirs(app.config["UPLOAD_FOLDER"], exist_ok=True)
|
| 57 |
|
| 58 |
# Choose an upload folder that is writable in container environments.
|
| 59 |
# Prefer environment override, then /tmp/uploads, then a tempdir fallback.
|