Communitygithub.com

beachyphotoandfilm-arch/video-skills

Design a unique Instagram cover for each reel in your house style. Reads what the reel is about, writes a short hook headline, picks one of your own photos from a tagged photo library, lays it out like your existing covers, and proofs it in grid view at phone size. Renders locally, never with AI image generation. Can be called by a scheduling skill before reels are scheduled. Trigger on "make covers", "reel covers", "cover photo for this reel", "design the IG covers".

video-skills とは?

video-skills is a Claude Code agent skill that design a unique Instagram cover for each reel in your house style. Reads what the reel is about, writes a short hook headline, picks one of your own photos from a tagged photo library, lays it out like your existing covers, and proofs it in grid view at phone size. Renders locally, never with AI image generation. Can be called by a scheduling skill before reels are scheduled. Trigger on "make covers", "reel covers", "cover photo for this reel", "design the IG covers".

対応✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/beachyphotoandfilm-arch/video-skills/tree/HEAD/skills/reel-covers

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

Reel covers

Every reel gets its own cover. It's built from your real photos and set in your real type, and it keeps the text inside the part Instagram shows on the profile grid.

Config: set your brand here

Edit these once before the first run.

settingwheredefault
accent color--brand in scripts/cover.html#3b82f6
headline font--display-font in scripts/cover.htmlAnton (free, Google Fonts)
subline font.sub in scripts/cover.htmlMontserrat Bold (free)
default sublineyour coverse.g. "from a Home Cook", or none
photo folderphotos_dir in library.json<PATH_TO_YOUR_COVER_PHOTOS>
Canva photo folder (optional)canva_folder in library.json<YOUR_CANVA_FOLDER_ID>
Canva cover master doc (optional)reference for your current style<YOUR_CANVA_COVER_MASTER_DOC_ID>
Canva scratch design (optional)used to export photos out of Canva<YOUR_CANVA_SCRATCH_DESIGN_ID>
cover logCOVER_LOG env var for pick.pydrafts/social/cover-log.json in the project root
where finished covers gostep 8<YOUR_VIDEO_FOLDER>/<Video> YYYY-MM-DD/Covers/
banned wordshooks.md rulesyour list (e.g. an old offer name)

