Local mflux operators: seedvr2_upscale + mflux_image_edit (free, ungated)
Two new local image-prep operators through the already-installed mflux 0.18 (no new heavy install, ungated weights): - seedvr2_upscale: mflux-upscale-seedvr2 (ByteDance SeedVR2, MIT) — faithful local upscale, free alternative to cloud fal_upscale - mflux_image_edit: mflux-generate-qwen-edit (Qwen-Image-Edit, Apache-2.0) — local prompt-based image editing, free alternative to fal_image_edit Research verdict on dinov3 (recorded): waiting for Meta approval is the only legitimate path — TRELLIS.2's DiT is trained on DINOv3 ViT-L/16 features so the encoder can't be swapped, and the only ungated mirrors are unauthorized re-uploads. trellis_mac stays blocked on the pending gate. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
1cc0b80d89
commit
f0bac67edb
20
server/operators/mflux_image_edit/manifest.json
Normal file
20
server/operators/mflux_image_edit/manifest.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"id": "mflux_image_edit",
|
||||
"name": "Edit Image (local, Qwen)",
|
||||
"category": "image-prep",
|
||||
"description": "Image + instruction → edited image entirely on this Mac via mflux Qwen-Image-Edit (ungated/Apache-2.0). Free local alternative to fal_image_edit / nano-banana edit — 'remove the sticker', 'make it studio-lit on white', material/lighting changes. First run downloads weights.",
|
||||
"accepts": ["image"],
|
||||
"produces": ["image"],
|
||||
"resources": "gpu",
|
||||
"entry": "run.py",
|
||||
"python": "/Users/m3ultra/Documents/MODELBEAST/venvs/mflux/bin/python",
|
||||
"params_schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"prompt": {"type": "string", "default": "", "description": "Edit instruction (what to change)"},
|
||||
"steps": {"type": "integer", "default": 25, "minimum": 1, "maximum": 50, "description": "Inference steps"},
|
||||
"seed": {"type": "integer", "default": 42, "description": "Random seed"},
|
||||
"guidance": {"type": "number", "default": 4.0, "minimum": 0, "maximum": 10, "description": "Guidance scale"}
|
||||
}
|
||||
}
|
||||
}
|
||||
48
server/operators/mflux_image_edit/run.py
Normal file
48
server/operators/mflux_image_edit/run.py
Normal file
@ -0,0 +1,48 @@
|
||||
import argparse
|
||||
import json
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
ap = argparse.ArgumentParser()
|
||||
ap.add_argument("--input", action="append", default=[])
|
||||
ap.add_argument("--outdir", required=True)
|
||||
ap.add_argument("--params", default="{}")
|
||||
a = ap.parse_args()
|
||||
p = json.loads(a.params)
|
||||
|
||||
if not a.input:
|
||||
print("ERROR: no input image")
|
||||
sys.exit(1)
|
||||
if not p.get("prompt"):
|
||||
print("ERROR: prompt is required — describe the edit you want")
|
||||
sys.exit(1)
|
||||
cli = Path(sys.executable).parent / "mflux-generate-qwen-edit"
|
||||
if not cli.exists():
|
||||
print(f"ERROR: {cli} missing. Run scripts/install_mflux.sh")
|
||||
sys.exit(1)
|
||||
|
||||
src = Path(a.input[0])
|
||||
outdir = Path(a.outdir)
|
||||
out = outdir / f"{src.stem}_edited.png"
|
||||
cmd = [str(cli), "--image-paths", str(src.resolve()),
|
||||
"--prompt", p["prompt"],
|
||||
"--steps", str(p.get("steps", 25)),
|
||||
"--seed", str(p.get("seed", 42)),
|
||||
"--guidance", str(p.get("guidance", 4.0)),
|
||||
"--output", str(out.resolve())]
|
||||
|
||||
print("+", " ".join(cmd), flush=True)
|
||||
print("(first run downloads Qwen-Image-Edit weights)", flush=True)
|
||||
res = subprocess.run(cmd, cwd=str(outdir), stdout=sys.stdout, stderr=subprocess.STDOUT)
|
||||
if res.returncode != 0:
|
||||
sys.exit(res.returncode)
|
||||
|
||||
pngs = sorted(outdir.rglob("*.png"))
|
||||
if not pngs:
|
||||
print("ERROR: no edited image produced")
|
||||
sys.exit(1)
|
||||
img = out if out.exists() else pngs[-1]
|
||||
(outdir / "result.json").write_text(json.dumps(
|
||||
{"outputs": [{"path": img.name, "meta": {"tool": "qwen-image-edit"}}]}))
|
||||
print(f"done: {img.name}", flush=True)
|
||||
20
server/operators/seedvr2_upscale/manifest.json
Normal file
20
server/operators/seedvr2_upscale/manifest.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"id": "seedvr2_upscale",
|
||||
"name": "Upscale (local, SeedVR2)",
|
||||
"category": "image-prep",
|
||||
"description": "Image → faithful upscale entirely on this Mac via mflux SeedVR2 (ByteDance, ungated/MIT). Free local alternative to the cloud fal_upscale. Sharpen thin/low-res inputs before mesh-gen or texture work. First run downloads weights.",
|
||||
"accepts": ["image"],
|
||||
"produces": ["image"],
|
||||
"resources": "gpu",
|
||||
"entry": "run.py",
|
||||
"python": "/Users/m3ultra/Documents/MODELBEAST/venvs/mflux/bin/python",
|
||||
"params_schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"resolution": {"type": "string", "default": "2x", "description": "Scale factor (\"2x\", \"4x\") or shortest-edge pixels (e.g. \"2048\")"},
|
||||
"softness": {"type": "number", "default": 0.0, "minimum": 0.0, "maximum": 1.0, "description": "Detail/denoise strength (0 = faithful, 1 = max)"},
|
||||
"seed": {"type": "integer", "default": 42, "description": "Random seed"},
|
||||
"quantize": {"type": "string", "enum": ["none", "8", "4"], "default": "none", "description": "Quantize to cut memory"}
|
||||
}
|
||||
}
|
||||
}
|
||||
47
server/operators/seedvr2_upscale/run.py
Normal file
47
server/operators/seedvr2_upscale/run.py
Normal file
@ -0,0 +1,47 @@
|
||||
import argparse
|
||||
import json
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
ap = argparse.ArgumentParser()
|
||||
ap.add_argument("--input", action="append", default=[])
|
||||
ap.add_argument("--outdir", required=True)
|
||||
ap.add_argument("--params", default="{}")
|
||||
a = ap.parse_args()
|
||||
p = json.loads(a.params)
|
||||
|
||||
if not a.input:
|
||||
print("ERROR: no input image")
|
||||
sys.exit(1)
|
||||
cli = Path(sys.executable).parent / "mflux-upscale-seedvr2"
|
||||
if not cli.exists():
|
||||
print(f"ERROR: {cli} missing. Run scripts/install_mflux.sh")
|
||||
sys.exit(1)
|
||||
|
||||
src = Path(a.input[0])
|
||||
outdir = Path(a.outdir)
|
||||
out = outdir / f"{src.stem}_upscaled.png"
|
||||
cmd = [str(cli), "-i", str(src.resolve()),
|
||||
"--resolution", str(p.get("resolution", "2x")),
|
||||
"--softness", str(p.get("softness", 0.0)),
|
||||
"--seed", str(p.get("seed", 42)),
|
||||
"--output", str(out.resolve())]
|
||||
quant = str(p.get("quantize", "none"))
|
||||
if quant in ("4", "8"):
|
||||
cmd += ["-q", quant]
|
||||
|
||||
print("+", " ".join(cmd), flush=True)
|
||||
print("(first run downloads SeedVR2 weights)", flush=True)
|
||||
res = subprocess.run(cmd, cwd=str(outdir), stdout=sys.stdout, stderr=subprocess.STDOUT)
|
||||
if res.returncode != 0:
|
||||
sys.exit(res.returncode)
|
||||
|
||||
pngs = sorted(outdir.rglob("*.png"))
|
||||
if not pngs:
|
||||
print("ERROR: no upscaled image produced")
|
||||
sys.exit(1)
|
||||
img = out if out.exists() else pngs[-1]
|
||||
(outdir / "result.json").write_text(json.dumps(
|
||||
{"outputs": [{"path": img.name, "meta": {"tool": "seedvr2", "resolution": p.get("resolution", "2x")}}]}))
|
||||
print(f"done: {img.name}", flush=True)
|
||||
Loading…
Reference in New Issue
Block a user