render-checks
Skill9 starsChanged 12 days agoMITView on GitHub
Flicker, z-fighting, shimmer, crawling, pop, glitch, blank frame, frozen frame, hard cut, jump cut, jitter, clipping, intersecting, QA, check a render: use after every render and before posting a draft of a code-rendered video, when someone reports a flicker or pop, or when building a QA gate. Scans for flicker with motion-compensated frame comparison, finds pops, blank frames, stray cuts and camera jitter, audits objects clipping into each other, and makes sure every check can actually fail.
In this repository8 other files it gives its agents.
- animation-principlesSkill
- blocking-firstSkill
- directing-sessionsSkill
- look-and-lightSkill
- renderingSkill
- review-pageSkill
- shot-designSkill
- song-timingSkill
The file
We split this skill into the rules it gives an agent
6 rules. About 0 are common, 6 are distinctive, and 0 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈6
Distinctive · estimate
This author's own choices. Worth a look.
0
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 95
Where a new source starts in a splice,: look at the whole frame at full resolution, old next to new, not only the largest difference.
- Distinctive: line 124
The camera is a solid too: After any camera re-key, check its path stays clear of the set.
- Distinctive: line 136
A FAIL can be the instrument too: When a gate contradicts the movie, check the gate's inputs before reporting.
- Distinctive: line 137
Before a new detector gates anything,: run it on a clean render of the same scene and crop what it flags.
- Distinctive: line 138
Every tool refuses an unknown id: instead of checking nothing.
- Distinctive: line 143
After a fix: the same frames scanned again, with the before and after compared.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Render checks
When to use
On every render and every join, and whenever the creator points at a frame that looks wrong. The quick checks (the blank
scan, the frame count) run before a draft is posted; the rest run right after, and what they find goes into the draft's
known issues (review-page). Everything runs before a render goes into the cut or a master. These find problems. The
fixes are usually in animation-principles, look-and-light or rendering.
Procedure
- Blank scan: black, white, frozen, magenta or missing frames, and the frame count against what was expected.
- Flicker scan (below), then judge each event on its contact sheet.
- Pop scan: spikes in frame-to-frame difference. Each one is a designed snap or a bug; look at every one.
- Cut scan and jitter scan (below).
- Step through consecutive frames around everything flagged, every contact, every entrance and every transition. Crop at 100%. Every-Nth-frame sheets hide strobing.
- Watch it at speed with the song. Numbers don't approve motion; frames and playback do.
- Clipping is audited before rendering (below), then checked in full-resolution stills.
Flicker
Flicker is something that changes for one to three frames and then changes back, without the shot's motion explaining it. In code-rendered film the usual causes are:
- two coplanar surfaces z-fighting (on Apple GPUs it often shows as square tiles switching);
- a decal, print or screen a millimeter off its surface;
- a shader threshold (a halftone, a cut-out, paint coverage) that a tiny camera move tips one way or the other;
- shadow-map or texture aliasing that crawls as the camera moves;
- highlights on thin, far faces glinting on and off;
- something scaled out of a surface from zero depth (
animation-principles, grow out, never through).
The method:
- Line up each frame's neighbors (up to three frames away on both sides) onto it with dense optical flow, so the camera and moving objects are compensated. Analyze at 720 lines (1080 to catch small flicker in a 4K master). Where the flow fails a forward-backward check (occlusions, motion edges, deforming characters), leave those pixels untested rather than flagged. One exception: where only one direction fails and the other passes, the passing one, reversed, can stand in. A contrasting patch that shows for two frames often fools the flow exactly where it starts or ends, and without this fill it hides.
- Test every run of one to three frames. A pixel scores when every frame of the run differs from both the frame
before the run and the frame after it, while those two agree with each other:
score = min over the run of min(d(frame, before), d(frame, after)) − d(before, after). A change that stays (a word appearing, a light switching on, a cut) scores zero, because the frame after agrees with it. A ramp (a fade, moving shading) scores zero, and so does something uncovered. - Measure differences tolerantly, in a perceptual color space (CIELAB): a pixel counts as different only by how far it lies outside the range of colors within one pixel of the same place in the neighbor. Sharp edges, sub-pixel misalignment and compression grain then stay quiet.
- Quiet the motion. Scale scores by 1 / (1 + (speed / 8 px)²), with speed in pixels a frame at 720 lines, so whips (whose motion blur changes length from frame to frame) don't read as flicker. Motion the flow missed (tapping fingers, a thin thing swinging, the outline of something rushing at the lens) also changes and changes back: where the motion reverses, or at motion boundaries, count small displacements as motion, and keep events mostly explained that way out of the report.
- Turn scores into events. Seed on high scores (12 ΔE at 720 lines worked), grow into connected pixels over a lower one (6), and drop specks and one-pixel lines. Group nearby regions within a frame, and across frames with gaps of up to two frames. An event's strength is its summed score per thousandth of the frame, so it reads the same at any resolution. Calibrate the thresholds on a span with a known flicker and on a known-clean span before trusting them.
- Report it so it can be acted on: a mask video (black where the picture is steady, white where it flickers), events ranked by strength with their frames and boxes, and a contact sheet per event (the region over the five frames round its peak, the flagged pixels underneath).
- Judge each event on its sheet. Designed blinks, strobes and sparkles get flagged too.
- Fix the cause, re-render the same frames, scan the same frames again, and compare the two event lists: gone, remaining, new.
For a locked-off shot, the core test (step 2) fits in a few lines. A real scan adds the flow alignment, the tolerance, the motion handling and the events:
import numpy as np
def flicker_scores(frames): # frames: float array (N, H, W, 3)
d = lambda a, b: np.abs(a - b).mean(-1)
score = np.zeros(frames.shape[:3])
for i in range(1, len(frames) - 1):
for run in (1, 2, 3):
if i + run >= len(frames):
break
before, after = frames[i - 1], frames[i + run]
inside = np.min([np.minimum(d(frames[j], before), d(frames[j], after)) for j in range(i, i + run)], axis=0)
score[i:i + run] = np.maximum(score[i:i + run], inside - d(before, after))
return score # high = a change that undoes itself within three framesCommon fixes: move or remove one of two coplanar surfaces; give decals a depth offset; draw grow-outs only once clear of the surface; supersample a stretch whose highlights crawl (light and material tweaks only move the glints); prove a fix with the light or effect turned off before blaming it.
Pops
- Anything that vanishes between two consecutive frames is a pop until you've shown it leaving the frame's edge. In every frame strip, follow each big object from frame to frame and say where it went.
- Where a new source starts in a splice, look at the whole frame at full resolution, old next to new, not only the largest difference.
Hard cuts
A color-histogram jump per frame pair: 16 bins per channel at 160×90, half the L1 distance (0 the same, 1 nothing in common). A one-frame world switch scores high even inside fast motion, where a pixel difference can't tell a cut from a whip. Step through every flagged pair: a fast push through a colored surface can score high too.
h = lambda f: np.concatenate([np.histogram(f[..., c], 16, (0, 256))[0] for c in range(3)]) / f.size
jump = [0.5 * np.abs(h(a) - h(b)).sum() for a, b in zip(small, small[1:])] # small: frames at 160x90Camera jitter
Phase-correlate each pair of consecutive frames (gray, 640×360) for the image's overall shift. Flag any one-second window with no step over 12 px (so not a whip) whose image path is 14 px or more while its net travel is under 35% of the path: the camera wandered and came back instead of moving once to a chosen framing. Confirm each hit against the camera's own path; a big subject crossing the frame can trigger it too.
Clipping
- Place with real oriented boxes (measured extents) and check every pair, plus an explicit list of the world's solids, with margins. Things that turn use the circle they sweep. Things that move are checked over time.
- Thin parts need triangle-against-triangle tests. A lamp's arm crossed a thin window board between its vertices, and a point-in-volume test passed it.
- Measure the depth before calling it a fault. Fingertips resting on keys read as a wide intersection that was 1 mm deep.
- The camera is a solid too. After any camera re-key, check its path stays clear of the set.
- Then look: full-resolution close-up stills of every cluster. One visible intersection makes a whole shot read amateur.
Checks must be able to fail
- Plant a known-bad case and make sure the check fails on it. The plant prints what it planted; "nothing to plant on" is a failed check, never a pass.
- A perfect result is a prompt to check the instrument. A debug flag parsed wrong made both sides of a comparison the same frame, and it read "diff 0.000".
- Count what was compared. A scan that read a deleted file compared zero frames and logged "ok". Expected versus compared must match.
- A FAIL can be the instrument too. When a gate contradicts the movie, check the gate's inputs before reporting.
- Before a new detector gates anything, run it on a clean render of the same scene and crop what it flags.
- Every tool refuses an unknown id instead of checking nothing.
Verify
- The report names every flagged event, what it is (designed or a bug), and the frame you looked at to decide.
- After a fix: the same frames scanned again, with the before and after compared.
- The checks were shown able to fail on this project at least once.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