Built for Instagram. The cover can ride on a normal IG + TikTok + Shorts post as the video thumbnail (for example Metricool's videoThumbnailUrl). Only the Instagram grid matters for the design. Never replace a cover a post already has.

Never AI-generate the image. Backgrounds are your photos, and layouts are copied from your covers. The code only arranges them.

Default house style (change to taste)

Reference only your newest covers in your master doc. Older styles you have moved on from don't count.

  • a bright, neutral photo of you with a relevant prop (laptop, camera, phone, product), with plain wall where the text goes
  • the headline in white display font, ALL CAPS every time, centered, 2 or 3 lines, fairly small
  • an optional subline in Montserrat Bold, normal upper and lowercase
  • default: no shadow, no outline, no band or darkening behind the text, no accent-colored text
  • no labels, no slanted type, no script or cursive fonts, no big-number or series layouts
  • the only extra: a plain accent-colored hand-drawn arrow, now and then
  • nothing under the reel icon: Instagram's grid puts it in the top-right corner of every tile. render.mjs warns if anything sits at x over 760 and y under 540.

Headline rules, hook types and labels are in hooks.md. Read it before writing a headline.

Files

scripts/cover.htmlthe one layout: headline + optional subline, plus arrow / inset / avatar extras. Brand config at the top.
scripts/render.mjsrenders 1080x1920 JPGs + both proofs, and warns on text outside the safe zone or files over 8MB
scripts/pick.pyshortlists photos by topic, blocks the last 9 used, and prints recent layouts and hook types
library.jsonevery photo, tagged (pose, props, where the empty space is, focus point). Ships with an example; build your own.
cover log (COVER_LOG)every cover shipped. This is what keeps them unique
photos_diryour full-res photos (local only, keep them out of git)

scripts/ needs puppeteer-core (npm i puppeteer-core in scripts/, or symlink scripts/node_modules to another skill's install) plus Google Chrome and ffmpeg. render.mjs points at the default macOS Chrome path; change executablePath if yours differs.

Run it

1. Know the reel. You need each reel's transcript, caption and opening text card. Name the one promise the reel makes.

2. Headline. Pick a hook type that isn't the last cover's type (pick.py prints it). Write 3 or 4 options, 3 to 8 words each, and pick the strongest. It must not repeat the opening text card word for word.

3. Photo.

python3 .claude/skills/reel-covers/scripts/pick.py "<topic words>" --space top

Then look at the top 3 or 4 before choosing (build a contact sheet with ffmpeg). Match the prop to the topic: laptop for email, systems or website; camera or product for gear; you mid-talk for sales and mindset. For customer stories, use an inset or avatar of the customer (with permission).

4. Layout. Not the same as the last cover's (see pick.py). Put the text in the photo's empty space (space), set focus so the face stays clear, and set y so the text block sits between 300 and 1250.

5. Render.

OUT="<work>/covers" node .claude/skills/reel-covers/scripts/render.mjs covers.json
{"covers":[{"id":"3-the-exact-close","img":"<PATH_TO_YOUR_COVER_PHOTOS>/<file>.jpg",
  "data":{"head":"the exact close I use on sales calls","sub":"from a Home Cook","y":560,"headroom":280}}],
 "history":["<last few shipped cover files from the cover log, newest first>"]}

Expand ~ to a real path; render.mjs does not. A non-zero exit means a warning, so fix it before sharing.

6. Check it yourself first. Open _proof.png and _grid-phone.png:

  • Is the headline readable in the grid proof (130px wide)? If not, cut words.
  • Is the face clear of the text in both the full cover and the grid crop?
  • Next to the other covers in the grid, does it look different (photo, layout, text position) but clearly from the same set?

7. Gate. Show the user _grid-phone.png and _proof.png, with each headline and one alternative headline. Ask: "Do these covers stop the scroll?" Swap photos or words on request and re-render. It takes seconds.

8. After approval:

  • Copy each JPG to <YOUR_VIDEO_FOLDER>/<Video> YYYY-MM-DD/Covers/, named like the reel (3. the exact close.jpg).
  • Append one entry per cover to the cover log: {"date":"YYYY-MM-DD","video":"<video-slug>","reel":"3. the exact close","photo":"<file>","layout":"stack","hook_type":"how","head":"the exact close I use on sales calls","file":"<abs path to the Covers jpg>"}
  • Hand the files to your scheduling step, which uploads each one and attaches it to the Instagram post.

Uniqueness rules

  • No photo used in the last 9 covers. pick.py enforces this.
  • Never the same layout or hook type twice in a row.
  • Rotate the subline: none, centered, or offset right and tilted (subdx, subrot).
  • Vary the text position (top, middle, left or right-aligned) based on the photo. Don't always center it at the top.
  • If the library runs thin (every good photo used recently), say so and suggest a new photo session rather than breaking the rule.

Layout lessons

  • The 9:16 crop puts the face high. Most photos are 2:3. Scaled to 1920 tall they lose the sides, not the top, so a face that looks low in the original sits around y 600 to 800. The most common failure is text sitting on the subject's hair. Look at every proof for that before anything else.
  • Fix it with headroom, not by shrinking the text. "headroom": 150-350 pushes the photo down and stretches the plain wall above the subject. It is invisible on plain studio walls. Don't use it on busy outdoor backgrounds (trees and sky smear).
  • Headline size: auto is 104px for 4 words or fewer, 84px for longer, shrinking to fit 3 lines.
  • Drop the subline if it would touch the head. It's texture, not the message.
  • Placing text with the reel icon in mind: either start the block at y 560 or lower (push the photo down with headroom so it clears the head), or keep it high and use align: left, right: 320. Mix both across a batch.
  • A 3:4 grid crop hides nothing above y 240. Keep text starting at 280 or lower (render.mjs warns).

Adding photos

From a local folder: md5-check against photos_dir for dupes, copy in as <name>-<k>__local<MMDD>.jpg, then tag.

From Canva (optional). Canva won't download images out of an uploads folder directly. A working route is a scratch design used only for exports:

  1. list-folder-items on <YOUR_CANVA_FOLDER_ID>, and diff the asset ids against library.json (keep the id in each filename after __).
  2. read-design on <YOUR_CANVA_SCRATCH_DESIGN_ID> with open_transaction, then one edit-design call with an add_page (2400x3600, title = asset id) for each new photo. Read the new page ids, then one call with an insert_fill per page (full page, top 0, left 0). commit.
  3. export-design as PDF, export_quality: pro, then pdfimages -j -f <first> -l <last> -p all.pdf ex/img. The PDF embeds the original JPEGs untouched. JPG export works too, but gives one URL per page.
  4. Save each as <name>__<assetid>.jpg into photos_dir. Several photos can share a Canva name, so the id keeps them apart. Then tag them.

If the same photo was uploaded twice, keep one copy ok and mark the other "ok": false, "note": "duplicate of N", or the no-repeat rule can pick the same picture twice.

Tag each new file in library.json by looking at it:

{"file":"photo_-13.jpg","pose":"smiling at laptop","props":["laptop","desk"],"topics":["email","follow","systems","website"],
 "cap":false,"space":["top"],"focus":"50% 55%","ok":true}

space is where the text can go without touching the face. Mark blurry, dark or awkward shots "ok":false instead of deleting them.

Related

  • video-reels: the opening text card, which the cover headline must not repeat
  • a scheduling skill (optional): uploads the covers and schedules the reels

Individual skills in this repo

This repo contains 7 individual skills — each has its own dedicated page.

beachyphotoandfilm-arch/video-skills

Sync camera footage to a separate lapel or field-recorder track (e.g. Tascam DR-10L and similar) and lay it up in DaVinci Resolve. Stitches the recorder's split files, finds each clip's exact place in the audio by matching words then waveforms, cuts one lapel slice per clip so every later skill works unchanged, checks for clipping, and builds a synced timeline in a new Resolve project. Trigger on "sync the lapel", "sync my audio", "line up the recorder", "I used a lav", or any shoot with a separate audio folder (live talks, events, workshops). Run it before paper-edit or video-reels.

beachyphotoandfilm-arch/video-skills

Turn raw talking-head footage into an assembled rough cut inside DaVinci Resolve. Pulls the clips off your footage drive, transcribes them locally, removes failed takes, restarts, asides and dead air, then creates a new Resolve project with two paper-edit timelines ready for your fine trim. Trigger on "paper edit", "cut my raw footage", "make a rough cut", "clean up this video", or when the user points at a folder of raw camera files for a YouTube video.

beachyphotoandfilm-arch/video-skills

Render finished reels out of DaVinci Resolve, write captions in the creator's voice, attach a custom Instagram cover from reel-covers, and schedule them to Instagram, TikTok and YouTube Shorts through Metricool. Handles the Drive upload hop, collision checks against the existing calendar, and cleanup. Trigger on "schedule the reels", "post these", "put these on the calendar", or after reels are approved.

beachyphotoandfilm-arch/video-skills

Build animated brand overlays (motion graphics) for a talking-head video, timed to the speaker's exact words, plus a DaVinci Resolve import file. House style is in-scene type (text beside and behind the speaker's head) plus diagrams. Transcribes the rough cut locally, picks the moments, renders transparent .mov clips, and writes an FCPXML that drops every clip onto the timeline already in position. Trigger on "make animations for this video", "add overlays/motion graphics", "animate this", "b-roll graphics for my YouTube video", or when the user shares a rough cut and asks for graphics.

beachyphotoandfilm-arch/video-skills

Cut vertical Instagram reels out of a long-form talking-head video, hook first. Picks the strongest standalone moments from the transcript, opens each reel on its punchiest line, builds vertical timelines in DaVinci Resolve framed on the speaker's face with the LUT applied, and finishes them: a hook (a held text card, or a word-by-word "build" hook with punch-in) and burned-look captions on V3; this-or-that reels get product graphics and a comment-keyword CTA card. You trim and render, nothing to import. Trigger on "make reels", "clip this for Instagram", "cut some verticals", or after a YouTube video is cut.

beachyphotoandfilm-arch/video-skills

Design YouTube thumbnails and titles for a talking-head video. Pulls graded full-res frames out of the raw footage, renders brand-styled variants in two proven layouts, and proofs them at phone size where the click actually gets decided. Trigger on "make thumbnails", "thumbnail for this video", "title and thumbnail", or after a video is cut.

beachyphotoandfilm-arch/video-skills

Run the whole YouTube video pipeline end to end, one stage at a time, stopping for the creator's approval at every gate. Paper edit, punch-ins, reels, reel covers, scheduling the reels, overlays, thumbnail and title, then scheduling the long-form video, all through Metricool. Keeps state per video so you can stop anywhere and pick up later. Trigger on "/youtube", "let's do the whole video", "run the video pipeline", "continue the <name> video", or when handed raw footage for a YouTube video.

関連スキル