Log in
TechniqueBy HypernaturalVersion 1, updated

Contact sheet

hn/python-contact-sheet

Make labelled contact sheets to look at many pictures at once: frames of a video at even steps, every N seconds, at given times or at fractions of its length (each labelled with its time and frame number), one row per take or shot comparing first, middle and last frames, or a folder of stills, renders or a site's scraped images labelled with name and size, plus a px grid for reading boxes and zoom targets off a frame. Use to watch a long recording, find where the action is in a render, compare takes side by side, check stills for baked words, or measure a region.

SKILL.md

Give it a video, several videos, or a set of images; get one labelled sheet to look at instead of dozens of separate frames. Every label is printed by Pillow, so it works whatever the local ffmpeg was built with. For a strip that finds where a take's action starts at a frame's precision, ffmpeg-frame-exact-trim (Picking a late start) is the quicker one-liner; for the frames of a compositor spec rather than a rendered file, take stills with hn4a-compositor and sheet them with images.

Inputs

  • A video (video seeks to each frame it shows, so length costs little; given a still image it sheets that image), several videos for rows, or image files.
  • What you need to see: the whole thing at even steps, given moments, or the first, middle and last frame of each take.

Run it

Write references/contact_sheet.md's script into the job's scripts/ as contact_sheet.py, unchanged:

exec("python", ["scripts/contact_sheet.py", "video", "work/sheets/take1.jpg", "source/take1.mp4", "--every", "6", "--cols", "5"], cwd="<job>")
CommandGivesUse it to
video OUT V [--count 20]20 frames first to last, labelled mm:ss.ss fNsee a clip or a render at a glance
video OUT V --every 6a frame every 6 swatch a long recording; pick moments
video OUT V --at 2.5,8,11.5the frames at those timescheck cues, a scene per time
video OUT V --fractions 0,.33,.66,1frames at fractions of the length, the last one the last framecheck a generated shot's start, middle and end
video OUT V --at 4.2 --cols 1 --width 0 --grid 50one full-size frame with a labelled 50 px gridread a box, a zoom target or four corners off a frame
video OUT shot.png --cols 1 --width 0 --grid 50a still image (a screenshot, a picked still) at full size with the gridread boxes off a screenshot, with no movie made first
rows OUT V1 V2 … [--count 3]one row per video, frames first to last by frame numbercompare takes, models or shots side by side
images OUT I1 I2 … [--cols 4]the images, labelled with name and size, see-through ones over greycheck stills for baked words; review a site's images and logo sizes

--cols and --width (px per tile; 0 keeps the source size) shape the sheet. Write sheets to work/sheets/ and look at every one you make: a sheet is for you to read, not to send.

What you get

A PNG (or a JPEG for a .jpg name), and its size printed. Tiles keep their aspect; labels sit above each tile, frame numbers in yellow on rows.

Tips and traps

  • A seek returns the first frame at or after its time, so a frame taken "at" 0.77 s in 25 fps footage is frame 20 (0.80 s), not 19, and a seek at a clip's very end returns nothing. The script seeks half a frame early and labels the frame it actually shows; times you pass are snapped to the nearest frame.
  • rows picks frames by number, decoding the whole file: exact, but read a long recording with video --every instead.
  • Read boxes off a full-size gridded frame, never a thumbnail: on a screen recording, highlight boxes measured on a contact sheet came out a row too high.
  • See-through images (logos, cutouts) are put on grey, so white and black art both show; the size in the label is the file's own, which is how to tell a 120 px logo from a usable one.
  • Variable-frame-rate screen recordings: the frame number is the nominal one (time × the stream's rate); trust the time.

Check it

Look at the sheet. On a clip with burned-in frame numbers, every tile's label matched the number drawn in its frame.

Workflows that use this skill

FAQs

Make labelled contact sheets to look at many pictures at once: frames of a video at even steps, every N seconds, at given times or at fractions of its length (each labelled with its time and frame number), one row per take or shot comparing first, middle and last frames, or a folder of stills, renders or a site's scraped images labelled with name and size, plus a px grid for reading boxes and zoom targets off a frame. Use to watch a long recording, find where the action is in a render, compare takes side by side, check stills for baked words, or measure a region.

Install Hypernatural Desktop, a free Mac app, and connect it to Claude Code, Codex or Claude Desktop. Then describe the video you want and your agent finds the skill itself, or paste this page's link (https://hypernatural.ai/skill/hn/python-contact-sheet) and it installs hn/python-contact-sheet and follows it.

Nothing. The skill is free and runs with tools on your own Mac, like python, ffmpeg and ffprobe.

Yes. Ask your agent to adjust it for your job, or to save its own version. You can publish your version under your own handle so anyone can install it.

Go make something cool.

Install the app, open your agent, describe the video. That's the whole onboarding.

Sticker HypernaturalSticker BannerSticker TVBoy