---
name: "still_image_animation"
description: "Animating a still image into a short clip: choosing a photo that moves well, picking one camera move or parallax or AI motion, designing a clean loop, checking faces, text, and geometry for warp, and exporting for social and ads. Use when asked to animate a photo, make a Ken Burns clip, add parallax to a picture, turn a still into a video, or make a looping clip from an image."
---

# Still Image Animation

## Purpose
Turn one still image into a short clip that holds up at phone size. The skill is tool-neutral: it covers a deterministic camera move in any editor or with the bundled ffmpeg renderer, a layered parallax build, and AI image-to-video generation. Each route uses the same photo scoring, the same failure checks, and the same export targets, so the method survives a change of tool.

## Workflow
1. **Score the photo first.** Use the hard rules and the 0 to 10 score in `references/failure-checks.md`. A photo that fails a hard rule does not get animated by that method. Check resolution against the output size times the planned zoom, subject headroom, depth, plausible natural motion, sharpness, and separation from the background.
2. **Pick the route.** Use a deterministic camera move when text or a logo must stay exact, when the photo is a portrait that must not change, or when the result must be repeatable. Use parallax when the photo has clear depth layers and a flat move feels dead. Use AI generation only when the scene has something that should really move, water, hair, clouds, fabric, light, and a small amount of warp is acceptable.
3. **Write a one-line plan.** Record the source image, method, preset or prompt, duration, frame rate, output size, zoom, and focus point. `assets/sample-plan.json` shows the shape. One clip gets one camera move and, for AI work, one subject action.
4. **Set the move.** Follow `references/motion-recipes.md`. Working ranges: push-in ends at 1.10 to 1.20, a pan holds 1.10 to 1.20 and travels inside the extra area, hold-subtle runs 1.00 to 1.04. In an editor, keyframe Scale and Position and ease both ends of the move, the Adobe Ken Burns method. Save the move as a preset when a batch shares it.
5. **Build parallax by layers when chosen.** Cut the subject out, fill the hole behind it, then scale the subject more than the background, a tested starting pair is plus 10 percent against plus 5 percent. Or set the layers at different depths in 3D space and keyframe the camera, the Adobe After Effects method. Preview the widest frame and check all four edges.
6. **Prompt AI generation as motion only.** Use the pattern in `references/motion-recipes.md`: subject motion, camera motion, scene response, motion style. The image already shows the scene, so do not restate it. Use positive phrasing, one precise camera term, and small actions for faces. Use start and end keyframes when the tool offers them and the end framing or the loop point matters, and verify the current duration and size limits in the tool at generation time.
7. **Render the deterministic route.** Run `bin/animate.py photo.jpg -o out.mp4 --preset push-in --size 1080x1920 --duration 4`. Add `--loop boomerang` for a seamless loop, or `--dry-run` to print the ffmpeg command without rendering. The renderer scales the input large before zoompan to cut step jitter, and writes the move from the frame count so it ends on the planned frame.
8. **QA every clip.** Run `bin/qa.py out.mp4 --expect 1080x1920 --expect-duration 4 --expect-fps 30 --out-dir qa/`, add `--loop` for loops. Then apply the checks in `references/failure-checks.md` to the extracted first, middle, and last frames: faces, text read letter by letter, geometry, hands, edges, and loop seam. Watch the full clip once at phone size. A text or face failure rejects the take.
9. **Export for the destination.** Follow `references/export-specs.md`. Vertical social is 1080x1920 at 30 fps, square is 1080x1080, horizontal is 1920x1080. MP4 with H.264 and yuv420p everywhere. Keep a clean master with no burned-in captions, and derive platform copies from the master.

## Output Contract
- One MP4 per plan, plus the plan record that produced it: source image, method, preset or prompt, duration, frame rate, size, zoom, and focus.
- MP4: H.264, yuv420p, even dimensions, faststart, at the size and frame rate in the plan.
- A QA report from `bin/qa.py` with all checks passing, plus the first, middle, and last frames kept with the output.
- Loops state their kind and total duration in the file name and the delivery note, for example harbour-loop-4s.mp4 for a boomerang loop.
- AI-generated clips state that they are generated, name the tool, and record the prompt that produced the shipped take.

## Operating Rules
1. Accuracy and rights come first. No invented claims in captions or overlays, and no animation of a photo whose licence is unclear.
2. One move per clip. A second move, a second subject action, or a longer duration is a new clip, not an edit to a take that already passed QA.
3. Text and faces get the strict route. If either must stay exact, use a camera move or composite the original element back over a generated clip. Never ship a take where the QA frames show changed letters or a changed face.
4. Fix the earliest cause. Photo problem, pick a better photo. Prompt problem, cut the action or lock the camera. Render problem, fix the plan or the preset. Do not patch single frames of a finished clip.
5. Platform and model numbers in the references were checked on 2026-10-17 and are targets, not guarantees. Verify the current limit at upload or generation time for a launch that matters.
6. Numbers given as working rules in `references/motion-recipes.md`, such as zoom ranges and the 10 against 5 parallax pair, are rules of this skill tested with the bundled renderer. They are not vendor limits, and the references say so where they appear.
7. Test before shipping. After any change to `bin/`, the test in the verification note below must pass again.

## Verification
Tested on 2026-10-17 with ffmpeg 8.1.2 and Pillow 10.2.0. A generated 2400x1600 test image rendered as a push-in to 1080x1920 in 4 seconds at 30 fps, and as a boomerang loop, and both outputs passed `bin/qa.py` including the loop seam check. The exact commands and results are in the run log for this skill build.
