import os import requests import zipfile import shutil from PyQt6.QtCore import QThread, pyqtSignal # URL de yt-dlp ejecutable directo URL_YTDLP = "https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp.exe" class DependencyChecker(QThread): progress_signal = pyqtSignal(str, int) # (Mensaje, Porcentaje) finished_signal = pyqtSignal() def __init__(self, bin_dir="bin"): super().__init__() self.bin_dir = os.path.abspath(bin_dir) def run(self): os.makedirs(self.bin_dir, exist_ok=True) ytdlp_path = os.path.join(self.bin_dir, "yt-dlp.exe") ffmpeg_path = os.path.join(self.bin_dir, "ffmpeg.exe") ffprobe_path = os.path.join(self.bin_dir, "ffprobe.exe") # Limpiar archivos corruptos o de tamaño inferior a 1 MB self.cleanup_invalid_files([ytdlp_path, ffmpeg_path, ffprobe_path]) # 1. Verificar / Descargar yt-dlp.exe if not os.path.exists(ytdlp_path): self.download_file("yt-dlp.exe", URL_YTDLP, ytdlp_path) # 2. Verificar / Descargar FFmpeg y FFprobe reales desde la API de GitHub if not os.path.exists(ffmpeg_path) or not os.path.exists(ffprobe_path): self.download_ffmpeg_suite() self.progress_signal.emit("Todos los componentes están listos.", 100) self.finished_signal.emit() def cleanup_invalid_files(self, paths): for p in paths: if os.path.exists(p) and os.path.getsize(p) < 1000000: # Menor a ~1 MB try: os.remove(p) except Exception: pass def download_file(self, name, url, save_path): headers = {"User-Agent": "Mozilla/5.0"} response = requests.get(url, headers=headers, stream=True, allow_redirects=True) total_size = int(response.headers.get('content-length', 0)) downloaded = 0 with open(save_path, 'wb') as file: for chunk in response.iter_content(chunk_size=16384): if chunk: file.write(chunk) downloaded += len(chunk) if total_size > 0: percent = int((downloaded / total_size) * 100) self.progress_signal.emit(f"Descargando {name}...", percent) def download_ffmpeg_suite(self): self.progress_signal.emit("Buscando versión de FFmpeg...", 5) headers = {"User-Agent": "Mozilla/5.0"} # Consultar la API de GitHub de GyanD/codexffmpeg para obtener la URL directa del ZIP api_url = "https://api.github.com/repos/GyanD/codexffmpeg/releases/latest" r = requests.get(api_url, headers=headers).json() download_url = None for asset in r.get("assets", []): if asset["name"].endswith("essentials_build.zip") or asset["name"].endswith("full_build.zip"): download_url = asset["browser_download_url"] break if not download_url: # URL de respaldo estática si falla la API download_url = "https://www.gyan.dev/ffmpeg/builds/ffmpeg-release-essentials.zip" zip_path = os.path.join(self.bin_dir, "ffmpeg.zip") self.download_file("FFmpeg Suite (ZIP)", download_url, zip_path) self.progress_signal.emit("Extrayendo FFmpeg y FFprobe...", 90) with zipfile.ZipFile(zip_path, 'r') as zip_ref: for member in zip_ref.namelist(): filename = os.path.basename(member) if filename in ["ffmpeg.exe", "ffprobe.exe"]: target_path = os.path.join(self.bin_dir, filename) with zip_ref.open(member) as source, open(target_path, "wb") as target: shutil.copyfileobj(source, target) if os.path.exists(zip_path): os.remove(zip_path)