Files
2025-03-16 15:46:16 -04:00

149 lines
5.7 KiB
Python

import os
import sys
import requests
import json
from pathlib import Path
import itertools
import shutil
import time
# Fix the import path to use relative import
from ..models.sr_model import SuperResolutionModel
def get_models_root_dir():
"""Get the root directory for downloaded SR models"""
# Find the ComfyUI_SuperResolution directory
base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Create downloaded_models directory separate from code
return os.path.join(base_dir, "downloaded_models")
def get_model_path(model_family, scale):
"""Get the path to a model file, ensuring directories exist"""
# Normalize model family name to lowercase for consistency
model_family = model_family.lower()
# Check if model family exists in our configurations
if model_family not in SuperResolutionModel.MODEL_CONFIGS:
print(f"Error: Unknown model family '{model_family}'")
return None
# Get configuration for this model
config = SuperResolutionModel.MODEL_CONFIGS[model_family]
# Convert scale to integer for comparison
scale_int = int(scale.replace('x', ''))
# Check if scale is supported for this model
if scale_int not in config["supported_scales"]:
print(f"Error: Scale {scale} not supported for {model_family}")
return None
# Get model filename from pattern
model_filename = config["filename_pattern"].format(scale=scale_int)
# Create family-specific subdirectory
models_dir = os.path.join(get_models_root_dir(), model_family.upper())
os.makedirs(models_dir, exist_ok=True)
# Return the full path to the model file
return os.path.join(models_dir, model_filename)
def download_model_file(url, destination):
"""Download a model file with progress indication"""
# Skip if model already exists
if os.path.exists(destination):
print(f"Model already exists: {os.path.basename(destination)}")
return True
print(f"Downloading {os.path.basename(destination)}...")
try:
# Download with progress indication for large files
with requests.get(url, stream=True) as r:
r.raise_for_status()
total_size = int(r.headers.get('content-length', 0))
with open(destination, 'wb') as f:
if total_size > 1024*1024: # Show progress for files > 1MB
downloaded = 0
start_time = time.time()
for chunk in r.iter_content(chunk_size=8192):
if chunk:
f.write(chunk)
downloaded += len(chunk)
# Show progress every 1MB
if downloaded % (1024*1024) < 8192:
percent = 100 * downloaded / total_size
elapsed = time.time() - start_time
speed = downloaded / (1024 * 1024 * elapsed) if elapsed > 0 else 0
print(f" {percent:.1f}% ({downloaded/(1024*1024):.1f}MB) - {speed:.1f}MB/s")
else:
# For small files, just download without progress
shutil.copyfileobj(r.raw, f)
print(f"Downloaded {os.path.basename(destination)} successfully!")
return True
except Exception as e:
print(f"Error downloading {url}: {e}")
# Remove partial file if download failed
if os.path.exists(destination):
os.remove(destination)
return False
def download_model(model_family, scale):
"""Download a specific SR model on-demand if it doesn't exist"""
# Normalize model family name to lowercase for consistency
model_family_norm = model_family.lower()
# Check if valid model family
if model_family_norm not in SuperResolutionModel.MODEL_CONFIGS:
print(f"Error: Unknown model family '{model_family}'")
return None
config = SuperResolutionModel.MODEL_CONFIGS[model_family_norm]
# Build model download URL map if we don't have a static one
model_urls = {
"fsrcnn": {
"base_url": "https://raw.githubusercontent.com/ryanontheinside/FSRCNN_Tensorflow/master/models/",
},
"fsrcnn-small": {
"base_url": "https://raw.githubusercontent.com/ryanontheinside/FSRCNN_Tensorflow/master/models/",
},
"edsr": {
"base_url": "https://raw.githubusercontent.com/ryanontheinside/EDSR_Tensorflow/master/models/",
},
"espcn": {
"base_url": "https://raw.githubusercontent.com/ryanontheinside/TF-ESPCN/master/export/",
},
"lapsrn": {
"base_url": "https://raw.githubusercontent.com/ryanontheinside/TF-LapSRN/master/export/",
},
"vdsr": {
"base_url": "https://raw.githubusercontent.com/ryanontheinside/TF-VDSR/master/export/",
}
}
# Check if we have a download URL for this model
if model_family_norm not in model_urls:
print(f"Error: No download URL for model family '{model_family}'")
return None
# Get the model path
model_path = get_model_path(model_family, scale)
if not model_path:
return None
# If model already exists, return its path
if os.path.exists(model_path):
return model_path
# Extract the scale number from the format
scale_int = int(scale.replace('x', ''))
# Get the base URL and create the download URL
base_url = model_urls[model_family_norm]["base_url"]
filename = config["filename_pattern"].format(scale=scale_int)
url = base_url + filename
if download_model_file(url, model_path):
return model_path
else:
return None