melodix-api / check_requirements.py
GitHub Action
deploy from github actions
440bac0
Raw
History Blame Contribute Delete
10.2 kB
"""
MELODIX - Verificador de Prerrequisitos
Verifica que todos los componentes necesarios estén instalados y configurados.
Uso: python check_requirements.py
"""
import sys
import os
import subprocess
import shutil
from dotenv import load_dotenv
# ==========================================
# CONFIGURACIÓN
# ==========================================
load_dotenv()
COLORS = {
'GREEN': '\033[92m',
'RED': '\033[91m',
'YELLOW': '\033[93m',
'BLUE': '\033[94m',
'END': '\033[0m'
}
def c(text, color):
"""Colorea el texto"""
return f"{COLORS.get(color, '')}{text}{COLORS['END']}"
def check_mark(passed):
"""Retorna ✓ o ✗"""
return c("✓", "GREEN") if passed else c("✗", "RED")
# ==========================================
# VERIFICACIONES
# ==========================================
def check_python():
"""Verifica la versión de Python"""
print("\n" + "=" * 50)
print(" PYTHON")
print("=" * 50)
version = sys.version_info
passed = version.major == 3 and version.minor >= 10
print(f" {check_mark(passed)} Versión: {version.major}.{version.minor}.{version.micro}")
print(f" {'→ Requiere Python 3.10+' if not passed else ''}")
return passed
def check_packages():
"""Verifica los paquetes Python instalados"""
print("\n" + "=" * 50)
print(" PAQUETES PYTHON")
print("=" * 50)
required_packages = {
'fastapi': 'FastAPI',
'uvicorn': 'Uvicorn',
'sqlalchemy': 'SQLAlchemy',
'celery': 'Celery',
'redis': 'Redis',
'librosa': 'Librosa',
'passlib': 'Passlib',
'jose': 'Python-JOSE',
'dotenv': 'python-dotenv',
'pydantic': 'Pydantic',
}
all_installed = True
for package, name in required_packages.items():
try:
__import__(package)
pkg = __import__(package)
version = getattr(pkg, '__version__', 'N/A')
print(f" {check_mark(True)} {name} ({version})")
except ImportError:
print(f" {check_mark(False)} {name} - NO INSTALADO")
all_installed = False
# Verificar demucs
try:
import demucs
print(f" {check_mark(True)} Demucs ({demucs.__version__ if hasattr(demucs, '__version__') else 'N/A'})")
except ImportError:
print(f" {check_mark(False)} Demucs - NO INSTALADO")
all_installed = False
return all_installed
def check_redis():
"""Verifica la conexión a Redis"""
print("\n" + "=" * 50)
print(" REDIS")
print("=" * 50)
try:
import redis
redis_url = os.getenv("REDIS_URL", "redis://localhost:6379/0")
# Normalize ssl_cert_reqs to 'none' if it is 'CERT_NONE' (case-insensitive) to prevent redis-py errors
if redis_url.startswith("rediss://"):
if "ssl_cert_reqs=" in redis_url:
redis_url = redis_url.replace("ssl_cert_reqs=CERT_NONE", "ssl_cert_reqs=none")
redis_url = redis_url.replace("ssl_cert_reqs=cert_none", "ssl_cert_reqs=none")
else:
if "?" in redis_url:
redis_url += "&ssl_cert_reqs=none"
else:
redis_url += "?ssl_cert_reqs=none"
r = redis.from_url(redis_url)
r.ping()
print(f" {check_mark(True)} Conexión: {redis_url}")
print(f" {check_mark(True)} Redis respondiendo: PONG")
return True
except ImportError:
print(f" {check_mark(False)} Paquete redis NO INSTALADO")
return False
except Exception as e:
print(f" {check_mark(False)} Conexión fallida: {e}")
print(f" → ¿Está Redis corriendo? Ejecuta: redis-server")
return False
def check_ffmpeg():
"""Verifica FFmpeg"""
print("\n" + "=" * 50)
print(" FFMPEG")
print("=" * 50)
ffmpeg_path = shutil.which("ffmpeg")
if ffmpeg_path:
try:
result = subprocess.run(
["ffmpeg", "-version"],
capture_output=True,
text=True,
timeout=5
)
version_line = result.stdout.split('\n')[0]
print(f" {check_mark(True)} FFmpeg encontrado: {ffmpeg_path}")
print(f" {check_mark(True)} {version_line}")
return True
except Exception as e:
print(f" {check_mark(False)} Error verificando versión: {e}")
return False
else:
print(f" {check_mark(False)} FFmpeg NO ENCONTRADO en PATH")
print(f" → Instala FFmpeg: https://ffmpeg.org/download.html")
print(f" → O usa Chocolatey: choco install ffmpeg")
return False
def check_demucs_models():
"""Verifica los modelos de Demucs"""
print("\n" + "=" * 50)
print(" MODELOS DEMUCS")
print("=" * 50)
# Los modelos se descargan automáticamente la primera vez
# Solo verificamos si existe el directorio de caché
cache_dir = os.path.expanduser("~/.cache/huggingface/hub")
if os.path.exists(cache_dir):
models = [d for d in os.listdir(cache_dir) if d.startswith('models--facebook--demucs')]
if models:
print(f" {check_mark(True)} Modelos en caché: {len(models)} encontrado(s)")
for m in models:
print(f" - {m}")
return True
else:
print(f" {check_mark(True)} Caché listo (modelos se descargarán la primera vez)")
return True
else:
print(f" {check_mark(True)} Los modelos se descargarán automáticamente")
return True
def check_directories():
"""Verifica los directorios necesarios"""
print("\n" + "=" * 50)
print(" DIRECTORIOS")
print("=" * 50)
base_dir = os.getenv("BASE_DIR", os.path.dirname(os.path.abspath(__file__)))
dirs_to_check = [
("BASE_DIR", base_dir),
("UPLOADS_DIR", os.getenv("UPLOADS_DIR", os.path.join(base_dir, "uploads"))),
("PROCESSED_DIR", os.getenv("PROCESSED_DIR", os.path.join(base_dir, "processed"))),
("LOGS_DIR", os.path.join(base_dir, "logs")),
]
all_ok = True
for name, path in dirs_to_check:
exists = os.path.exists(path)
writable = os.access(path, os.W_OK) if exists else False
if exists and writable:
print(f" {check_mark(True)} {name}: {path}")
elif exists:
print(f" {check_mark(False)} {name}: {path} (NO ESCRIBIBLE)")
all_ok = False
else:
print(f" {check_mark(False)} {name}: {path} (NO EXISTE)")
all_ok = False
return all_ok
def check_env_file():
"""Verifica el archivo .env"""
print("\n" + "=" * 50)
print(" VARIABLES DE ENTORNO")
print("=" * 50)
env_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), ".env")
if os.path.exists(env_file):
print(f" {check_mark(True)} Archivo .env encontrado")
# Verificar variables críticas
critical_vars = ["SECRET_KEY", "REDIS_URL"]
for var in critical_vars:
value = os.getenv(var)
if value:
print(f" {check_mark(True)} {var}: configurado")
else:
print(f" {check_mark(False)} {var}: NO CONFIGURADO")
return True
else:
print(f" {check_mark(False)} Archivo .env NO ENCONTRADO")
print(f" → Copia .env.example a .env")
return False
def check_gpu():
"""Verifica disponibilidad de GPU CUDA"""
print("\n" + "=" * 50)
print(" GPU / CUDA")
print("=" * 50)
try:
import torch
cuda_available = torch.cuda.is_available()
if cuda_available:
gpu_name = torch.cuda.get_device_name(0)
gpu_memory = torch.cuda.get_device_properties(0).total_memory / (1024**3)
print(f" {check_mark(True)} CUDA disponible: {gpu_name}")
print(f" {check_mark(True)} Memoria GPU: {gpu_memory:.1f} GB")
return True
else:
print(f" {check_mark(False)} CUDA NO disponible")
print(f" → Se usará CPU (más lento)")
print(f" → Para GPU: instala PyTorch con CUDA")
return False
except ImportError:
print(f" {check_mark(False)} PyTorch NO INSTALADO")
print(f" → Demucs lo instalará como dependencia")
return False
except Exception as e:
print(f" {check_mark(False)} Error verificando GPU: {e}")
return False
# ==========================================
# MAIN
# ==========================================
def main():
print(c("\n" + "=" * 60, "BLUE"))
print(c(" MELODIX - VERIFICADOR DE PRERREQUISITOS", "BLUE"))
print(c("=" * 60, "BLUE"))
results = {
"Python": check_python(),
"Paquetes": check_packages(),
"Redis": check_redis(),
"FFmpeg": check_ffmpeg(),
"Demucs": check_demucs_models(),
"Directorios": check_directories(),
".env": check_env_file(),
"GPU": check_gpu(),
}
# ==========================================
# RESUMEN FINAL
# ==========================================
print("\n" + "=" * 60)
print(c(" RESUMEN", "BLUE"))
print("=" * 60)
passed = sum(1 for v in results.values() if v)
total = len(results)
for name, result in results.items():
status = c("✓ PASS", "GREEN") if result else c("✗ FAIL", "RED")
print(f" {status} - {name}")
print("\n" + "-" * 60)
if passed == total:
print(c(" ¡TODO LISTO! Puedes iniciar Melodix", "GREEN"))
print(c(" Ejecuta: iniciar_melodix.bat", "GREEN"))
else:
print(c(f" ATENCIÓN: {total - passed} verificación(es) fallida(s)", "YELLOW"))
print(c(" Revisa los errores arriba y corrígelos antes de iniciar", "YELLOW"))
print("=" * 60 + "\n")
return 0 if passed == total else 1
if __name__ == "__main__":
sys.exit(main())