# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 # # Licensed under the Apache License, Version 2.0 (the "License"). """List smoke-test scenarios + their video paths, and optionally play them. Usage:: # most recent run under outputs/libero_smoke_tests/ python examples/LIBERO/smoke_tests/review_smoke_tests.py # a specific run dir python examples/LIBERO/smoke_tests/review_smoke_tests.py --run-dir outputs/libero_smoke_tests/20260512_120000 # try to open each video one by one (xdg-open / open / ffplay, if available) python examples/LIBERO/smoke_tests/review_smoke_tests.py --open """ from __future__ import annotations import argparse import json from pathlib import Path import shutil import subprocess import sys REPO_ROOT = Path(__file__).resolve().parents[3] DEFAULT_OUTPUT_DIR = REPO_ROOT / "outputs" / "libero_smoke_tests" def _latest_run_dir(output_dir: Path) -> Path | None: if not output_dir.exists(): return None runs = sorted((p for p in output_dir.iterdir() if p.is_dir()), key=lambda p: p.name) return runs[-1] if runs else None def _find_video(scenario_dir: Path) -> Path | None: cand = scenario_dir / "video.mp4" if cand.exists(): return cand vids = sorted(scenario_dir.glob("**/*.mp4")) return vids[0] if vids else None def _open_video(path: Path) -> None: for opener in ("xdg-open", "open", "ffplay"): exe = shutil.which(opener) if exe: args = [exe, str(path)] if opener == "ffplay": args = [exe, "-autoexit", "-loglevel", "error", str(path)] print(f" opening with: {' '.join(args)}") try: subprocess.run(args, check=False) except Exception as e: # noqa: BLE001 print(f" (failed to open: {e})") return print(" no video opener found (xdg-open / open / ffplay). Path printed above.") def main() -> int: ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) ap.add_argument("--output-dir", default=str(DEFAULT_OUTPUT_DIR)) ap.add_argument("--run-dir", default=None, help="Specific / dir.") ap.add_argument("--open", action="store_true", help="Try to play each video, pausing between.") args = ap.parse_args() run_dir = Path(args.run_dir) if args.run_dir else _latest_run_dir(Path(args.output_dir)) if run_dir is None or not run_dir.exists(): print(f"No run directory found under {args.output_dir}. Run run_10_smoke_tests.py first.", file=sys.stderr) return 1 print(f"Run directory: {run_dir}\n") summary_path = run_dir / "summary.json" rows = [] if summary_path.exists(): try: rows = json.loads(summary_path.read_text()).get("scenarios", []) except Exception: rows = [] scenario_dirs = sorted(p for p in run_dir.iterdir() if p.is_dir()) by_id = {r.get("scenario_id"): r for r in rows} for i, sc_dir in enumerate(scenario_dirs, 1): sid = sc_dir.name row = by_id.get(sid, {}) meta = {} mp = sc_dir / "metadata.json" if mp.exists(): try: meta = json.loads(mp.read_text()) except Exception: meta = {} label = row.get("label") or meta.get("label", "?") success = row.get("success", "unknown") video = _find_video(sc_dir) actions = sc_dir / "actions.npy" print(f"[{i:2d}] {sid}") print(f" label={label} success={success} " f"rollout_started={row.get('rollout_started')} " f"actions={'yes' if actions.exists() else 'no'}") env_name = (meta.get("resolved") or {}).get("env_name") or (meta.get("manifest_entry") or {}).get("env_name") if env_name: print(f" env: {env_name}") if row.get("error_if_any"): print(f" error: {row['error_if_any']}") if video: print(f" video: {video}") else: frames = sc_dir / "frames" if frames.exists(): n = len(list(frames.glob('*.png'))) print(f" frames: {frames}/ ({n} png)") else: print(f" video: ") print() if args.open and video: _open_video(video) if i < len(scenario_dirs): try: input(" [enter] for next, Ctrl-C to stop... ") except (EOFError, KeyboardInterrupt): print() break print(f"Summary: {summary_path if summary_path.exists() else '(not found)'}") md = run_dir / "summary.md" if md.exists(): print(f"Markdown summary: {md}") return 0 if __name__ == "__main__": raise SystemExit(main())