Spaces:
Runtime error
Runtime error
| import gradio as gr | |
| from huggingface_hub import hf_hub_download | |
| import os | |
| import time | |
| import torch | |
| import cv2 | |
| import numpy as np | |
| # ================================================================= | |
| # 1. CONFIGURACIÓN Y DESCARGA AUTOMÁTICA DE CHECKPOINTS | |
| # ================================================================= | |
| # Directorio local donde se guardarán los archivos | |
| LOCAL_CHECKPOINT_DIR = "checkpoints" | |
| os.makedirs(LOCAL_CHECKPOINT_DIR, exist_ok=True) | |
| downloaded_paths = {} | |
| # --- LÓGICA DE DESCARGA VERIFICADA (VERSION FINAL) --- | |
| try: | |
| # 1. WAV2LIP PRINCIPAL (Fuente más estable para el modelo) | |
| WAV2LIP_REPO = "Nekochu/Wav2Lip" | |
| WAV2LIP_FILE = "wav2lip_gan.pth" | |
| print(f"-> Descargando {WAV2LIP_FILE} desde {WAV2LIP_REPO}...") | |
| path_wav2lip = hf_hub_download(repo_id=WAV2LIP_REPO, filename=WAV2LIP_FILE, local_dir=LOCAL_CHECKPOINT_DIR, local_dir_use_symlinks=False) | |
| downloaded_paths[WAV2LIP_FILE] = path_wav2lip | |
| print(f"✅ Descarga de {WAV2LIP_FILE} completada.") | |
| # 2. DETECTOR FACIAL SFD (Fuente final verificada para el detector) | |
| SFD_REPO = "face-alignment/s3fd" | |
| SFD_FILE = "s3fd.pth" | |
| print(f"-> Descargando {SFD_FILE} desde {SFD_REPO}...") | |
| path_sfd = hf_hub_download(repo_id=SFD_REPO, filename=SFD_FILE, local_dir=LOCAL_CHECKPOINT_DIR, local_dir_use_symlinks=False) | |
| downloaded_paths[SFD_FILE] = path_sfd | |
| print(f"✅ Descarga de {SFD_FILE} completada.") | |
| print("✅ Descarga de Checkpoints completada. Modelos listos.") | |
| except Exception as e: | |
| print(f"❌ ERROR CRÍTICO EN LA DESCARGA: {e}") | |
| exit(1) | |
| # Rutas de los modelos descargados (Globales para la inferencia) | |
| WAV2LIP_PATH = downloaded_paths[WAV2LIP_FILE] | |
| SFD_PATH = downloaded_paths[SFD_FILE] | |
| # ================================================================= | |
| # 2. MODELO Y FUNCIONES HELPER (¡REQUIERE CÓDIGO EXTERNO!) | |
| # ================================================================= | |
| # ---> NOTA IMPORTANTE: FALTAN FUNCIONES HELPER AQUÍ <--- | |
| # Debes pegar aquí: | |
| # 1. La clase 'Wav2Lip' (definición del modelo). | |
| # 2. Las funciones de utilidad para pre-procesamiento de video/audio (ej. get_smoothened_fpc, face_detect, etc.). | |
| # Estos archivos se encuentran en el repositorio original de Wav2Lip (ver Paso 3). | |
| # --- PLACEHOLDERS DE MODELO --- | |
| def load_wav2lip_model(path): | |
| """Placeholder para cargar el modelo PyTorch.""" | |
| # Aquí iría la lógica real de carga del modelo Wav2Lip. | |
| print(f"Cargando modelo Wav2Lip desde: {path}") | |
| # model = Wav2Lip().to(device) | |
| # model.load_state_dict(torch.load(path)['state_dict']) | |
| # return model | |
| return "Wav2Lip_Instance" | |
| def execute_inference_pipeline(model, sfd_path, image_path, audio_path, output_path): | |
| """ | |
| Placeholder para la ejecución completa del pipeline de Wav2Lip. | |
| """ | |
| # Aquí se ejecuta la magia de Wav2Lip, usando las rutas de entrada. | |
| print("Inferencia en proceso...") | |
| # Simulación de la creación del archivo de salida | |
| time.sleep(10) # Simulación del tiempo de renderizado en CPU | |
| output_dir = os.path.dirname(output_path) | |
| os.makedirs(output_dir, exist_ok=True) | |
| # Crea un archivo de salida dummy para que Gradio no falle (EN PRODUCCIÓN DEBE SER UN MP4 REAL) | |
| with open(output_path, 'w') as f: | |
| f.write("Dummy video content") | |
| return output_path | |
| # Carga global de modelos | |
| WAV2LIP_MODEL = load_wav2lip_model(WAV2LIP_PATH) | |
| # ================================================================= | |
| # 3. FUNCIÓN PRINCIPAL DEL SERVIDOR (Lógica expuesta por la API) | |
| # ================================================================= | |
| def generar_avatar_wav2lip(imagen_fuente, archivo_audio): | |
| """ | |
| Función que recibe la imagen y el audio, | |
| ejecuta el modelo Wav2Lip y devuelve la ruta al video generado. | |
| """ | |
| # Ruta temporal y única para el archivo de salida | |
| OUTPUT_VIDEO_PATH = os.path.join("results", f"output_{time.time()}.mp4") | |
| print("--- INICIANDO PROCESO WAV2LIP ---") | |
| print(f"Ruta de Salida: {OUTPUT_VIDEO_PATH}") | |
| # Llama a la función de inferencia. | |
| final_video_path = execute_inference_pipeline( | |
| model=WAV2LIP_MODEL, | |
| sfd_path=SFD_PATH, | |
| image_path=imagen_fuente, | |
| audio_path=archivo_audio, | |
| output_path=OUTPUT_VIDEO_PATH | |
| ) | |
| print("--- PROCESO FINALIZADO ---") | |
| return final_video_path | |
| # ================================================================= | |
| # 4. CONFIGURACIÓN DE LA INTERFAZ (UI y API) | |
| # ================================================================= | |
| gr.Interface( | |
| fn=generar_avatar_wav2lip, | |
| inputs=[ | |
| gr.Image(type="filepath", label="Imagen del Avatar (JPG/PNG)"), | |
| gr.Audio(type="filepath", label="Archivo de Audio (MP3/WAV)") | |
| ], | |
| outputs=gr.Video(label="Video Generado"), | |
| title="Wav2Lip en Space CPU (Con Descarga Automática)", | |
| description="Modelo Wav2Lip optimizado para CPU. Recuerda que la inferencia en CPU será lenta." | |
| ).launch() |