agentleFS
shaharshashaharsha/claude-skills/skills/generating-video-clips/SKILL.md

generating-video-clips

Skill6 starsChanged 21 days agoMITView on GitHub

Use when turning a still image, illustration, comic panel or character art into a short animated clip (image-to-video), choosing a video model or provider (Gemini Omni, Veo, Seedance, Kling, ElevenLabs Flows) or hitting their API gates, lip-syncing a character's mouth to existing dialogue audio (Sync, fal.ai, active speaker), or fixing a generated clip with artifacts - duplicated props, a door or a second figure appearing, hands through bodies, glowing eyes, a gesture repeated at the start, a sudden scene cut.

  • Reads credentials

The file

We split this skill into the rules it gives an agent

3 rules. About 0 are common, 1 is distinctive, and 2 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈1

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 2

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Read the sheet: rows are takes, columns are times.

    line 46
  2. Very specific:

    Write shot.json: each line with its start/end in the shot (seconds) and its speaker.

    line 70
  3. Very specific:

    Run lipsync_parts.py split shot.json parts/.

    line 76

≈ “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.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Generating video clips (still to clip, then lip-sync)

Overview

A finished still becomes a 4-9 s clip with an image-to-video model. Then, if a character talks on screen, a lip-sync model re-times their mouth to your own dialogue. You cannot watch the result: judge every clip from extracted frames (scripts/take_sheet.py, and the viewing-videos skill), and let the human have the final say on motion.

Requirements: Python 3 (stdlib only) and ffmpeg/ffprobe. Keys go in env vars: GEMINI_API_KEY (a Google AI Studio key; an image-scoped one works, and GEMINI_IMAGE_API_KEY is read as a fallback) for Omni, and FAL_KEY (the full key exactly as fal shows it) for lip-sync. Never print them.

Choose the model

ModelReached throughUse forNotes
Gemini Omni Flash 1.1 (gemini-omni-1.1-flash)Google Interactions API, AI Studio keyDefault for illustrated, anime and cartoon stills; also worked on a photoreal still (one test)keeps art style and faces; any input aspect (a 2:3 still came back as clean 9:16, so no need to outpaint or crop first); 720p 9:16 or 16:9; synchronous, ~25-35 s per clip; adds its own audio (mute it)
Veo 3.1 / Veo 3.1 FastGemini API, image as the start framephotoreal stillsnot used in our runs; check current docs first
Seedance 2.5ElevenLabs Flows, or ByteDance directlyalternative lookneeded account approval when tried
Any model inside ElevenLabs FlowsElevenLabs APIone key for everythingAPI access needs the Pro plan (402 paid_plan_required) and the key's image_video_generation permission (401 without it); Omni there is app-only

For lip-sync, Sync 3 on fal (fal-ai/sync-lipsync/v3) is the default. It works video-to-video, so it keeps the clip's motion and re-times only the mouth. Comparison and prices: references/providers.md.

Animate a still

python3 <this-skill-dir>/scripts/omni_generate.py jobs.json clips/ [--takes 3] [--only S05]
{"base": "Bring this still to life as it is: same art style, palette, light and layout, and every character keeps the face, hair, build and clothes they have in it. Natural, fluid movement. Nothing written on screen, no speech bubbles, nobody new, one continuous shot. ",
 "jobs": {"S05": {"image": "panels/p05.png",
                  "prompt": "[0-3s] The woman in the red jacket lifts the phone and talks, excited. [3-6s] The friend in the green hoodie leans back on the sofa and laughs. Slow camera push-in."}}}

How to write the prompt (full guide with examples in references/gemini-omni.md):

  • A per-second timeline, one beat per bracket. The clip runs about as long as the timeline.
  • Name people by what they wear, never by name: the model doesn't know who "Dana" is.
  • Say "talks" for anyone who will be lip-synced, so the mouth already moves.
  • Pin what must not change: "the camera stays still", "one single window on the left wall", "exactly ONE hooded figure", "her hands stay flat on the table". Each pin in references/failure-modes.md came from a real failure.

Review every take before using it

python3 <this-skill-dir>/scripts/take_sheet.py sheet review/S09.jpg clips/S09_t1.mp4 clips/S09_t2.mp4 clips/S09_t3.mp4 --times 0.3,1,2,3,4,5,6

Read the sheet: rows are takes, columns are times. Look for props that double, doors or people that appear, hands crossing bodies, faces that drift, and a gesture done twice. Name the exact second of each problem, because the fix depends on where it is.

A hard cut is easy to miss between sampled frames. List them directly; no output means one continuous shot:

