In plain words: I film short clips on my phone, and turning them into one publishable reel costs me about two hours — watching everything back, deciding what to keep, writing captions, cutting. That is on top of filming and getting the dogs to look their best. I gave the whole editing half to my agent. Today it took thirty minutes of me reviewing and correcting, across five iterations. Next time I expect ten.
The setup is four small pieces, and the interesting part is which one mattered.
The clips live in iCloud, and my Mac keeps almost none of them: 3 of my last 400 videos were actually on disk. osxphotos fixes that — it downloads exactly the clips a query matches, so "everything from August 7th" arrives in about a minute instead of pulling the whole library down. It also reads Photos' own database, which matters more than it sounds: file timestamps lie. The newest file on my Mac was a clip I had shared with a relative, not the newest thing I filmed.
Then the agent looks at the footage — really looks. Its first attempt sampled three frames per clip and the cut was wrong in a way I could feel but not name: it had used a shot of the puppy refusing to walk as "first steps outside", because from three thumbnails that is what it resembles. Sampling every second and stamping each frame with its timecode changed everything. The best joke in my footage — the puppy chews the leash and lies flat rather than walk — was invisible at three frames per clip and obvious at one frame per second.
Only then, story. Not "which clips are pretty" but what happens: harness on, puppy refuses, outside he changes his mind, and his grown-up version walks over to collect him. Beats get chosen to serve that, and anything that does not serve it is left on disk.
My corrections were all editorial, never technical. Beats were uniformly short, so it read like a slideshow — beats now vary by type and none is under three seconds. Three of nine beats went to putting the harness on; one moment gets one beat. A caption that predicts what you are about to see must land on the cut so you read it and then watch it happen; a caption that comments on what just happened waits for the moment. The closing caption named my town for no reason; it now says "spoiler: in a year he will look like this" over the adult dog, which is both the joke and the thing every buyer actually wants to know.
What is still missing: the Instagram and TikTok description. The reel is done and in my photo library, and I still write that part by hand.
Reproduce this
Prerequisites: macOS with Photos + iCloud; ffmpeg (brew install ffmpeg); Python with Pillow; osxphotos (pip install osxphotos) — first run asks for Photos permission. Optional but useful for watching video generally: the claude-video skill (npx skills add bradautomates/claude-video), install it per-project unless you want it everywhere.
Your agent will need from you: which day, album or favourites to pull; the language for captions; and — the part only you can supply — which proposed story is actually good.
Steps:
- Select and download from Photos by capture date, not file date:
osxphotos export <dir> --only-movies --from-date <ISO> --to-date <ISO> --download-missing --use-photokit. Add--updatewhen re-running into a non-empty folder, or it aborts asking for confirmation. - Build one labelled contact sheet per clip: sample ~1 frame per second, scale to ~240px, tile 3 across, and stamp each tile with its timecode. The agent reads in-points straight off the sheet.
- Have the agent write a moment inventory from those sheets, then a story — before choosing a single beat. Ask for one unexpected turn; footage of animals or children usually contains one.
- Cast beats to the story. Rules that fixed my first drafts: one moment, one beat; nothing under 3 seconds; beat length varies by role (hook ~3s, action 3–4s, ending 4s+); every beat contains a visible change; 20 seconds is 5–7 beats, not 10.
- Render from an edit list (clip, in-point, length, caption, caption delay) so iterating is editing numbers, not redoing work. Scale/crop to 1080×1920, normalise to 30fps before joining, drop the audio, crossfade ~0.4s between beats.
- Captions: if your ffmpeg has no
drawtext, render them as PNG overlays. A per-frame PNG sequence gives a letter-by-letter typing effect and per-caption delays. - Put the result back where you post from:
osxphotos import <file> --album Reelsputs it in Photos and iCloud carries it to the phone.
Verify: the finished file is 1080×1920, has no audio stream (ffprobe shows video only, so the app's music needs no ducking), and appears on your phone in the target album. Then the real test: watch it once without pausing and check that you can read every caption before its shot ends.