#!/usr/bin/env python3 """Generate data.js metadata for the MiniMax-H3 workflows showcase.""" import json import collections import os REPO_ROOT = r"C:\Users\dragon\Documents\Default Project\workflows_space\space" SRC = r"C:\Users\dragon\Documents\Default Project\workflows_space\workflows" OUT = os.path.join(REPO_ROOT, "data.js") NOISE = { "Reroute", "Note", "MarkdownNote", "PrimitiveStringMultiline", "PrimitiveBoolean", "PrimitiveInt", "easy int", "easy boolean", "easy anythingIndexSwitch", "Group Controller", "get", "set", "ImpactIfNone", "ComfySwitchNode", "PreviewAny", "PreviewAudio", "SeedNode", } def node_types(d): out = [] out.extend(n.get("type") for n in d.get("nodes", [])) for sg in d.get("definitions", {}).get("subgraphs", []): out.extend(n.get("type") for n in sg.get("nodes", [])) return out def widget_strings(nodes): strings = [] for n in nodes: w = n.get("widgets_values") if isinstance(w, list): for v in w: if isinstance(v, str) and len(v) > 3: strings.append(v) elif isinstance(v, list): for x in v: if isinstance(x, str) and len(x) > 3: strings.append(x) return strings def extract_notes(d): notes = [] for n in d.get("nodes", []): t = n.get("type") if t in ("Note", "MarkdownNote"): w = n.get("widgets_values") if isinstance(w, list): for v in w: if isinstance(v, str) and len(v) > 8: notes.append(v) elif isinstance(w, str) and len(w) > 8: notes.append(w) return notes def clean(s): return " ".join(s.split()) def main(): workflows = [] def add(path_in_repo, src_path, title, subtitle, description, features, prompts_map=None): d = json.load(open(src_path, encoding="utf-8")) counts = collections.Counter(node_types(d)) top_level = len(d.get("nodes", [])) total = sum(counts.values()) inventory = [{"type": t, "count": c} for t, c in counts.most_common()] notable = [inv for inv in inventory if not inv["type"].startswith("__")] models = sorted(set(s for s in widget_strings(d.get("nodes", [])) if s.endswith(".safetensors"))) notes = extract_notes(d) notes = [clean(n) for n in notes] notes = [n for n in notes if not n.startswith("The Turbo-LoRA included in this list")] workflows.append({ "file": path_in_repo, "title": title, "subtitle": subtitle, "description": description, "features": features, "topLevelNodes": top_level, "totalNodes": total, "inventory": notable, "models": models, "notes": notes[:5], }) add( "workflows/MiniMax_int8_I2V-javano2609.1.2.json", os.path.join(SRC, "MiniMax_int8_I2V-javano2609.1.2.json"), "Image-to-Video (FLF)", "First-Last-Frame generation with Extend, ControlNet-Union V2V and Latent Upscaler", "Condition the video on the first AND last frames. Built on the INT8 FL2VA model with " "native Block Sparse Attention, Spectrum sampling, Lightx2v/Turbo LoRAs, native Extend, " "Fun ControlNet Union (OpenPose/Canny/Depth) and low-res -> latent upscale -> high-res decode.", ["First + Last Frame", "INT8", "Block Sparse Attention", "Fun ControlNet Union", "Native Extend", "Latent Upscaler", "Spectrum", "Lightx2v LoRA", "Group Bypass"], prompts_map="fl2va", ) add( "workflows/MiniMax_int8_R2V-javano2609.2.2.json", os.path.join(SRC, "MiniMax_int8_R2V-javano2609.2.2.json"), "Reference-to-Video (R2V)", "Reference-guided generation with Ref LoRA, ControlNet-Union V2V, Extend and Upscaler", "Animate from one or more reference images using the R2V Reference LoRA, with Fun " "ControlNet Union video control, native Extend, audio-VAE aware outputs and the Latent " "Upscaler. The most complete workflow in the collection.", ["Reference LoRA", "INT8", "Block Sparse Attention", "Fun ControlNet Union", "Native Extend", "Latent Upscaler", "Spectrum", "Lightx2v LoRA", "Group Bypass"], prompts_map="ref2va", ) add( "workflows/MiniMax_int8_Bridge-javano2609.1.1.json", os.path.join(SRC, "MiniMax_int8_Bridge-javano2609.1.1.json"), "Bridge", "Generate a transition clip between Video A and Video B", "Takes two clips and synthesizes a bridge that connects them: Video A -> generated cut " "-> Video B. Uses the R2V pipeline with Ref LoRA and keeps all clips at the same size.", ["Video A -> Bridge -> Video B", "R2V pipeline", "Ref LoRA", "INT8", "Latent Upscaler"], prompts_map="ref2va", ) add( "workflows/MiniMax_int8_FR-javano2609.1.1.json", os.path.join(SRC, "MiniMax_int8_FR-javano2609.1.1.json"), "Face Refine", "Automatic face detection and refinement pass", "Refines faces in generated video with ComfyUI-H3-FaceRefine. For small faces, raise " "crop_size (e.g. 512-640) at the cost of slower processing.", ["FaceRefine", "Automatic detection", "INT8", "R2V pipeline", "Selectable crop size"], prompts_map="ref2va", ) add( "workflows/MiniMax_int8_TTS-javano2609.1.json", os.path.join(SRC, "MiniMax_int8_TTS-javano2609.1.json"), "Text-to-Speech / Video-to-Audio", "Fast audio-only speech generation, or new background audio for a mute clip", "Generate speech from text or new ambient audio for an existing video. Not a lip-sync " "tool: it produces background sound, leaving the video frames untouched.", ["Audio-only", "TTS", "Video-to-Audio", "INT8", "SpeechLengthCalculator"], None, ) extras_cfg = [ ("extra/MiniMax-Music3-javano2608.1.json", os.path.join(SRC, "extra", "MiniMax-Music3-javano2608.1.json"), "Music 3", "Songs up to 5 minutes from a structured music caption", "MiniMax Music 3 generates complete, stable songs (up to 5 min) from a music " "description with an optional reference audio track.", ["Music generation", "Up to 5 min", "Caption + reference audio"], None), ("extra/MiniMax_int8-Ref2Image-javano2608.2.json", os.path.join(SRC, "extra", "MiniMax_int8-Ref2Image-javano2608.2.json"), "Ref2Image", "Reference-guided single image generation", "INT8 image generation conditioned on a reference image and Ref LoRA, with the Latent " "Upscaler for high-resolution output.", ["Reference image", "INT8", "Ref LoRA", "Latent Upscaler"], None), ] for path_in_repo, src_path, title, subtitle, desc, feats, _pm in extras_cfg: d = json.load(open(src_path, encoding="utf-8")) counts = collections.Counter(node_types(d)) workflows[-1] # keep adding; reuse add() logic below via manual construction workflows.append({ "file": path_in_repo, "title": title, "subtitle": subtitle, "description": desc, "features": feats, "topLevelNodes": len(d.get("nodes", [])), "totalNodes": sum(counts.values()), "inventory": [{"type": t, "count": c} for t, c in counts.most_common()], "models": sorted(set(s for s in widget_strings(d.get("nodes", [])) if s.endswith(".safetensors"))), "notes": [clean(n) for n in extract_notes(d)][:3], }) for w in workflows: w["notes"] = [n for n in w["notes"] if not n.startswith("The Turbo-LoRA")] prompts = {} fl2va = os.path.join(SRC, "llm_system_prompt_for_minimax-h3_fl2va-2608.6.txt") ref2va = os.path.join(SRC, "llm_system_prompt_for_minimax-h3_ref2va-2608.8.txt") with open(fl2va, encoding="utf-8") as f: prompts["fl2va"] = f.read() with open(ref2va, encoding="utf-8") as f: prompts["ref2va"] = f.read() payload = {"prompts": prompts, "workflows": workflows} with open(OUT, "w", encoding="utf-8") as f: f.write("window.WORKFLOW_DATA = ") json.dump(payload, f, ensure_ascii=False, indent=1) f.write(";\n") print("wrote", OUT, "with", len(workflows), "workflows") for w in workflows: print(f" {w['title']:35s} top={w['topLevelNodes']:3d} total={w['totalNodes']:4d} models={len(w['models'])} notes={len(w['notes'])}") if __name__ == "__main__": main()