Spaces:
Running
Running
| """ | |
| Configuration and Constants Module | |
| This module centralizes all configuration settings and constants used throughout | |
| the application. Think of this as a "settings file" where you can adjust behavior | |
| without touching the main code. | |
| For Non-Technical Developers: | |
| - DEVICE: Where the AI runs (GPU if available, CPU otherwise) | |
| - TIMEOUTS: How long to wait before giving up on internet requests | |
| - MODEL_CACHE_SIZE: How many things to remember to avoid re-downloading | |
| - THREAD_WORKERS: How many tasks can run at the same time | |
| """ | |
| import os | |
| import torch | |
| # ==================== DEVICE CONFIGURATION ==================== | |
| # Determines where the AI models run: | |
| # - 'cuda': Graphics card (NVIDIA GPU) - MUCH faster but requires NVIDIA GPU | |
| # - 'cpu': Regular computer processor - slower but works everywhere | |
| DEVICE = 'cuda' if torch.cuda.is_available() else 'cpu' | |
| # ==================== FILE PATHS ==================== | |
| # Paths to downloaded AI models that we use for face swapping | |
| INSWAPPER_MODEL_PATH = 'inswapper_128.onnx' # The main face-swapping model | |
| GFPGAN_MODEL_URL = 'https://github.com/TencentARC/GFPGAN/releases/download/v1.3.4/GFPGANv1.4.pth' # Updated to v1.4 | |
| # ==================== HUGGING FACE API ==================== | |
| # Hugging Face is a platform where AI models are stored | |
| # We need a token to download larger models | |
| HF_TOKEN = os.getenv('HF_TOKEN') | |
| INSWAPPER_HF_URL = 'https://huggingface.co/netrunner-exe/Insight-Swap-models-onnx/resolve/main/inswapper_128.onnx' | |
| # ==================== MODEL PATHS ==================== | |
| # Where downloaded models are stored | |
| # These can be customized via environment variables | |
| MODELS_DIR = os.getenv('MODELS_DIR', os.path.join(os.path.dirname(__file__), '..', 'models')) | |
| INSIGHTFACE_MODELS_DIR = os.getenv('INSIGHTFACE_MODELS_DIR', os.path.expanduser('~/.insightface/models')) | |
| GFPGAN_MODELS_DIR = os.getenv('GFPGAN_MODELS_DIR', os.path.expanduser('~/.cache/gfpgan')) | |
| # Create model directories if they don't exist | |
| os.makedirs(MODELS_DIR, exist_ok=True) | |
| os.makedirs(INSIGHTFACE_MODELS_DIR, exist_ok=True) | |
| os.makedirs(GFPGAN_MODELS_DIR, exist_ok=True) | |
| # ==================== HTTP/WEB SETTINGS ==================== | |
| # Standard browser headers - tells websites we're a normal browser, not a bot | |
| DEFAULT_HEADERS = { | |
| 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', | |
| 'Accept': 'image/avif,image/webp,image/apng,image/*,*/*;q=0.8', | |
| } | |
| # Optional Instagram session cookie to improve media extraction reliability | |
| INSTAGRAM_SESSION_COOKIE = os.getenv('INSTAGRAM_SESSION_COOKIE') or os.getenv('INSTAGRAM_COOKIE') | |
| INSTAGRAM_ACCEPT_LANGUAGE = os.getenv('INSTAGRAM_ACCEPT_LANGUAGE', 'en-US,en;q=0.9') | |
| INSTAGRAM_APP_ID = os.getenv('INSTAGRAM_APP_ID', '936619743392459') | |
| INSTAGRAM_HEADERS = dict(DEFAULT_HEADERS) | |
| INSTAGRAM_HEADERS['Accept-Language'] = INSTAGRAM_ACCEPT_LANGUAGE | |
| INSTAGRAM_HEADERS['X-IG-App-ID'] = INSTAGRAM_APP_ID | |
| INSTAGRAM_HEADERS['X-Requested-With'] = 'XMLHttpRequest' | |
| INSTAGRAM_HEADERS['Referer'] = 'https://www.instagram.com/' | |
| if INSTAGRAM_SESSION_COOKIE: | |
| INSTAGRAM_HEADERS['Cookie'] = INSTAGRAM_SESSION_COOKIE | |
| # How long to wait (in seconds) before timing out when downloading files from the internet | |
| DOWNLOAD_TIMEOUT = 30 | |
| # ==================== SUPPORTED MEDIA FORMATS ==================== | |
| # File extensions we can process | |
| SUPPORTED_IMAGE_FORMATS = {'.jpg', '.jpeg', '.png', '.webp', '.bmp', '.tiff'} | |
| SUPPORTED_VIDEO_FORMATS = {'.mp4', '.mov', '.avi', '.mkv', '.flv', '.wmv'} | |
| SUPPORTED_GIF_FORMATS = {'.gif'} | |
| SUPPORTED_FORMATS = SUPPORTED_IMAGE_FORMATS | SUPPORTED_VIDEO_FORMATS | SUPPORTED_GIF_FORMATS | |
| # Default processing limits to avoid deployment timeouts on long videos | |
| DEFAULT_MAX_FRAMES = 60 | |
| MAX_ALLOWED_FRAMES = 120 | |
| PROCESSING_TIMEOUT_SECONDS = 240 | |
| # ==================== CACHING SETTINGS ==================== | |
| # Cache: A way to remember things we've already downloaded/processed | |
| # This saves time and internet bandwidth | |
| EMBEDDING_CACHE_SIZE = 10 # How many face embeddings to remember | |
| FRAME_CACHE_SIZE = 5 # How many video/GIF frame sequences to remember | |
| # ==================== FACE DETECTION SETTINGS ==================== | |
| # Constants for face detection thresholds | |
| FACE_DETECTION_THRESHOLDS = [0.15, 0.10, 0.05] # Try these confidence levels, in order | |
| MIN_FACE_CONFIDENCE = 0.15 # Don't process faces with confidence lower than this | |
| MIN_LANDMARK_CONFIDENCE = 0.2 # Minimum confidence for face landmarks (features like eyes, nose) | |
| # How many consecutive frames can have NO face before we give up and stop trying | |
| NO_FACE_LIMIT = 10 | |
| # Face size thresholds (in pixels) | |
| MIN_FACE_AREA_RATIO = 0.01 # Minimum face area as a percentage of frame size | |
| FACE_POSE_THRESHOLD = 60 # Maximum head rotation angle (degrees) to accept | |
| # ==================== PREPROCESSING SETTINGS ==================== | |
| # Preprocessing: Preparing frames to make them easier for AI to detect faces | |
| # Different strengths for different use cases | |
| PREPROCESS_STRENGTHS = { | |
| 'light': { | |
| 'clahe_limit': 1.5, | |
| 'sharpen_strength': 0.3, | |
| 'apply_gamma': False, | |
| }, | |
| 'medium': { | |
| 'clahe_limit': 2.5, | |
| 'sharpen_strength': 0.5, | |
| 'apply_gamma': False, | |
| }, | |
| 'heavy': { | |
| 'clahe_limit': 4.0, | |
| 'sharpen_strength': 1.0, | |
| 'apply_gamma': True, | |
| }, | |
| } | |
| # ==================== THREADING/PARALLELIZATION ==================== | |
| # Threading: Running multiple tasks at the same time to speed things up | |
| MAX_WORKERS = 4 # Maximum number of tasks that can run simultaneously | |
| # Multi-threading options for PyTorch (AI library) | |
| TORCH_NUM_THREADS = 2 # Keep low to avoid bottlenecks | |
| ONNX_INTRA_OP_THREADS = 2 # Threads for running individual AI operations | |
| # ==================== OUTPUT SETTINGS ==================== | |
| # Settings for generating output GIFs | |
| GIF_QUALITY = 80 # Quality level (1-100, higher = better quality but bigger file) | |
| DEFAULT_GIF_DURATION = 67 # milliseconds - how long to show each frame | |
| # ==================== INSTAGRAM SETTINGS ==================== | |
| # Instagram connection settings for extracting photos/videos from posts/reels | |
| INSTAGRAM_API_TIMEOUT = 30 # How long to wait for Instagram responses | |
| INSTAGRAM_MAX_RETRIES = 3 # How many times to try if Instagram connection fails | |
| INSTAGRAM_REQUEST_DELAY = 1 # Seconds to wait between Instagram API requests (to be polite) | |
| # ==================== LOGGING/DEBUGGING ==================== | |
| # Whether to print detailed information while processing | |
| DEBUG_MODE = os.getenv('DEBUG_MODE', 'False').lower() == 'true' | |
| # ==================== VIDEO SETTINGS ==================== | |
| # Settings for converting videos to frames | |
| VIDEO_FRAME_EXTRACTION_METHOD = 'cv2' # How to extract frames from video files | |
| VIDEO_CODEC = 'mp4v' # Codec for video encoding | |
| # Default frames per second when extracting from video | |
| # If unknown, we use this to estimate duration | |
| DEFAULT_VIDEO_FPS = 30 | |
| # ==================== ERROR MESSAGES ==================== | |
| # User-friendly error messages | |
| ERROR_MESSAGES = { | |
| 'no_face_source': 'Could not detect a face in the source image. Please provide a clear photo with a visible face.', | |
| 'no_face_target': 'Could not detect a face in the target image/video. Please use a target with visible faces.', | |
| 'invalid_media_url': 'The provided URL does not point to a valid image or video.', | |
| 'unsupported_format': 'The media format is not supported. Please use: GIF, MP4, WebP, PNG, or JPG.', | |
| 'download_failed': 'Failed to download the media. Please check the URL and try again.', | |
| 'instagram_extraction_failed': 'Could not extract media from Instagram. Please check the link and try again.', | |
| 'processing_error': 'An error occurred during face swapping. Please try again.', | |
| 'swap_failed': 'Face swap failed. The source or target images may not be suitable.', | |
| } | |