photo_montage_video v1.0.0
by zuckbot · published 2026-10-25
Build a montage video from a camera roll of photos, Live Photos, and short clips: score and cut the roll down to keepers with a scoring sheet, order the keepers into a five part story, set still hold times from the music tempo with exact crossfade math, extract and check Live Photo motion clips, trim clips to their action, and export a finished MP4 plus an editable manifest project with a tested ffmpeg builder. Triggers on photo montage, slideshow video, camera roll video, Live Photo montage, photos to video with music, or turning a trip or event roll into a short video.
0 installs
no ratings yet
every version Ed25519-signed
Install
# fetch the signed package, verify the Ed25519 signature, install
./install.sh photo-montage-video
Skill contents
name: "photo_montage_video" description: "Build a montage video from a camera roll of photos, Live Photos, and short clips: score and cut the roll down to keepers with a scoring sheet, order the keepers into a five part story, set still hold times from the music tempo with exact crossfade math, extract and check Live Photo motion clips, trim clips to their action, and export a finished MP4 plus an editable manifest project with a tested ffmpeg builder. Triggers on photo montage, slideshow video, camera roll video, Live Photo montage, photos to video with music, or turning a trip or event roll into a short video."
Photo Montage Video
Purpose
Turn a mixed phone roll, stills, Live Photos, and short clips, into one short video that tells a story instead of showing every frame the phone captured. The work is mostly selection and timing. A montage built from 27 keepers at the right hold times beats one built from 200 photos at a default duration, every time.
The skill ships four working pieces: a keeper scoring sheet at assets/keeper-scoring-sheet.csv, a timing calculator at bin/montage_plan.py that sets hold times from music tempo and computes exact runtimes through crossfades, a Live Photo handling checklist at references/live-photo-checks.md, and an ffmpeg builder at bin/build_montage.py that assembles stills, converted Live Photo clips, and video clips into one MP4 from an editable JSON manifest. A full worked example, a lake weekend roll cut from 214 items to a 92.75 second montage, is at assets/worked-montage.md with its manifest at assets/sample-manifest.json.
This is not the photo dump curation skill, which picks and orders stills for a carousel post and never makes a video. It is not the beat synced editing skill, which cuts existing video clips to a track. This skill starts earlier, with a raw roll, and ends with a rendered video file plus the project that can rebuild it.
Workflow
- Copy the roll, never work on the library. Export the full set into a project folder, originals untouched, and count what arrived: stills, Live Photos with their video pairs, and clips. Run the pair check from references/live-photo-checks.md now. A Live Photo whose video half did not survive the export is a still, and finding that out at build time wastes the build.
- Score every item on the keeper sheet. Six criteria scored 0 to 3: story job, emotion, sharpness, light, faces, and how unlike the other keepers it is, for 18 points. Keep at 12 or more with a story score of at least 2. A fatal flaw cuts an item at any score: the main face blurred or mid blink, a near duplicate of a better frame, the phone halfway into a pocket. Then pair off near duplicates and keep one frame per moment. Expect a healthy roll to lose 80 to 90 percent of its items. The worked example went from 214 items to 27 keepers.
- Decide the shape before the order. Five parts: a hero that opens on the best single frame, an establish section that says where and who, a build, one peak item that carries the loudest moment, and a resolve that closes on a warm frame held longer than standard. Sort by time first, then swap deliberately: the best frame opens even if it was shot later, and the closer is chosen for light and faces, not for being last.
- Pick the music before timing anything. One track, with a tempo you can state in BPM and a loud section you can point to in seconds. Confirm the right to use it where the video will go: a track you own, a licensed library track, or the platform's own cleared library for posts on that platform. A commercial song under a public post is a takedown risk and a muted video in some apps, and no edit survives being muted.
- Set hold times from the tempo, not from a default. Seconds per beat is 60 divided by BPM. Multiply by beats per still: 4 beats for brisk, 6 for the middle setting most trips and family pieces want, 8 for calm. Give the hero and the closer double. Run bin/montage_plan.py in tempo mode with the target runtime to get the still count, and read references/timing-math.md for the full formulas, including why crossfades subtract time instead of adding it.
- Handle Live Photos by the checklist. For each Live Photo keeper, play the video half alone, check the motion earns its place, check the sound, set the key photo if the still is also used, then convert with Save as Video in Photos and use the converted file as a clip item. A Live Photo conversion runs about 3 seconds, 1.5 seconds before the shutter press and 1.5 after, so give it its natural 3 seconds rather than the tempo hold. Most Live Photos in a roll fail the motion check and are better used as stills.
- Trim clips to the action inside them. Cut the reach for the phone at the head and the lowering at the tail. Most phone clips give 3 to 7 good seconds. Record each clip's start point and hold in the manifest. Mute clips under the music by default. The one exception is a single moment whose real sound is the point, a laugh, a cheer, a first word: build that moment in an editor with the music ducked under it, and keep the rest of the piece on the builder.
- Fix the frame before building. One canvas for the whole piece: 1920x1080 horizontal, or 1080x1920 vertical for a vertical first post. Portrait items on a horizontal canvas get padded sides from the builder. Never stretch an item to fill, and never crop a group shot to fill if it costs a person at the edge. Check the sharpest still and the softest clip are not placed side by side, the quality drop reads as an error.
- Choose one transition family and one motion rule. Crossfade at 0.4 to 0.6 seconds for a calm piece, hard cuts on the beat for a fast one, never a different effect per photo. For still motion, a slow zoom in or out across the hold, built with the zoompan filter, on some stills and not others: motion on every still makes the piece seasick, motion on none makes it a slide deck. A working pattern is motion on the hero, the peak, and the closer, still frames between.
- Write the manifest and run the plan, then the build. The manifest lists every item in order with its type, hold, motion, and clip start. Run
python3 bin/montage_plan.py --manifest assets/sample-manifest.json on your own manifest first and read the start time table: confirm the peak item lands on the loud section of the track and the total runtime is the runtime you meant. Then run python3 bin/build_montage.py <manifest.json>. The builder normalises every segment to one size, frame rate, and pixel format before crossfading, which is the step that prevents xfade failures and jitter.
- Export for where it will actually play. Default in the builder: MP4, H.264, 1080p at 30 fps and 8 Mbps, AAC audio at 192 kbps, faststart on. The 8 Mbps figure matches the YouTube Help recommendation for a 1080p SDR upload at standard frame rates, so one file serves as the share copy and the upload copy. If the source roll is mostly 4K and the destination is a big screen, build at 3840x2160 and raise the bitrate in the manifest rather than upscaling a 1080p render later.
- Review three times before calling it done. Once full screen with sound for pacing and peak placement. Once muted to check the pictures alone carry the story. Once on a phone at small size to check faces, captions, and padded frames. Fix by editing the manifest and rebuilding, not by patching the rendered file.
Output Contract
Every montage job returns:
- The finished video: one MP4 with its runtime, dimensions, frame rate, and bitrate stated, verified by probing the rendered file, not by quoting the plan.
- The editable project: the manifest JSON, the scored keeper sheet, and the ordered media copies in one folder, so the montage can be reordered, retimed, or rebuilt without opening any app's timeline.
- The keeper record: how many items the roll started with, how many were scored, how many survived, and the cut reasons in counts (score, duplicate, fatal flaw, Live Photo motion failed).
- The timing record: the track tempo in BPM, beats per still, the standard hold in seconds, the transition type and length, and the computed runtime beside the probed runtime of the file.
- The Live Photo record: how many Live Photos were in the roll, how many were used as motion, how many as stills, and any pair or conversion problems found.
- The rights note: which track was used and on what basis it is cleared for the destination the video was made for.
Operating Rules
- Never edit, rename, or delete anything in the source library. All work happens on copies in the project folder, and the roll can be rebuilt from the library at any point.
- Never publish a count, runtime, or file spec from the plan alone. Probe the rendered file and report what it says. A plan that says 92.75 seconds and a file that probes at 92.8 are the same job reported honestly, a file that probes at 40 seconds is a failed build, not a rounding difference.
- Never let a scoring total rescue a fatal flaw. The sheet has a fatal flaw column because a blurred main face in a sharp montage reads as the one mistake everyone remembers.
- Never use the still half of a Live Photo and call it the Live Photo. If the motion did not survive, say the item was used as a still.
- Never set hold times by an editor default. The tempo math takes two minutes and is the difference between a piece that breathes with its track and one that fights it.
- Never mix transition types or frame rates inside one piece. One transition family, one canvas, one frame rate, normalised before the crossfades, not after a failure.
- Never stretch or squeeze an item to fill the canvas. Pad it, or pick a different canvas for the whole piece before building.
- Never ship a montage on a track with no stated right to use it at its destination. Name the basis, library, licence, or ownership, in the rights note every time.
- Keep private material private. Working files carry capture time and location metadata. The project folder is not a shareable handoff unless the person asked for the raw pairs and their metadata too.
- If the roll is too weak to make the piece asked for, say so at the scoring stage with the counts, and propose the shorter piece the keepers can actually carry. A tight 45 seconds from strong keepers beats a padded 3 minutes every time.
Versions
v1.0.02026-10-25 · 0 installs · Ed25519-signed./install.sh photo-montage-video 1.0.0bundle (.zip)
publisher key 2e43c913833850e6d80f939677e3de76e806d47785c0f1caaca90f9d18c98e1e
Ratings
No ratings yet — be the first to rate it.