matlod's picture
Add recovered fight source and reproducible four-tile canvas examples
42cbd13 verified
Raw History Blame Contribute Delete
2.85 kB
"""Render one API graph on your ComfyUI server and download its result."""
import argparse
import json
from pathlib import Path
import time
import urllib.parse
import urllib.request
import uuid
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('workflow', type=Path)
parser.add_argument('--server', default='http://127.0.0.1:8188')
parser.add_argument('--output', required=True, type=Path)
parser.add_argument('--output-node', help='SaveVideo node ID to download for multi-output graphs')
args = parser.parse_args()
if args.output.exists():
parser.error('output already exists; choose a new filename')
graph = json.loads(args.workflow.read_text())
for node in graph.values():
if node['class_type'] == 'SaveVideo':
node['inputs']['filename_prefix'] += '_' + uuid.uuid4().hex[:12]
def api(path, payload=None):
data = None if payload is None else json.dumps(payload).encode()
req = urllib.request.Request(args.server.rstrip('/') + path, data=data,
headers={'Content-Type': 'application/json'})
with urllib.request.urlopen(req, timeout=60) as response:
return json.load(response)
result = api('/prompt', {'prompt': graph, 'client_id': 'fight_quad_example'})
if result.get('node_errors') or 'prompt_id' not in result:
raise RuntimeError(result)
pid = result['prompt_id']
print('Queued', pid, flush=True)
deadline = time.monotonic() + 7200
while time.monotonic() < deadline:
history = api('/history/' + pid)
if pid not in history:
time.sleep(5)
continue
record = history[pid]
if record['status'].get('status_str') != 'success':
raise RuntimeError(record['status'])
for key, node in graph.items():
if node['class_type'] != 'SaveVideo' or (args.output_node and key != args.output_node):
continue
files = record['outputs'].get(key, {}).get('images', [])
for item in files:
if item.get('type') != 'output':
continue
query = urllib.parse.urlencode({k: item[k] for k in ('filename', 'subfolder', 'type')})
with urllib.request.urlopen(args.server.rstrip('/') + '/view?' + query, timeout=120) as response:
with args.output.open('xb') as output:
while chunk := response.read(1024 * 1024):
output.write(chunk)
print('Saved', args.output)
return
raise RuntimeError('Completed without a SaveVideo output')
raise TimeoutError('Render still pending after two hours; check ComfyUI before resubmitting')
if __name__ == '__main__':
main()