Open mijuku233 opened 7 months ago
came here because I just ended up downloading a bunch more, and, yes... it's a pain.
civit link auto downloads png previews and json files. These integrate perfectly with it.
civit link auto downloads png previews and json files. These integrate perfectly with it.
Sorry, could you be more specific? Which node downloads the previews?
So, I ended up writing a janky lil' python script to handle image previews, if anyone here is handy with python and wants something they can kinda just run.
@pythongosssss I'd be happy to upstream this (after making it like, nicer) if you're interested, but I'd need to know what your preference is for activation - like, where should I put the button and how should this be triggered. My immediate thought is to have a checkbox somewhere that enables running on startup or something of that nature.
Also, how do you prefer your PRs? Forks I'm guessing?
Note if anyone plans on using this: You have to either get an api key from civitai and put that where it says REDACTED
or just delete the authorization from the header entirely (which if I understood correctly would mean some models won't allow you to download their data?)
usage: python script.py <path-to-models-dir>
import os
import hashlib
from pathlib import Path
import requests
import sys
import json
def get_file_hash(file_path):
hasher = hashlib.sha256() # Using SHA256 for hashing
with open(file_path, "rb") as file:
chunk = file.read(4096)
while chunk:
hasher.update(chunk)
chunk = file.read(4096)
return hasher.hexdigest()
def get_model_image_url(file_path):
file_hash = get_file_hash(file_path)
api_url = f"https://civitai.com/api/v1/model-versions/by-hash/{file_hash}"
headers = {"Content-Type": "application/json", "Authorization": "Bearer REDACTED"}
response = requests.get(api_url, headers=headers)
try:
return response.json()["images"][0]["url"]
except Exception as e:
print(f"could not establish image url: {e}")
def save_model_preview_image(file_path):
preview_path = file_path.with_suffix(".preview.png")
if Path(preview_path).exists():
print(f"{preview_path} exists. Skipping...")
else:
image_url = get_model_image_url(file_path)
if image_url is not None:
response = requests.get(image_url)
if response.status_code == 200:
with open(preview_path, "wb") as f:
f.write(response.content)
else:
print(f"No image URL; Couldn't save image for {file_path}")
def fetch_and_save_previews(directory):
# Walk through all directories and files in the specified directory
for root, dirs, files in os.walk(directory):
for filename in files:
# Check if the file is a .safetensors file
if filename.endswith(".safetensors"):
file_path = Path(root) / filename
save_model_preview_image(file_path)
if __name__ == "__main__":
file_path = sys.argv[1]
fetch_and_save_previews(file_path)
this is good, yet, I feel like most of this logic already exists, and should be leveraged from here: https://github.com/pythongosssss/ComfyUI-Custom-Scripts/blob/main/py/model_info.py
That way we get the previews, we get the .sha256
files, etc.
EDIT: Sorry, wrong place. Need to recheck, I thought this was all done in python somewhere.
My bad. This all happens in JS here: https://github.com/pythongosssss/ComfyUI-Custom-Scripts/blob/3f2c021e50be2fed3c9d1552ee8dcaae06ad1fe5/web/js/common/modelInfoDialog.js#L211
@pksebben in the short term, this could be just a regular node. Not something that would run often, but loading up an empty workflow with just this one thing would be fine. Another idea for where it could be used is in the ComfyUI Manager as another button there.
@pksebben I made some improvements to the script. Saving/Reading the .sha256
file in order to avoid hashing each model on every run.
import os
import hashlib
from pathlib import Path
import requests
import sys
def get_and_save_file_hash(file_path):
sha256_path = file_path.with_suffix(".sha256")
if Path(sha256_path).exists():
print(f"existing hash found: {sha256_path}")
with open(sha256_path, "r") as file:
return str(file.read()).strip()
print(f"hashing: {file_path}")
hasher = hashlib.sha256() # Using SHA256 for hashing
with open(file_path, "rb") as file:
chunk = file.read(4096)
while chunk:
hasher.update(chunk)
chunk = file.read(4096)
file_hash = str(hasher.hexdigest())
with open(sha256_path, "w") as file:
file.write(file_hash)
return file_hash
def get_model_image_url(file_hash):
api_url = f"https://civitai.com/api/v1/model-versions/by-hash/{file_hash}"
print(f"getting model info from: {api_url}")
headers = {"Content-Type": "application/json", "Authorization": "Bearer REDACTED"}
response = requests.get(api_url, headers=headers)
try:
return response.json()["images"][0]["url"]
except Exception as e:
print(f"could not establish image url: {e}")
def save_model_meta(file_path):
preview_path = file_path.with_suffix(".preview.png")
file_hash = get_and_save_file_hash(file_path)
if Path(preview_path).exists():
print(f"{preview_path} exists. Skipping...")
else:
image_url = get_model_image_url(file_hash)
if image_url is not None:
response = requests.get(image_url)
if response.status_code == 200:
with open(preview_path, "wb") as f:
f.write(response.content)
else:
print(f"No image URL; Couldn't save image for {file_path}")
def fetch_and_save_previews(directory):
# Walk through all directories and files in the specified directory
for root, _, files in os.walk(directory):
for filename in files:
# Check if the file is a .safetensors file
if filename.endswith(".safetensors"):
file_path = Path(root) / filename
print(f"→ {file_path}")
save_model_meta(file_path)
if __name__ == "__main__":
file_path = sys.argv[1]
fetch_and_save_previews(file_path)
Is there a way to set previews for all loras at once? I have too many loras, and setting previews for them one by one is cumbersome and time-consuming.
In addition, when the mouse is hovering over
Autocomplete lora text
, It would be useful to be able to see a preview!