modelbeast/server/operators/vidgod_index/run.py
John King b7458ec2b0 fix(vidgod_index): sqlite busy timeout for concurrent jobs
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-26 10:29:59 +10:00

62 lines
2.2 KiB
Python

"""vidgod_index — MODELBEAST wrapper around VIDGOD's vg-index.
Stdlib-only: runs under system python3, shells out to ~/Documents/VIDGOD/bin/vg-index
(which brings its own venv). By default the video is copied into
VIDGOD/library/ingest/ first so library entries point at a path that outlives
the job workspace.
"""
import argparse
import json
import shutil
import sqlite3
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 = Path.home() / "Documents/VIDGOD"
vg_index = vg / "bin/vg-index"
if not vg_index.exists():
sys.exit("VIDGOD not installed on this node — clone gitea monster/vidgod to "
"~/Documents/VIDGOD and run setup/setup_venvs.sh")
src = Path(args.input)
if p.get("keep_copy", True):
ingest = vg / "library/ingest"
ingest.mkdir(parents=True, exist_ok=True)
target = ingest / src.name
if not (target.exists() and target.stat().st_size == src.stat().st_size):
shutil.copy2(src, target)
src = target
cmd = [str(vg_index), str(src), "--min-shot", str(p.get("min_shot", 0.5))]
if p.get("no_whisper", False):
cmd.append("--no-whisper")
print("+", " ".join(cmd), flush=True)
subprocess.run(cmd, check=True, stderr=sys.stdout)
db = sqlite3.connect(vg / "library/clips.sqlite", timeout=30)
row = db.execute(
"""SELECT v.id, v.duration, COUNT(DISTINCT s.id), COUNT(DISTINCT g.id)
FROM videos v LEFT JOIN shots s ON s.video_id=v.id
LEFT JOIN segs g ON g.video_id=v.id WHERE v.path=? GROUP BY v.id""",
(str(src),)).fetchone()
if not row:
sys.exit(f"indexing ran but {src} not found in library db")
summary = {"indexed_path": str(src), "duration_s": row[1],
"shots": row[2], "dialogue_segments": row[3],
"search_hint": "vg-find <words> on this node"}
out = Path(args.outdir) / "index_summary.json"
out.write_text(json.dumps(summary, indent=2))
(Path(args.outdir) / "result.json").write_text(json.dumps(
{"outputs": [{"path": "index_summary.json", "name": "index_summary.json"}],
"summary": summary}))
print("done:", json.dumps(summary), flush=True)