Anniversary video from old photos: three 10-second clips and a song

Animate three old photos with Gemini Omni image_to_video, 10 seconds each, then join them over a Lyria 3.5 track in Timeline. 30 seconds bills at $0.10.

6 min readSume
All posts

To make an anniversary video from old photos, send each photo as image_url to gemini-omni-flash-1.1 for a 10-second clip (its maximum), write a Lyria 3.5 track with sume/music-auto, and join the three clips in one Timeline 1.0 render with the track as soundtrack. Three 10-second clips are 30 seconds, which bills as 1 minute at $0.10 per ceil(output minute).

Sources: Video Router, Music Router and Timeline 1.0, read 2026-10-04.

The pipeline

Each stage has its own limits. The Omni clips come with audio that you may want to remove before laying music under them.

Anniversary video stages (read 2026-10-04)
StageRouteLimit or price
Animate a photoPOST /v1/video-router/generate, gemini-omni-flash-1.1, image_url3 to 10 s, audio always on
Drop the clip audioPOST /v1/video-trim, audio drop$0.02 per trim
Write the songPOST /v1/music-router/generatePrompt up to 5000 characters; steer length in the prompt
AssemblePOST /v1/timeline-1.0/render$0.10 per ceil(output minute)

Animate one photo

Old photos are often scratched or low-resolution, and the model animates what it sees, including damage. Ask for gentle motion only: a breeze, a smile, a slow push-in.

curl -X POST https://api.sume.com/v1/video-router/generate \
  -H "Authorization: Bearer $SUME_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: anniversary-photo-1" \
  -d '{
    "model": "gemini-omni-flash-1.1",
    "prompt": "Gentle motion only: a slow push-in, the couple smiles, leaves move in a light breeze. Keep faces and clothing unchanged.",
    "image_url": "https://example.com/1996-photo.jpg",
    "resolution": "1080p",
    "aspect_ratio": "16:9",
    "duration": 10,
    "mode": "async"
  }\

Write the song

Write the track as a 30-second brief. Ask for what you want in the positive prompt, since a non-empty negative_prompt is rejected.

curl -X POST https://api.sume.com/v1/music-router/generate \
  -H "Authorization: Bearer $SUME_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: anniversary-song-1" \
  -d '{
    "model": "sume/music-auto",
    "prompt": "Warm acoustic waltz, 90 BPM, G major. Fingerpicked guitar and soft strings, tender and nostalgic. A 30-second track with a gentle ending. Instrumental, no vocals."
  }\

Assemble

Import the three clips (silent versions if you trimmed) and the track, then render. Spine 30 seconds, three slots at starts 0, 10 and 20, a fade of 0.5 seconds between them, and soundtrack.fade_out_seconds of 3.

{
  "audio": { "mode": "silence", "duration_seconds": 30 },
  "soundtrack": { "url": "https://media.sume.com/artifacts/artf_demo/anniversary.wav", "fade_out_seconds": 3 },
  "video": [
    { "source_url": "https://media.sume.com/artifacts/artf_demo/clip1.mp4", "start": 0, "duration": 10 },
    { "source_url": "https://media.sume.com/artifacts/artf_demo/clip2.mp4", "start": 10, "duration": 10,
      "transition": { "type": "fade", "duration": 0.5 } },
    { "source_url": "https://media.sume.com/artifacts/artf_demo/clip3.mp4", "start": 20, "duration": 10,
      "transition": { "type": "fade", "duration": 0.5 } }
  ],
  "output": { "width": 1920, "height": 1080, "fps": 30 }
}

Be clear about what is generated

Tell the family which parts are animated. The faces come from the photo, and the motion around them is the model's. Check each clip's first and last frames with Video frames before you send the finished video.

Sources

Related posts

More in Use cases

All Use cases posts

Written by Sume