Two stdlib-only wrapper ops around the VIDGOD stack (gitea monster/vidgod): click-to-cutout (SAM2.1+MatAnyone -> ProRes 4444 alpha) and clip-library indexing (PySceneDetect + mlx-whisper). They shell out to ~/Documents/VIDGOD bin CLIs, which carry their own venvs — no MODELBEAST venv or install script. New optional manifest field requires_path: gates the LOCAL node on a path existing (expanduser), so ops whose stack lives only on some boxes are not grabbed by the primary. Remote nodes stay allowlist-gated via nodes.json (vidgod_* allowlisted on m1/ultra only for now). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
59 lines
2.0 KiB
Python
59 lines
2.0 KiB
Python
"""vidgod_roto — MODELBEAST wrapper around VIDGOD's vg-roto.
|
|
|
|
Stdlib-only on purpose: runs under the node's system python3 and shells out to
|
|
~/Documents/VIDGOD/bin/vg-roto, which brings its own venv (SAM 2.1 + MatAnyone).
|
|
"""
|
|
import argparse
|
|
import json
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
ap = argparse.ArgumentParser()
|
|
ap.add_argument("--input", required=True)
|
|
ap.add_argument("--outdir", required=True)
|
|
ap.add_argument("--params", default="{}")
|
|
args = ap.parse_args()
|
|
p = json.loads(args.params)
|
|
|
|
vg_roto = Path.home() / "Documents/VIDGOD/bin/vg-roto"
|
|
if not vg_roto.exists():
|
|
sys.exit("VIDGOD not installed on this node — clone gitea monster/vidgod to "
|
|
"~/Documents/VIDGOD and run setup/setup_venvs.sh")
|
|
|
|
outdir = Path(args.outdir)
|
|
workdir = outdir / "roto"
|
|
cmd = [str(vg_roto), args.input, "--out", str(workdir),
|
|
"--frame", str(int(p.get("frame", 0))),
|
|
"--mode", p.get("mode", "matte"),
|
|
"--max-size", str(int(p.get("max_size", -1)))]
|
|
for pt in str(p.get("points", "")).split(";"):
|
|
if pt.strip():
|
|
cmd += ["--point", pt.strip()]
|
|
for pt in str(p.get("neg_points", "")).split(";"):
|
|
if pt.strip():
|
|
cmd += ["--neg", pt.strip()]
|
|
if str(p.get("box", "")).strip():
|
|
cmd += ["--box", str(p["box"]).strip()]
|
|
|
|
print("+", " ".join(cmd), flush=True)
|
|
subprocess.run(cmd, check=True, stderr=sys.stdout)
|
|
|
|
# vg-roto writes <stem>_{alpha.mov,matte.mov,green.mp4} into workdir; lift them
|
|
# to outdir top-level so the runner registers them as job outputs.
|
|
outputs = []
|
|
for f in sorted(workdir.glob("*_*.m*")):
|
|
dest = outdir / f.name
|
|
shutil.move(str(f), dest)
|
|
outputs.append({"path": f.name, "name": f.name})
|
|
if not outputs:
|
|
sys.exit("vg-roto produced no outputs")
|
|
shutil.rmtree(workdir, ignore_errors=True)
|
|
|
|
(outdir / "result.json").write_text(json.dumps({
|
|
"outputs": outputs,
|
|
"summary": {"mode": p.get("mode", "matte"), "files": [o["name"] for o in outputs]},
|
|
}))
|
|
print("done:", ", ".join(o["name"] for o in outputs), flush=True)
|