python ~/ComfyUI/_install.models.etc.py [path to workflow.json]
installs all missing models and lets you insert civitai or huggingface key if needed
extract workflow json from image using https://absurdity.ai/comfyui/image2workflowjson.html
python ~/ComfyUI/_install.models.etc.py [path to workflow.json]
installs all missing models and lets you insert civitai or huggingface key if needed
extract workflow json from image using https://absurdity.ai/comfyui/image2workflowjson.html
| import json | |
| import os | |
| import sys | |
| import requests | |
| MODELS_BASE_DIR = os.path.join("ComfyUI", "models") | |
| def download_file(url, directory, filename, civitai_key=None, hf_token=None): | |
| target_dir = os.path.join(MODELS_BASE_DIR, directory) | |
| os.makedirs(target_dir, exist_ok=True) | |
| target_path = os.path.join(target_dir, filename) | |
| if os.path.exists(target_path): | |
| print(f"β Already exists: {target_path}") | |
| return | |
| print(f"β¬οΈ Downloading {filename} β {directory}") | |
| headers = {} | |
| if civitai_key and "civitai.com" in url: | |
| headers["Authorization"] = f"Bearer {civitai_key}" | |
| if hf_token and "huggingface.co" in url: | |
| headers["Authorization"] = f"Bearer {hf_token}" | |
| try: | |
| with requests.get(url, stream=True, headers=headers) as r: | |
| r.raise_for_status() | |
| with open(target_path, "wb") as f: | |
| for chunk in r.iter_content(chunk_size=8192): | |
| if chunk: | |
| f.write(chunk) | |
| print(f"β Saved: {target_path}") | |
| except Exception as e: | |
| print(f"β Failed to download {url}: {e}") | |
| def download_models_from_list(models, civitai_key=None, hf_token=None): | |
| for m in models: | |
| name = m.get("name") | |
| url = m.get("url") | |
| directory = m.get("directory", "") | |
| if name and url and directory: | |
| download_file(url, directory, name, civitai_key, hf_token) | |
| else: | |
| print(f"β οΈ Missing info for model: {m}") | |
| def main(workflow_path): | |
| if not os.path.isfile(workflow_path): | |
| print(f"β File not found: {workflow_path}") | |
| sys.exit(1) | |
| with open(workflow_path, "r", encoding="utf-8") as f: | |
| workflow_data = json.load(f) | |
| # Collect all model URLs from root models and node properties | |
| all_urls = set() | |
| for m in workflow_data.get("models", []): | |
| url = m.get("url", "") | |
| if url: | |
| all_urls.add(url) | |
| for node in workflow_data.get("nodes", []): | |
| props = node.get("properties", {}) | |
| models = props.get("models", []) | |
| for m in models: | |
| url = m.get("url", "") | |
| if url: | |
| all_urls.add(url) | |
| civitai_key = None | |
| if any("civitai.com" in url for url in all_urls): | |
| civitai_key = input("π Enter your Civitai API key (or leave empty to skip): ").strip() or None | |
| hf_token = None | |
| if any("huggingface.co" in url for url in all_urls): | |
| hf_token = input("π Enter your Huggingface API token (or leave empty to skip): ").strip() or None | |
| print("β³ Downloading models listed at root...") | |
| download_models_from_list(workflow_data.get("models", []), civitai_key, hf_token) | |
| print("β³ Downloading models listed inside nodes...") | |
| for node in workflow_data.get("nodes", []): | |
| props = node.get("properties", {}) | |
| models = props.get("models", []) | |
| download_models_from_list(models, civitai_key, hf_token) | |
| if __name__ == "__main__": | |
| if len(sys.argv) != 2: | |
| print("Usage: python download_comfyui_models.py <workflow.json>") | |
| sys.exit(1) | |
| main(sys.argv[1]) |
| import json | |
| import os | |
| import sys | |
| import requests | |
| WORKSPACE_MODELS_DIR = "/workspace/models" | |
| COMFYUI_MODELS_DIR = os.path.join("ComfyUI", "models") | |
| def ensure_symlink(src_path, dest_path): | |
| try: | |
| if os.path.islink(dest_path) or os.path.exists(dest_path): | |
| os.remove(dest_path) | |
| os.symlink(os.path.relpath(src_path, os.path.dirname(dest_path)), dest_path) | |
| print(f"π Symlinked {dest_path} β {src_path}") | |
| except Exception as e: | |
| print(f"β Failed to create symlink from {src_path} to {dest_path}: {e}") | |
| def find_model_in_workspace(filename): | |
| for root, _, files in os.walk(WORKSPACE_MODELS_DIR): | |
| if filename in files: | |
| return os.path.join(root, filename) | |
| return None | |
| def download_file(url, subdir, filename, civitai_key=None, hf_token=None): | |
| target_dir = os.path.join(WORKSPACE_MODELS_DIR, subdir) | |
| os.makedirs(target_dir, exist_ok=True) | |
| workspace_path = os.path.join(target_dir, filename) | |
| if not os.path.exists(workspace_path): | |
| print(f"β¬οΈ Downloading {filename} β {target_dir}") | |
| headers = {} | |
| if civitai_key and "civitai.com" in url: | |
| headers["Authorization"] = f"Bearer {civitai_key}" | |
| if hf_token and "huggingface.co" in url: | |
| headers["Authorization"] = f"Bearer {hf_token}" | |
| try: | |
| with requests.get(url, stream=True, headers=headers) as r: | |
| r.raise_for_status() | |
| with open(workspace_path, "wb") as f: | |
| for chunk in r.iter_content(chunk_size=8192): | |
| if chunk: | |
| f.write(chunk) | |
| print(f"β Downloaded to: {workspace_path}") | |
| except Exception as e: | |
| print(f"β Download failed: {url} β {e}") | |
| return None | |
| else: | |
| print(f"β Already exists in workspace: {workspace_path}") | |
| return workspace_path | |
| def ensure_model_symlink(url, subdir, filename, civitai_key=None, hf_token=None): | |
| comfy_dir = os.path.join(COMFYUI_MODELS_DIR, subdir) | |
| os.makedirs(comfy_dir, exist_ok=True) | |
| comfy_path = os.path.join(comfy_dir, filename) | |
| if os.path.exists(comfy_path): | |
| print(f"β ComfyUI path exists: {comfy_path}") | |
| return | |
| existing = find_model_in_workspace(filename) | |
| if not existing: | |
| existing = download_file(url, subdir, filename, civitai_key, hf_token) | |
| if existing: | |
| ensure_symlink(existing, comfy_path) | |
| else: | |
| print(f"β Model not found or downloaded: {filename}") | |
| def download_models_from_list(models, civitai_key=None, hf_token=None): | |
| for m in models: | |
| name = m.get("name") | |
| url = m.get("url") | |
| directory = m.get("directory", "") | |
| if name and url and directory: | |
| ensure_model_symlink(url, directory, name, civitai_key, hf_token) | |
| else: | |
| print(f"β οΈ Missing fields in model entry: {m}") | |
| def main(workflow_path): | |
| if not os.path.isfile(workflow_path): | |
| print(f"β File not found: {workflow_path}") | |
| sys.exit(1) | |
| with open(workflow_path, "r", encoding="utf-8") as f: | |
| workflow_data = json.load(f) | |
| # Get all URLs | |
| all_urls = set() | |
| for m in workflow_data.get("models", []): | |
| url = m.get("url", "") | |
| if url: | |
| all_urls.add(url) | |
| for node in workflow_data.get("nodes", []): | |
| props = node.get("properties", {}) | |
| models = props.get("models", []) | |
| for m in models: | |
| url = m.get("url", "") | |
| if url: | |
| all_urls.add(url) | |
| civitai_key = None | |
| if any("civitai.com" in url for url in all_urls): | |
| civitai_key = input("π Enter your Civitai API key (or leave empty): ").strip() or None | |
| hf_token = None | |
| if any("huggingface.co" in url for url in all_urls): | |
| hf_token = input("π Enter your Huggingface token (or leave empty): ").strip() or None | |
| print("π¦ Processing root models...") | |
| download_models_from_list(workflow_data.get("models", []), civitai_key, hf_token) | |
| print("π¦ Processing node models...") | |
| for node in workflow_data.get("nodes", []): | |
| props = node.get("properties", {}) | |
| models = props.get("models", []) | |
| download_models_from_list(models, civitai_key, hf_token) | |
| if __name__ == "__main__": | |
| if len(sys.argv) != 2: | |
| print("Usage: python download_comfyui_models.py <workflow.json>") | |
| sys.exit(1) | |
| main(sys.argv[1]) |