Files
novafarma/scripts/generate_full_overnight.py

200 lines
7.5 KiB
Python
Executable File

#!/usr/bin/env python3
"""
🌙 NOČNA GENERACIJA - FULL Asset Set
BREZ NPCs in glavnih karakterjev
Z avtomatskim Git commitom in progress trackingom
"""
import os
import sys
import time
import uuid
import requests
import subprocess
from pathlib import Path
from datetime import datetime
try:
from rembg import remove
from PIL import Image
except ImportError:
os.system("pip3 install --user rembg pillow onnxruntime")
from rembg import remove
from PIL import Image
# Configuration
COMFYUI_URL = "http://127.0.0.1:8000"
OUTPUT_DIR = Path("/Users/davidkotnik/repos/novafarma/assets/images")
REPO_DIR = Path("/Users/davidkotnik/repos/novafarma")
PROGRESS_LOG = REPO_DIR / "generation_progress.log"
STYLE = "2D indie game sprite, cartoon vector style, clean smooth outlines, full body visible, isolated on pure white background"
NEGATIVE = "pixel art, pixelated, 3d render, realistic photo, anime, blurry, watermark, text, green background"
def log(msg):
ts = datetime.now().strftime("%H:%M:%S")
line = f"[{ts}] {msg}"
print(line)
sys.stdout.flush()
with open(PROGRESS_LOG, 'a') as f:
f.write(line + "\n")
def git_commit(file_path, category, name):
try:
rel_path = file_path.relative_to(REPO_DIR)
subprocess.run(["git", "add", str(rel_path)], cwd=REPO_DIR, check=True, capture_output=True)
subprocess.run(["git", "commit", "-m", f"🎨 Generated: {category}/{name}"], cwd=REPO_DIR, capture_output=True)
return True
except:
return False
# Load FULL registry safely
sys.path.insert(0, str(REPO_DIR / "scripts"))
import generate_assets_full
ALL_ASSETS = generate_assets_full.generate_registry()
FILTERED_ASSETS = [a for a in ALL_ASSETS if a['cat'] != 'npcs']
def create_workflow(prompt_text, output_name, size=512):
seed = int(time.time() * 1000) % 2147483647
full_prompt = f"{STYLE}, {prompt_text}"
return {
"1": {"class_type": "CheckpointLoaderSimple", "inputs": {"ckpt_name": "dreamshaper_8.safetensors"}},
"2": {"class_type": "EmptyLatentImage", "inputs": {"width": size, "height": size, "batch_size": 1}},
"3": {"class_type": "CLIPTextEncode", "inputs": {"text": full_prompt, "clip": ["1", 1]}},
"4": {"class_type": "CLIPTextEncode", "inputs": {"text": NEGATIVE, "clip": ["1", 1]}},
"5": {
"class_type": "KSampler",
"inputs": {
"seed": seed, "steps": 30, "cfg": 7.5,
"sampler_name": "euler_ancestral", "scheduler": "karras",
"denoise": 1.0, "model": ["1", 0],
"positive": ["3", 0], "negative": ["4", 0], "latent_image": ["2", 0]
}
},
"6": {"class_type": "VAEDecode", "inputs": {"samples": ["5", 0], "vae": ["1", 2]}},
"7": {"class_type": "SaveImage", "inputs": {"filename_prefix": output_name, "images": ["6", 0]}}
}
def queue_prompt(workflow):
try:
r = requests.post(f"{COMFYUI_URL}/prompt", json={"prompt": workflow, "client_id": f"full_{uuid.uuid4().hex[:8]}"}, timeout=10)
return r.json().get("prompt_id")
except Exception as e:
log(f"❌ Queue error: {e}")
return None
def wait_completion(prompt_id, timeout=120):
start = time.time()
while time.time() < start + timeout:
try:
r = requests.get(f"{COMFYUI_URL}/history/{prompt_id}", timeout=5)
if prompt_id in r.json() and r.json()[prompt_id].get("outputs"):
return True
except:
pass
time.sleep(2)
return False
def download_and_process(prompt_id, output_path):
try:
h = requests.get(f"{COMFYUI_URL}/history/{prompt_id}").json()
for out in h.get(prompt_id, {}).get("outputs", {}).values():
for img in out.get("images", []):
r = requests.get(f"{COMFYUI_URL}/view", params={"filename": img["filename"], "subfolder": img.get("subfolder", ""), "type": "output"})
if r.status_code == 200:
output_path.parent.mkdir(parents=True, exist_ok=True)
from io import BytesIO
transparent_img = remove(Image.open(BytesIO(r.content)))
transparent_img.save(str(output_path), "PNG")
return True
return False
except Exception as e:
log(f"❌ Download error: {e}")
return False
def main():
log("="*70)
log("🌙 DAYTIME GENERATION - FULL Asset Set")
log(" BREZ NPCs in glavnih karakterjev")
log("="*70)
try:
r = requests.get(f"{COMFYUI_URL}/system_stats", timeout=5)
log(f"✅ ComfyUI v{r.json()['system']['comfyui_version']}")
except:
log("❌ ComfyUI not running!")
return
log(f"\n📊 Registry Statistics:")
log(f" Total assets: {len(ALL_ASSETS)}")
log(f" NPCs (excluded): {len([a for a in ALL_ASSETS if a['cat'] == 'npcs'])}")
log(f" FILTERED (to generate): {len(FILTERED_ASSETS)}")
existing = sum(1 for a in FILTERED_ASSETS if (OUTPUT_DIR / a['cat'] / a['file']).exists())
to_generate = len(FILTERED_ASSETS) - existing
log(f"\n📁 File Status:")
log(f" Already exist: {existing}")
log(f" To generate: {to_generate}")
log(f"\n📦 By Category:")
cats = {}
for a in FILTERED_ASSETS:
cats[a['cat']] = cats.get(a['cat'], 0) + 1
for cat, count in sorted(cats.items(), key=lambda x: -x[1]):
existing_cat = sum(1 for a in FILTERED_ASSETS if a['cat'] == cat and (OUTPUT_DIR / a['cat'] / a['file']).exists())
log(f" {cat:20s}: {count:4d} total ({existing_cat} exist, {count-existing_cat} to gen)")
if to_generate == 0:
log("\n✅ All assets already generated!")
return
log(f"\n🚀 Starting generation of {to_generate} assets...")
log(f" ETA: ~{to_generate * 20 / 3600:.1f} hours\n")
success, skip, fail = 0, 0, 0
start_time = time.time()
for i, asset in enumerate(FILTERED_ASSETS, 1):
path = OUTPUT_DIR / asset['cat'] / asset['file']
if path.exists():
skip += 1
if i % 50 == 0:
log(f"[{i}/{len(FILTERED_ASSETS)}] Progress: ✅{success} ⏭️ {skip}{fail}")
continue
log(f"[{i}/{len(FILTERED_ASSETS)}] 🎨 {asset['cat']}/{asset['file'][:40]}")
size = 768 if asset['cat'] == 'bosses' else 512
wf = create_workflow(asset['prompt'], asset['file'].replace('.png', ''), size)
pid = queue_prompt(wf)
if pid and wait_completion(pid) and download_and_process(pid, path):
log(f" ✅ Done")
git_commit(path, asset['cat'], asset['file'])
success += 1
else:
log(f" ❌ FAILED")
fail += 1
if i % 10 == 0:
elapsed = time.time() - start_time
per_asset = elapsed / (success + fail) if (success + fail) > 0 else 20
remaining = per_asset * (to_generate - success - fail)
log(f"\n📊 [{i}/{len(FILTERED_ASSETS)}] ✅{success} ⏭️ {skip}{fail}")
log(f" ⏱️ Elapsed: {elapsed/60:.1f}m | ETA: {remaining/60:.1f}m\n")
elapsed = time.time() - start_time
log("\n" + "="*70)
log("🎨 GENERATION COMPLETE!")
log(f" ✅ Success: {success}")
log(f" ⏭️ Skipped: {skip}")
log(f" ❌ Failed: {fail}")
log(f" ⏱️ Total time: {elapsed/3600:.1f} hours")
log(f" 📁 Output: {OUTPUT_DIR}")
log("="*70)
if __name__ == "__main__":
main()