# app.py (Complete Version for Hugging Face Spaces) import os import gradio as gr from refacer import Refacer import imageio from PIL import Image import tempfile import base64 import shutil import time # --- Configuration (Hardcoded for Hugging Face Spaces) --- NUM_FACES = 8 FORCE_CPU = True # --- Initialize Refacer --- refacer = Refacer(force_cpu=FORCE_CPU) # --- Core Functions --- def run_image(*vars): image_path = vars[0] origins = vars[1:(NUM_FACES + 1)] destinations = vars[(NUM_FACES + 1):(NUM_FACES * 2) + 1] thresholds = vars[(NUM_FACES * 2) + 1:-2] face_mode = vars[-2] partial_reface_ratio = vars[-1] disable_similarity = (face_mode in ["Single Face", "Multiple Faces"]) multiple_faces_mode = (face_mode == "Multiple Faces") faces = [{'origin': origins[k] if not multiple_faces_mode else None, 'destination': destinations[k], 'threshold': thresholds[k] if not multiple_faces_mode else 0.0} for k in range(NUM_FACES) if destinations[k] is not None] return refacer.reface_image(image_path, faces, disable_similarity=disable_similarity, multiple_faces_mode=multiple_faces_mode, partial_reface_ratio=partial_reface_ratio) def run_video(*vars): video_path = vars[0] origins = vars[1:(NUM_FACES + 1)] destinations = vars[(NUM_FACES + 1):(NUM_FACES * 2) + 1] thresholds = vars[(NUM_FACES * 2) + 1:-3] preview = vars[-3] face_mode = vars[-2] partial_reface_ratio = vars[-1] disable_similarity = (face_mode in ["Single Face", "Multiple Faces"]) multiple_faces_mode = (face_mode == "Multiple Faces") faces = [{'origin': origins[k] if not multiple_faces_mode else None, 'destination': destinations[k], 'threshold': thresholds[k] if not multiple_faces_mode else 0.0} for k in range(NUM_FACES) if destinations[k] is not None] mp4_path, gif_path = refacer.reface(video_path, faces, preview=preview, disable_similarity=disable_similarity, multiple_faces_mode=multiple_faces_mode, partial_reface_ratio=partial_reface_ratio) return mp4_path, gif_path def load_first_frame(filepath): if filepath is None: return None with imageio.get_reader(filepath) as reader: return reader.get_data(0) def extract_faces_auto(filepath, max_faces=5, isvideo=False): if filepath is None: return [None] * max_faces if isvideo and os.path.getsize(filepath) > 10 * 1024 * 1024: print("Video too large for auto-extract.") return [None] * max_faces try: frame = load_first_frame(filepath) faces = refacer.extract_faces_from_image(frame, max_faces=max_faces) return faces + [None] * (max_faces - len(faces)) except Exception as e: print(f"Could not extract faces: {e}") return [None] * max_faces def toggle_tabs_and_faces(mode): if mode == "Single Face": return [gr.update(visible=(i == 0)) for i in range(NUM_FACES)] + [gr.update(visible=False)] * NUM_FACES elif mode == "Multiple Faces": return [gr.update(visible=True)] * NUM_FACES + [gr.update(visible=False)] * NUM_FACES else: # Faces By Match return [gr.update(visible=True)] * NUM_FACES + [gr.update(visible=True)] * NUM_FACES def handle_tif_preview(filepath): if filepath is None: return None with Image.open(filepath) as img, tempfile.NamedTemporaryFile(suffix=".jpg", delete=False) as temp_file: img.convert('RGB').save(temp_file.name) return temp_file.name # --- UI --- theme = gr.themes.Base(primary_hue="blue", secondary_hue="cyan") with gr.Blocks(theme=theme, title="NeoRefacer - AI Refacer") as demo: with open("icon.png", "rb") as f: icon_data = base64.b64encode(f.read()).decode() gr.Markdown(f'