Skip to content

About

Check sampled frame drift in AI videos with a local Python CLI and reproducible examples.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Camera Motion Language

Check unwanted motion in AI video before you publish.

A local Python CLI and optional agent skill for creators checking image-to-video clips. Measure a global feature-motion proxy, flag clips above your threshold, and send intentional camera moves for review. Runs on your own video files; no API key, GPU, or Hermes installation is needed for the CLI.

繁體中文 · Agent skill · Synthetic examples · Automation contract · Evaluation results · Release candidate

Your intent What the CLI does Next step
Keep the shot static PASS or FAIL against an 8% default threshold Review the actual subject and framing before publishing
Make an intentional pan / tilt / dolly NEEDS_REVIEW, with the measured motion Confirm the move matches your shot plan
Video cannot be measured reliably NEEDS_REVIEW, exit 2 Inspect the file or use a visual review

The metric tracks global feature motion, so a moving subject can trigger a false alarm. It does not detect faces, prove subject containment, stabilize footage, or generate video. The 8% default is a project policy, not a validated universal quality threshold.

Try the included demo

Install Python 3.10 or newer and Git. From a terminal:

git clone https://github.com/leonininder/camera-motion-language.git
cd camera-motion-language
python -m venv .venv

Windows PowerShell:

.\.venv\Scripts\python.exe -m pip install -r requirements.txt
.\.venv\Scripts\python.exe scripts/measure_frame_drift.py --video golden_clips/static_hold.mp4 --intent static

macOS / Linux:

.venv/bin/python -m pip install -r requirements.txt
.venv/bin/python scripts/measure_frame_drift.py --video golden_clips/static_hold.mp4 --intent static

Expected key lines:

drift_pct_of_width=0.000
status=PASS
gate=ENFORCE

The included clips are synthetic OpenCV fixtures, not real AI-video outputs. The sparse legacy golden_clips/pan_authorized.mp4 now returns NEEDS_REVIEW (exit 2) because its matches fail geometric consistency. Run python scripts/evaluate_regressions.py --output regression-results.json for reproducible textured pan/return-pan FAIL cases. Replace the fixture path with your own MP4 or MOV.

Read the result correctly

Exit code Status Meaning
0 PASS All decoded frames satisfy the measured proxy policy for static intent
0 NEEDS_REVIEW Intentional motion or an opt-in sampled preview is reported, never auto-approved
1 FAIL Static intent exceeds the selected threshold
2 NEEDS_REVIEW or error Insufficient features, unreadable video, invalid options, or missing dependencies

Do not treat exit 0 alone as approval. Check both status and gate when integrating with automation. Low texture, failed frame decoding, or insufficient tracked features cannot produce PASS. Each sampled frame after the first needs at least eight geometrically consistent ORB inliers to the first frame (at least 50% of the best 50 matches), and each adjacent pair needs at least eight flow tracks with forward/backward disagreement of at most one pixel.

The proxy takes the larger of sampled adjacent-frame median optical flow and maximum first-to-sampled-frame ORB displacement, normalized by frame width. Comparing every sample against the first catches movement that returns to its start. ORB mismatches can still inflate results; geometric checks do not identify background versus subject. A PASS is a screening result, not proof of camera lock or identity preservation. Every frame is decoded by default (--all-frames is an explicit alias). --sample-frames N opts into a faster preview that cannot auto-approve; inspect the clip visually. The default full-frame mode reads frames sequentially without retaining the entire video in memory.

Use in a local review pipeline

python scripts/measure_frame_drift.py --video golden_clips/static_hold.mp4 --format json --require-pass --all-frames

--require-pass gives exit 0 only for PASS/ENFORCE. JSON includes a boolean approved, schema version, actual sample indices and evidence counts; errors cannot silently become zero drift. Contract and Python example.

In the stress suite, 24-frame sampling misses an isolated 20% displacement. The preview therefore returns NEEDS_REVIEW even when its sampled metric is low; the default full decode detects the excursion and returns FAIL. The raw sampled_proxy_status is diagnostic only and never grants approval. Four CC BY 3.0 open-animation excerpts all required review under strict geometry; this is a current usability limitation, not a successful real-video benchmark.

Plan the shot before generating

  1. For authored animation, key exact camera values in your animation tool.
  2. For AI-generated video, start with a static camera unless you want one named move.
  3. Keep the subject visible in both endpoint stills; review the entire output afterward.
  4. Run the gate, then inspect flagged clips. Rework the prompt or endpoint images when framing is wrong.

A starter camera line: Static Shot. Stationary camera. Only the person moves. Set stays fixed. This is prompt guidance, not a guarantee that a video model will obey it. See the shot-card schema and example.

Use with an agent

The self-contained skill explains keyed versus sampled camera motion and the review workflow. Read it in any file-capable agent. For Hermes, copy this repository to %LOCALAPPDATA%/hermes/profiles/<profile>/skills/creative/camera-motion-language/ and start a new session. Private operator notes are optional historical context; the CLI and examples work without them.

Verification and contributions

Using the Python interpreter from your virtual environment, run:

python -m unittest discover -s tests -v

Substitute .venv/bin/python or .\.venv\Scripts\python.exe if you have not activated the environment. Tests cover included pass/fail/report-only clips, featureless input, missing files, and invalid CLI settings.

Useful contributions: a redistributable real video with your camera intent, observed framing, CLI output, and permission to publish; a reproducible false positive or false negative; or clearer onboarding. Open an issue with the command, Python/OpenCV versions, and expected result. Never upload private footage without permission.

Project status and license

Early public tool with synthetic regression fixtures. Real AI-video accuracy and subject-retention benchmarks remain open work. An authored open-animation probe and synthetic stress results are available in benchmarks. Earlier internal SOP review scores do not establish public adoption, benchmark accuracy, or independent endorsement. See release-readiness work.

MIT for this repository's original text and scripts. Referenced animation libraries have their own licenses; see sources. The historical brightness-centroid implementation remains in scripts/measure_frame_drift_brightness_legacy.py for comparison.

About

Check sampled frame drift in AI videos with a local Python CLI and reproducible examples.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages