Spaces:
Running
Running
File size: 5,648 Bytes
6f39470 fbac153 6f39470 7ade725 fbac153 6f39470 fbac153 7ade725 6f39470 fbac153 7ade725 fbac153 6f39470 fbac153 6f39470 fbac153 7ade725 8c30810 7ade725 fbac153 7ade725 fbac153 026557e 7ade725 fbac153 6f39470 7ade725 6f39470 7ade725 6f39470 7ade725 6f39470 fbac153 7ade725 fbac153 6f39470 fbac153 7ade725 6f39470 fbac153 7ade725 6f39470 7ade725 6f39470 fbac153 7ade725 fbac153 7ade725 fbac153 6f39470 4966b41 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
import os
import subprocess
import logging
from typing import Optional
from fastapi import FastAPI, HTTPException
import gradio as gr
# Configuraci贸n de logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
# Directorios y rutas
UPLOAD_DIR = os.path.join(os.getcwd(), "uploads")
FFMPEG_PATH = "./ffmpeg"
# Crear directorios
os.makedirs(UPLOAD_DIR, exist_ok=True)
# Definir formatos de video y audio soportados
VIDEO_FORMATS = ['.mp4', '.avi', '.mov', '.mkv', '.webm', '.flv', '.wmv']
AUDIO_FORMATS = ['.mp3', '.wav', '.aac', '.flac', '.ogg', '.m4a', '.wma']
def detect_media_type(file_path: str) -> str:
"""Detectar si el archivo es de audio o video."""
ext = os.path.splitext(file_path)[1].lower()
if ext in VIDEO_FORMATS:
return 'video'
elif ext in AUDIO_FORMATS:
return 'audio'
else:
return 'unsupported'
def sanitize_filename(filename: str) -> str:
"""Limpiar y validar nombre de archivo para prevenir riesgos de seguridad."""
return ''.join(c for c in filename if c.isalnum() or c in ('.', '_', '-')).rstrip()
def ensure_unique_filename(directory: str, filename: str) -> str:
"""Generar un nombre de archivo 煤nico para evitar sobreescrituras."""
base, ext = os.path.splitext(filename)
counter = 1
new_filename = filename
while os.path.exists(os.path.join(directory, new_filename)):
new_filename = f"{base}_{counter}{ext}"
counter += 1
return new_filename
def make_ffmpeg_executable(ffmpeg_path: str):
"""Asegurar permisos correctos para FFmpeg."""
try:
subprocess.run(["chmod", "+x", ffmpeg_path], check=True)
logger.info(f"Permisos de FFmpeg configurados para {ffmpeg_path}")
except subprocess.CalledProcessError as e:
logger.error(f"Error al configurar permisos de FFmpeg: {e}")
raise
def convert_media(input_file: str, output_dir: str) -> str:
"""Convertir archivos multimedia con configuraciones optimizadas."""
try:
media_type = detect_media_type(input_file)
base_name = os.path.basename(input_file)
# Elegir extensi贸n de salida seg煤n el tipo de medio
output_extension = 'mp4' if media_type == 'video' else 'm4a'
output_filename = ensure_unique_filename(
output_dir,
f"{os.path.splitext(base_name)[0]}_converted.{output_extension}"
)
output_file = os.path.join(output_dir, output_filename)
if media_type == 'video':
# Configuraciones de conversi贸n de video
ffmpeg_command = [
FFMPEG_PATH,
'-i', input_file,
'-vf', 'fps=24', # Cambiar la tasa de fotogramas
'-c:v', 'libx264', # Codificador de video
'-c:a', 'libfdk_aac', # Codificador de audio
'-profile:a', 'aac_he_v2', # Perfil de audio
'-crf', '28', # Tasa de compresi贸n
'-b:a', '32k', # Tasa de bits de audio
'-preset', 'slow', # Preajuste de codificaci贸n
'-movflags', '+faststart', # Web optimization
output_file
]
elif media_type == 'audio':
# Configuraciones de conversi贸n de audio
ffmpeg_command = [
FFMPEG_PATH,
'-i', input_file,
'-vn', # Ignorar video
'-c:a', 'libfdk_aac', # Codificador AAC para M4A
'-profile:a', 'aac_he_v2',
'-b:a', '32k', # Calidad de audio alta
'-ar', '44100', # Frecuencia de muestreo
output_file
]
else:
raise ValueError("Formato no soportado")
# Ejecutar conversi贸n
result = subprocess.run(
ffmpeg_command,
check=True,
capture_output=True,
text=True
)
logger.info(f"Medio convertido exitosamente: {output_file}")
return output_file
except subprocess.CalledProcessError as e:
logger.error(f"Error de conversi贸n de FFmpeg: {e.stderr}")
raise HTTPException(status_code=500, detail=f"Fallo en la conversi贸n de medio: {e.stderr}")
except Exception as e:
logger.error(f"Error inesperado durante la conversi贸n: {e}")
raise HTTPException(status_code=500, detail="Error inesperado durante la conversi贸n")
def process_media(file_path: str) -> str:
"""Procesar medio completo."""
return convert_media(file_path, UPLOAD_DIR)
def gradio_interface(media: Optional[str]) -> Optional[str]:
"""Interfaz de Gradio para conversi贸n de medios."""
if not media:
raise gr.Error("No se ha subido ning煤n medio. Por favor, sube un archivo.")
try:
converted_media = process_media(media)
return converted_media
except Exception as e:
raise gr.Error(f"Conversi贸n fallida: {str(e)}")
# Asegurar permisos de FFmpeg
make_ffmpeg_executable(FFMPEG_PATH)
# Crear aplicaci贸n FastAPI
app = FastAPI()
# Configurar interfaz de Gradio
iface = gr.Interface(
fn=gradio_interface,
inputs=gr.File(
label="Subir Archivo",
type="filepath"
),
outputs=gr.File(
label="Descargar Archivo Convertido",
type="filepath"
),
title="馃帴馃幍 Convertidor Universal",
description="Convierte videos a MP4 y audios a M4A con configuraciones optimizadas",
theme="huggingface"
)
# Lanzar interfaz de Gradio
if __name__ == "__main__":
iface.launch(share=True) |