#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""run_h3_batch.py — 顺序跑完 prompts/h3/batch.json 里的 H3 动态镜头（官方工作流）。

纪律（用户要求）：
  · 官方 MinimaxH3Director 工作流，无加速节点/LoRA
  · 单镜 ≤ 11s（本批次 3–8s）
  · 每镜生成后冷却 90 秒（由 h3_official_shot.py 执行）
特性：断点续跑（已存在的成片跳过）、逐镜日志、失败不中断整批。
用法: python3 run_h3_batch.py [--only S01,S02] [--size 960x544] [--workers 1]
"""
import argparse, json, subprocess, sys, time
from pathlib import Path

ROOT = Path(__file__).resolve().parent
PY = "/home/zyw/Downloads/vlm-env/bin/python"
SEED_BASE = 20260925
LOG = ROOT / "logs" / "h3_batch.log"


def log(msg):
    line = f"[{time.strftime('%m-%d %H:%M:%S')}] {msg}"
    print(line, flush=True)
    with open(LOG, "a", encoding="utf-8") as f:
        f.write(line + "\n")


def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("--only", default=None, help="只跑指定的镜号，逗号分隔")
    ap.add_argument("--size", default="1344x768")
    ap.add_argument("--cooldown", type=int, default=300)
    a = ap.parse_args()

    items = json.load(open(ROOT / "prompts/h3/batch.json", encoding="utf-8"))
    if a.only:
        want = {x.strip() for x in a.only.split(",")}
        items = [i for i in items if i["shot"] in want]

    todo = [i for i in items if not (ROOT / "06-H3片段" / i["shot"] / f"{i['shot']}.mp4").exists()]
    log(f"计划 {len(items)} 镜；待跑 {len(todo)} 镜；尺寸 {a.size}；冷却 {a.cooldown}s")
    ok, fail = 0, []
    for n, it in enumerate(todo, 1):
        sid = it["shot"]
        cmd = [PY, str(ROOT / "h3_official_shot.py"), "--shot", sid,
               "--prompt-file", it["prompt_file"], "--keyframe", it["keyframe"],
               "--size", a.size, "--dur", str(it["dur"]),
               "--seed", str(SEED_BASE + int(sid[1:])), "--task", "r2v",
               "--cooldown", str(a.cooldown)]
        for r in it.get("extra_refs", []):
            cmd += ["--extra-ref", r]
        log(f"({n}/{len(todo)}) 开始 {sid}  dur={it['dur']}s  参考图 {1+len(it.get('extra_refs',[]))} 张")
        t0 = time.time()
        p = subprocess.run(cmd, capture_output=True, text=True)
        dt = (time.time() - t0) / 60
        out = ROOT / "06-H3片段" / sid / f"{sid}.mp4"
        if p.returncode == 0 and out.exists():
            ok += 1
            log(f"({n}/{len(todo)}) ✅ {sid} 完成，用时 {dt:.1f} 分钟")
        else:
            fail.append(sid)
            log(f"({n}/{len(todo)}) ❌ {sid} 失败 rc={p.returncode}，用时 {dt:.1f} 分钟")
            log("   " + (p.stderr or p.stdout)[-400:].replace("\n", " "))
    log(f"批次结束：成功 {ok}，失败 {len(fail)} {fail if fail else ''}")
    return 1 if fail else 0


if __name__ == "__main__":
    sys.exit(main())
