225 lines
8.1 KiB
Python
225 lines
8.1 KiB
Python
"""
|
|
AI Model Downloader for Warlock-Studio
|
|
Descarga automática de modelos AI cuando no están presentes
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import requests
|
|
import zipfile
|
|
from pathlib import Path
|
|
from typing import Optional
|
|
import tempfile
|
|
import shutil
|
|
from tkinter import messagebox
|
|
import threading
|
|
import time
|
|
|
|
class ModelDownloader:
|
|
def __init__(self):
|
|
self.base_path = self._get_base_path()
|
|
self.ai_models_path = os.path.join(self.base_path, "AI-onnx")
|
|
self.download_url = "https://github.com/Ivan-Ayub97/Warlock-Studio/releases/download/v4.0/AI-onnx-models.zip"
|
|
self.backup_urls = [
|
|
"https://sourceforge.net/projects/warlock-studio/files/AI-Models/AI-onnx-models.zip",
|
|
# Agregar más URLs de respaldo aquí
|
|
]
|
|
|
|
def _get_base_path(self) -> str:
|
|
"""Obtener la ruta base de la aplicación"""
|
|
if getattr(sys, '_MEIPASS', None):
|
|
return sys._MEIPASS
|
|
return os.path.dirname(os.path.abspath(__file__))
|
|
|
|
def check_models_exist(self) -> bool:
|
|
"""Verificar si los modelos AI existen"""
|
|
if not os.path.exists(self.ai_models_path):
|
|
return False
|
|
|
|
required_models = [
|
|
"BSRGANx2_fp16.onnx",
|
|
"BSRGANx4_fp16.onnx",
|
|
"GFPGANv1.4.fp16.onnx",
|
|
"IRCNN_Lx1_fp16.onnx",
|
|
"IRCNN_Mx1_fp16.onnx",
|
|
"RIFE_Lite_fp32.onnx",
|
|
"RIFE_fp32.onnx",
|
|
"RealESRGANx4_fp16.onnx",
|
|
"RealESRNetx4_fp16.onnx",
|
|
"RealESR_Animex4_fp16.onnx",
|
|
"RealESR_Gx4_fp16.onnx",
|
|
"RealSRx4_Anime_fp16.onnx",
|
|
"super-resolution-10.onnx"
|
|
]
|
|
|
|
for model in required_models:
|
|
model_path = os.path.join(self.ai_models_path, model)
|
|
if not os.path.exists(model_path):
|
|
return False
|
|
|
|
return True
|
|
|
|
def download_with_progress(self, url: str, destination: str, progress_callback=None) -> bool:
|
|
"""Descargar archivo con barra de progreso"""
|
|
try:
|
|
response = requests.get(url, stream=True)
|
|
response.raise_for_status()
|
|
|
|
total_size = int(response.headers.get('content-length', 0))
|
|
downloaded = 0
|
|
|
|
with open(destination, 'wb') as file:
|
|
for chunk in response.iter_content(chunk_size=8192):
|
|
if chunk:
|
|
file.write(chunk)
|
|
downloaded += len(chunk)
|
|
|
|
if progress_callback and total_size > 0:
|
|
progress = (downloaded / total_size) * 100
|
|
progress_callback(progress, downloaded, total_size)
|
|
|
|
return True
|
|
|
|
except Exception as e:
|
|
print(f"Error downloading from {url}: {str(e)}")
|
|
return False
|
|
|
|
def extract_zip(self, zip_path: str, extract_path: str) -> bool:
|
|
"""Extraer archivo ZIP"""
|
|
try:
|
|
with zipfile.ZipFile(zip_path, 'r') as zip_ref:
|
|
zip_ref.extractall(extract_path)
|
|
return True
|
|
except Exception as e:
|
|
print(f"Error extracting {zip_path}: {str(e)}")
|
|
return False
|
|
|
|
def download_models(self, progress_callback=None) -> bool:
|
|
"""Descargar modelos AI"""
|
|
if self.check_models_exist():
|
|
print("AI models already exist, skipping download")
|
|
return True
|
|
|
|
print("AI models not found, downloading...")
|
|
|
|
# Crear directorio temporal
|
|
with tempfile.TemporaryDirectory() as temp_dir:
|
|
zip_path = os.path.join(temp_dir, "AI-onnx-models.zip")
|
|
|
|
# Intentar descargar desde URL principal
|
|
success = False
|
|
for url in [self.download_url] + self.backup_urls:
|
|
print(f"Attempting download from: {url}")
|
|
if self.download_with_progress(url, zip_path, progress_callback):
|
|
success = True
|
|
break
|
|
else:
|
|
print(f"Failed to download from {url}, trying next URL...")
|
|
|
|
if not success:
|
|
return False
|
|
|
|
# Crear directorio de destino
|
|
os.makedirs(self.ai_models_path, exist_ok=True)
|
|
|
|
# Extraer archivos
|
|
if self.extract_zip(zip_path, self.base_path):
|
|
print("AI models downloaded and extracted successfully")
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
def download_models_async(self, completion_callback=None, progress_callback=None):
|
|
"""Descargar modelos de forma asíncrona"""
|
|
def download_thread():
|
|
success = self.download_models(progress_callback)
|
|
if completion_callback:
|
|
completion_callback(success)
|
|
|
|
thread = threading.Thread(target=download_thread)
|
|
thread.daemon = True
|
|
thread.start()
|
|
return thread
|
|
|
|
# Función para integrar con el código principal
|
|
def ensure_models_available(show_dialog=True) -> bool:
|
|
"""Asegurar que los modelos AI estén disponibles"""
|
|
downloader = ModelDownloader()
|
|
|
|
if downloader.check_models_exist():
|
|
return True
|
|
|
|
if show_dialog:
|
|
from tkinter import messagebox
|
|
result = messagebox.askyesno(
|
|
"AI Models Required",
|
|
"AI models are required but not found. Would you like to download them now?\n\n"
|
|
"This will download approximately 327MB of data.\n\n"
|
|
"Click 'Yes' to download or 'No' to continue without AI functionality."
|
|
)
|
|
|
|
if not result:
|
|
return False
|
|
|
|
# Mostrar ventana de progreso simple
|
|
try:
|
|
import tkinter as tk
|
|
from tkinter import ttk
|
|
|
|
progress_window = tk.Toplevel()
|
|
progress_window.title("Downloading AI Models")
|
|
progress_window.geometry("400x120")
|
|
progress_window.resizable(False, False)
|
|
|
|
progress_label = tk.Label(progress_window, text="Downloading AI models...")
|
|
progress_label.pack(pady=10)
|
|
|
|
progress_bar = ttk.Progressbar(progress_window, length=300, mode='determinate')
|
|
progress_bar.pack(pady=10)
|
|
|
|
status_label = tk.Label(progress_window, text="Starting download...")
|
|
status_label.pack(pady=5)
|
|
|
|
download_complete = [False]
|
|
|
|
def update_progress(percentage, downloaded, total):
|
|
progress_bar['value'] = percentage
|
|
mb_downloaded = downloaded / (1024 * 1024)
|
|
mb_total = total / (1024 * 1024)
|
|
status_label.config(text=f"Downloaded: {mb_downloaded:.1f} MB / {mb_total:.1f} MB")
|
|
progress_window.update()
|
|
|
|
def on_completion(success):
|
|
download_complete[0] = True
|
|
if success:
|
|
status_label.config(text="Download completed successfully!")
|
|
else:
|
|
status_label.config(text="Download failed!")
|
|
progress_window.after(2000, progress_window.destroy)
|
|
|
|
# Iniciar descarga
|
|
downloader.download_models_async(on_completion, update_progress)
|
|
|
|
# Mantener ventana activa hasta completar
|
|
while not download_complete[0]:
|
|
progress_window.update()
|
|
time.sleep(0.1)
|
|
|
|
return download_complete[0]
|
|
|
|
except ImportError:
|
|
# Si no hay tkinter, descargar sin interfaz gráfica
|
|
return downloader.download_models()
|
|
|
|
if __name__ == "__main__":
|
|
downloader = ModelDownloader()
|
|
if not downloader.check_models_exist():
|
|
print("Downloading AI models...")
|
|
success = downloader.download_models()
|
|
if success:
|
|
print("Models downloaded successfully!")
|
|
else:
|
|
print("Failed to download models!")
|
|
else:
|
|
print("AI models already available!")
|