Photo to Video · compétence Open Skill
Photo to Video
Photo to Video est une Open Skill publique sur Digen. Ouvrez-la pour voir ce que ce workflow crée.
Film
4 0 2
https://d7qlwi7tl2u27.cloudfront.net/skill-covers/prod/1261060/2026-10-20/kspmn96h.jpg
---
allowed-tools:
- generate_video
- mix_clips
- generate_music
- generate_tts
- recognize_image
- probe_media
- extract_frame
- caption_video
---
# Photo to Video
Turn still photos into moving video: animate a single photo (i2v), morph one photo into another (fl2v), or build a slideshow montage from many photos (i2v per photo + mix_clips), with optional music, voiceover, and captions.
## When to use
- "Make this photo move / come alive / animate it"
- "Turn these photos into a video / slideshow / montage / reel"
- "Add camera motion to my picture", "Make a cinematic clip from this image"
- Not for: text-to-video with no photo (use `t2v`), or editing an existing video file (use a post-production workflow).
## Steps
1. **Clarify the goal.** Confirm in one short question (only if not already clear): single animated clip vs. multi-photo slideshow; desired motion (push-in, orbit, parallax, slow pan, hair/cloth/smoke movement); orientation (default `portrait` for social, `landscape` for cinematic); duration; whether music/voiceover/captions are wanted. Don't over-ask — one round is enough, then proceed.
2. **Look at the photo(s).** Use `recognize_image(image_url=<asset>, prompt="Describe the subject, depth layers, lighting, and what could move naturally in this image.")` so the motion prompt matches the actual content. Never guess the content of an unseen image.
3. **Pick the channel (hard-code in the `model=` parameter):**
| Case | Channel | Input shape |
|---|---|---|
| One photo → one animated clip | `i2v` | `input_urls=[photo]` (first entry = start frame) |
| Two photos → morph from A to B | `fl2v` | `input_urls=[A, B]` (first = first frame, second = last frame) |
| Many photos → slideshow | `i2v` per photo | one call per photo, then stitch |
| Pure text (no photo) | `t2v` | `input_urls=[]`, pass `model='t2v'` explicitly |
Use `ref2v` only when the user explicitly asks to keep a character's identity consistent across several different generated shots — for a plain photo-to-video request use `i2v`.
4. **Write the motion prompt in English.** Describe camera + subject motion + atmosphere, and explicitly keep the composition, subject identity, clothing, colors and lighting unchanged. Example:
"Slow cinematic push-in toward the subject, gentle parallax between foreground and background, soft natural light, subtle hair and fabric movement, shallow depth of field, photorealistic, stable framing, no morphing, no new objects."
5. **Generate.** `generate_video(model='i2v', input_urls=[<photo asset_id>], prompt=<motion prompt>, duration=<5-10, seconds>, orientation=<portrait|landscape|square>, resolution='720P', name=<clip name>, entity_type='photo_to_video_clips')`.
- `resolution='720P'` is the default; use `1080P` only if the user asks for HD.
- `duration`: keep 5–10s per clip unless the model supports longer; split long requests into several clips.
- For a slideshow, give each clip a distinct short name ("Photo 1 – Portrait", "Photo 2 – Beach") and the same `entity_type='photo_to_video_clips'`.
6. **Stitch a slideshow.** Pass the generated clips' `asset_id`s to `mix_clips` in the user's order: `mix_clips(clips=[{video:{url:<id>}}, ...], name='Photo Reel', entity_type='final_videos', orientation=<matching orientation>, fps=30, crf=23)`.
- To add a soundtrack, generate one first (`generate_music(model='music', prompt=<style>, duration=<total seconds>, name='Soundtrack', entity_type='music')`), then pass it as an audio track in the mix: `clips=[{video:{url:<id>}, audio:{url:<music id>}}]`.
- To add a voiceover, synthesize it with `generate_tts(model='tts.design', text=<script>, voice_instruction='<describe the voice>', name='Voiceover', entity_type='voiceovers')` and mix it the same way.
7. **Captions (optional).** For TikTok/Reels-style word-by-word highlighted captions on one finished clip, use `caption_video(video_url=<final clip asset_id>, template='hormozi', name=<