ffmpeg -i clips/S09_t1.mp4 -vf "select='gt(scene,0.3)',showinfo" -an -f null - 2>&1 | grep pts_time

Fit a clip to its shot

An edit needs a clip that fills its shot exactly, at the edit's frame rate:

ProblemFix
Bad start (a gesture done before its line, a doubled prop in the first second)Start later: --off 1.5.
Too short after trimmingSlow it with --speed 1.22 (up to ~1.25 reads fine); the last frame is held.
Bad middleSplit the shot: play the first line on a crop that keeps the problem out of frame, then cut back after it.
Unfixable (a door appears, a second person walks in)Regenerate with a pinned prompt, 2-3 takes, and pick on a sheet.

lipsync_parts.py normalize clip.mp4 shot.mp4 --frames N --off S --speed K does the offset, speed, fps, scale (cover and center-crop, never stretch) and last-frame hold in one step, and always returns exactly N frames.

Lip-sync dialogue

  1. Normalize the clip to the shot: python3 <this-skill-dir>/scripts/lipsync_parts.py normalize clip.mp4 shot.mp4 --frames 132 --off 1.5 --speed 1.22.
  2. Split at line boundaries so each part has one speaker.
    • Write shot.json: each line with its start/end in the shot (seconds) and its speaker; frames equals the --frames you normalized to. Add "skip": true for a speaker seen from behind, off screen, or a crowd shout:
      {"id": "S05", "video": "shot.mp4", "fps": 24, "frames": 132,
       "lines": [{"id": "05-1", "audio": "lines/05-1.mp3", "start": 0.72, "end": 2.31, "speaker": "maya"},
                 {"id": "05-2", "audio": "lines/05-2.mp3", "start": 2.43, "end": 4.10, "speaker": "ido"}]}
    • Run lipsync_parts.py split shot.json parts/. Besides the parts it writes parts/S05_lipsync_jobs.json: one entry per non-skip part, with absolute paths, out already named the way join expects (synced/S05_<k>.mp4), and face: null.
  3. Point at the speaker in each part, and write it into that jobs file as "face": "x,y@<mid>" (mid is in each entry).
    • Pick a pixel on their face on the part's middle frame.
    • Confirm it: take_sheet.py point parts/S05_1.mp4 check.jpg --frame 30 --xy 410,560, then read the image.
    • Face detectors are unreliable on drawn faces, so pick and confirm by eye. Leave null only when one face is visible.
  4. Sync: lipsync_fal.py --jobs parts/S05_lipsync_jobs.json. Expect ~$0.13 per second and ~70-150 s per part; 6 run in parallel. Existing outputs are skipped. To redo one part after correcting its face, run that part alone: lipsync_fal.py parts/S05_1.mp4 parts/S05_1.wav synced/S05_1.mp4 --face 410,560@30 --force (--force with --jobs would redo every part).
  5. Join: lipsync_parts.py join parts/S05_plan.json synced/ final/S05.mp4. Each part is forced to its exact frame count, skipped parts keep their original frames, a part with no synced file is reported (--strict makes that an error), and the total frame count is checked.

Details, model choice and failure cases: references/lipsync.md.

Costs and times (measured 2026-10)

StepCountCostTime
Omni clipper second of output video (a 6 s clip is ~$0.60; plan ~1.5 calls per shot for retakes)~$0.10~30 s per call, 4 in parallel
Sync 3 lip-syncper second of output (a part is typically 3-6 s)~$0.13~70-150 s per part, 6 in parallel

Common mistakes

MistakeResultFix
Naming characters in the video promptthe wrong person movesdescribe them by clothes
Keeping Omni's audioinvented voices and music under your dialoguemute it (-an)
Using a take without a sheetdoubled props and new doors shipsheet every take
Re-rolling the whole clip for a bad first secondnew problems elsewhereoffset plus slow-down
Lip-syncing a whole two-speaker shotone mouth moves for both linessplit at line boundaries, one speaker per part
Letting the model pick the speakerthe wrong face talks--face X,Y@FRAME
Shortening the fal key401pass the key exactly as fal shows it
Joining parts without fixing frame countsthe shot drifts out of sync with the editlipsync_parts.py join

Related skills

  • image-generation: the stills (character cards, panels).
  • elevenlabs-tts: the dialogue the mouths sync to.
  • viewing-videos: frame extraction for reviewing clips.
  • producing-animated-episodes: the whole episode workflow that uses these clips.

Download now (ZIP)

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
What did you use it for? e.g. Reviewing pull requests in a Rails app

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.