import gradio as gr import os import subprocess import time import logging import psutil from pathlib import Path # Configuración de logging logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') logger = logging.getLogger(__name__) # Configuración de rutas FFMPEG_PATH = os.path.join(os.getcwd(), "ffmpeg.exe") UPLOADS_DIR = os.path.join(os.getcwd(), "uploads") # Crear directorio de uploads si no existe os.makedirs(UPLOADS_DIR, exist_ok=True) # Formatos soportados VIDEO_FORMATS = ['.mp4', '.avi', '.mov', '.mkv', '.wmv', '.flv', '.webm', '.m4v'] AUDIO_FORMATS = ['.mp3', '.wav', '.flac', '.aac', '.ogg', '.m4a', '.wma'] SUPPORTED_FORMATS = VIDEO_FORMATS + AUDIO_FORMATS # Presets de compresión COMPRESSION_PRESETS = { "Compresión Rápida": { "video": "-c:v libx264 -preset ultrafast -crf 28", "audio": "-c:a aac -b:a 128k" }, "Compresión Media": { "video": "-c:v libx264 -preset medium -crf 23", "audio": "-c:a aac -b:a 128k" }, "Compresión Alta": { "video": "-c:v libx264 -preset slow -crf 20", "audio": "-c:a aac -b:a 192k" }, "Compresión Máxima": { "video": "-c:v libx264 -preset veryslow -crf 18", "audio": "-c:a aac -b:a 256k" } } def compress_media(file_path, preset="Compresión Alta", progress=gr.Progress()): """Comprimir archivo de media usando FFmpeg""" try: if not os.path.exists(file_path): return None, "Error: Archivo no encontrado" file_ext = Path(file_path).suffix.lower() if file_ext not in SUPPORTED_FORMATS: return None, f"Error: Formato {file_ext} no soportado" # Generar nombre de archivo de salida base_name = Path(file_path).stem output_path = os.path.join(UPLOADS_DIR, f"{base_name}_compressed{file_ext}") # Obtener configuración del preset preset_config = COMPRESSION_PRESETS.get(preset, COMPRESSION_PRESETS["Compresión Alta"]) # Construir comando FFmpeg cmd = [ FFMPEG_PATH, "-i", file_path, "-y", # Sobrescribir archivo de salida ] # Agregar configuración según el tipo de archivo if file_ext in VIDEO_FORMATS: cmd.extend(preset_config["video"].split()) cmd.extend(preset_config["audio"].split()) else: # Audio cmd.extend(preset_config["audio"].split()) cmd.append(output_path) logger.info(f"Ejecutando comando: {' '.join(cmd)}") # Ejecutar FFmpeg process = subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True ) # Simular progreso for i in progress.tqdm(range(100), desc="Comprimiendo..."): time.sleep(0.1) if process.poll() is not None: break stdout, stderr = process.communicate() if process.returncode != 0: logger.error(f"Error en FFmpeg: {stderr}") return None, f"Error durante compresión: {stderr[:200]}" if not os.path.exists(output_path): return None, "Error: No se pudo crear el archivo comprimido" # Calcular ratio de compresión original_size = os.path.getsize(file_path) compressed_size = os.path.getsize(output_path) compression_ratio = (1 - compressed_size / original_size) * 100 logger.info(f"Compresión completada. Ratio: {compression_ratio:.1f}%") return output_path, f"Compresión exitosa! Reducción: {compression_ratio:.1f}%" except Exception as e: logger.error(f"Error en compress_media: {str(e)}") return None, f"Error durante compresión: {str(e)}" def run_app(): """Ejecutar la aplicación Gradio""" # Verificar que FFmpeg existe if not os.path.exists(FFMPEG_PATH): print(f"Error: FFmpeg no encontrado en {FFMPEG_PATH}") return with gr.Blocks(title="Compresor de Video y Audio", theme=gr.themes.Soft()) as iface: gr.Markdown("# 🎬 Compresor de Video y Audio") gr.Markdown("Comprime tus archivos de video y audio de forma eficiente") with gr.Row(): with gr.Column(): file_input = gr.File( label="Seleccionar archivo", file_types=SUPPORTED_FORMATS ) preset_dropdown = gr.Dropdown( choices=list(COMPRESSION_PRESETS.keys()), value="Compresión Alta", label="Nivel de compresión" ) compress_btn = gr.Button("🚀 Comprimir", variant="primary") with gr.Column(): output_file = gr.File(label="Archivo comprimido") status_text = gr.Textbox(label="Estado", interactive=False) # Información sobre formatos soportados gr.Markdown( f"**Formatos soportados:**\n" f"- Video: {', '.join(VIDEO_FORMATS)}\n" f"- Audio: {', '.join(AUDIO_FORMATS)}" ) # Evento de compresión compress_btn.click( fn=compress_media, inputs=[file_input, preset_dropdown], outputs=[output_file, status_text] ) # Lanzar interfaz iface.launch( share=False, server_name="127.0.0.1", server_port=7862, show_error=True, inbrowser=True ) if __name__ == "__main__": run_app()