diff --git a/tests/test_cli.py b/tests/test_cli.py index a864e92..5534480 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -377,6 +377,22 @@ class CliTests(unittest.TestCase): json.dumps(existing_record, sort_keys=True) + "\n", encoding="utf-8", ) + (output_dir / "phase_timings.json").write_text( + json.dumps( + { + "schema_version": "phase-timings-v1", + "started_at": "2026-06-17T00:00:00+00:00", + "updated_at": "2026-06-17T00:00:00+00:00", + "phases": { + "source_acquisition_seconds": 7.0, + "inference_seconds": 11.0, + }, + }, + sort_keys=True, + ) + + "\n", + encoding="utf-8", + ) config_path = root / "local_batch.yaml" config_path.write_text( "\n".join( @@ -405,6 +421,14 @@ class CliTests(unittest.TestCase): for line in manifest_path.read_text(encoding="utf-8").splitlines() ] self.assertEqual(records, [existing_record]) + phase_timings = json.loads( + (output_dir / "phase_timings.json").read_text(encoding="utf-8") + ) + self.assertGreaterEqual( + phase_timings["phases"]["source_acquisition_seconds"], + 7.0, + ) + self.assertEqual(phase_timings["phases"]["inference_seconds"], 11.0) def test_until_clips_writes_video_frame_and_clip_manifests_without_vlm(self): with tempfile.TemporaryDirectory() as tmp: diff --git a/video_ai_analysis_poc/cli.py b/video_ai_analysis_poc/cli.py index 742b175..07f705d 100644 --- a/video_ai_analysis_poc/cli.py +++ b/video_ai_analysis_poc/cli.py @@ -33,6 +33,22 @@ def _new_phase_timings() -> dict[str, object]: } +def _load_phase_timings(path: Path, *, resume: bool) -> dict[str, object]: + if not resume or not path.exists(): + return _new_phase_timings() + try: + phase_timings = json.loads(path.read_text(encoding="utf-8")) + except (OSError, json.JSONDecodeError): + return _new_phase_timings() + if not isinstance(phase_timings, dict): + return _new_phase_timings() + if phase_timings.get("schema_version") != "phase-timings-v1": + return _new_phase_timings() + if not isinstance(phase_timings.get("phases"), dict): + phase_timings["phases"] = {} + return phase_timings + + def _write_phase_timings( output_dir: Path, phase_timings: dict[str, object], @@ -104,10 +120,13 @@ def main(argv: Sequence[str] | None = None) -> int: output_dir = Path(config["output"]["dir"]) output_dir.mkdir(parents=True, exist_ok=True) - phase_timings = _new_phase_timings() video_manifest_path = output_dir / "video_manifest.jsonl" resume_enabled = bool(config.get("output", {}).get("resume", False)) + phase_timings = _load_phase_timings( + output_dir / "phase_timings.json", + resume=resume_enabled, + ) records = _load_resume_records( video_manifest_path, resume=resume_enabled,