Spaces:
Running
Running
| """ | |
| 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()) | |