Files
magnus919_agent-skills/ffmpeg/scripts/media-verify
T
Magnus HedemarkandGitHub 3b416dda7e feat: enrich FFmpeg with evidence-driven media editing
Adds evidence-bounded video and podcast editing references, reusable templates, deterministic media workflow helpers, and tests. Closes #438.
2026-09-01 21:20:51 -04:00

55 lines
2.6 KiB
Python
Executable File

#!/usr/bin/env python3
"""Compare two ffprobe JSON documents against basic media criteria."""
import argparse
import json
import sys
from pathlib import Path
def load(path):
try:
return json.loads(Path(path).read_text(encoding="utf-8"))
except (OSError, json.JSONDecodeError) as exc:
raise ValueError(str(exc)) from exc
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("input_probe")
parser.add_argument("output_probe")
parser.add_argument("--duration-tolerance", type=float, default=0.1)
parser.add_argument("--require-subtitles", action="store_true")
args = parser.parse_args()
try:
before = load(args.input_probe)
after = load(args.output_probe)
except ValueError as exc:
print(json.dumps({"ok": False, "status": "invalid_probe", "error": str(exc)}))
return 2
before_streams = before.get("streams", [])
after_streams = after.get("streams", [])
checks = [{"criterion": "output_has_streams", "passed": bool(after_streams)}]
for stream_type in ("video", "audio"):
before_stream = next((s for s in before_streams if s.get("codec_type") == stream_type), None)
after_stream = next((s for s in after_streams if s.get("codec_type") == stream_type), None)
if before_stream:
checks.append({"criterion": f"{stream_type}_stream", "passed": after_stream is not None})
if after_stream and before_stream.get("codec_name") and after_stream.get("codec_name"):
checks.append({"criterion": f"{stream_type}_codec", "passed": before_stream["codec_name"] == after_stream["codec_name"], "input": before_stream["codec_name"], "output": after_stream["codec_name"]})
if args.require_subtitles:
checks.append({"criterion": "subtitle_stream", "passed": any(s.get("codec_type") == "subtitle" for s in after_streams)})
try:
input_duration = float(before.get("format", {}).get("duration"))
output_duration = float(after.get("format", {}).get("duration"))
except (TypeError, ValueError):
input_duration = output_duration = None
if input_duration is not None and output_duration is not None:
checks.append({"criterion": "duration", "passed": abs(input_duration - output_duration) <= args.duration_tolerance, "input": input_duration, "output": output_duration, "tolerance": args.duration_tolerance})
ok = all(check["passed"] for check in checks)
print(json.dumps({"ok": ok, "status": "pass" if ok else "fail", "checks": checks}, indent=2, sort_keys=True))
return 0 if ok else 1
if __name__ == "__main__":
sys.exit(main())