Automotion docs
Guides

Slideshow from a list of images

Turn image URLs into a polished slideshow with transitions, captions and music.

The simplest useful automation: a list of image URLs in, a slideshow MP4 out. One scene per image, a transition between scenes, an optional caption, music underneath.

The pattern

Each image becomes a scene: the image as a full-bleed element, a caption, and a transition describing how the scene enters from the previous one.

movie.json
{
  "schema": "v1",
  "preset": "16:9",
  "scenes": [
    {
      "id": "slide-1",
      "duration": 3,
      "elements": [
        {
          "id": "slide-1-img",
          "type": "image",
          "src": "https://assets.example.com/gallery/beach.jpg",
          "fit": "cover",
          "animation": { "preset": "zoom-in", "easing": "ease-out", "duration": 3 }
        },
        {
          "id": "slide-1-caption",
          "type": "text",
          "text": "Day 1 — the coast",
          "fontSize": 44,
          "background": "#00000099",
          "padding": 16,
          "position": "bottom-left"
        }
      ]
    },
    {
      "id": "slide-2",
      "duration": 3,
      "transition": { "type": "fade", "duration": 0.6 },
      "elements": [
        {
          "id": "slide-2-img",
          "type": "image",
          "src": "https://assets.example.com/gallery/mountains.jpg",
          "fit": "cover",
          "animation": { "preset": "zoom-out", "easing": "ease-out", "duration": 3 }
        },
        {
          "id": "slide-2-caption",
          "type": "text",
          "text": "Day 2 — up high",
          "fontSize": 44,
          "background": "#00000099",
          "padding": 16,
          "position": "bottom-left"
        }
      ]
    },
    {
      "id": "slide-3",
      "duration": 3,
      "transition": { "type": "slide", "duration": 0.6 },
      "elements": [
        {
          "id": "slide-3-img",
          "type": "image",
          "src": "https://assets.example.com/gallery/city.jpg",
          "fit": "cover"
        },
        {
          "id": "slide-3-caption",
          "type": "text",
          "text": "Day 3 — the city",
          "fontSize": 44,
          "background": "#00000099",
          "padding": 16,
          "position": "bottom-left"
        }
      ]
    }
  ],
  "elements": [
    {
      "id": "soundtrack",
      "type": "audio",
      "src": "https://assets.example.com/audio/acoustic.mp3",
      "volume": 0.5,
      "fadeOut": 1
    }
  ]
}

▶ Try it in the playground

Generating the document from a list

The document is plain JSON — generate it from your data with a few lines:

build-slideshow.ts
const images: { url: string; caption: string }[] = loadGallery();
 
const movie = {
  schema: "v1",
  preset: "16:9",
  scenes: images.map((image, index) => ({
    id: `slide-${index + 1}`,
    duration: 3,
    ...(index > 0 ? { transition: { type: "fade", duration: 0.6 } } : {}),
    elements: [
      {
        id: `slide-${index + 1}-img`,
        type: "image",
        src: image.url,
        fit: "cover",
        animation: { preset: index % 2 ? "zoom-out" : "zoom-in", duration: 3 },
      },
      {
        id: `slide-${index + 1}-caption`,
        type: "text",
        text: image.caption,
        fontSize: 44,
        background: "#00000099",
        padding: 16,
        position: "bottom-left",
      },
    ],
  })),
};

Remember: element and scene ids must be unique across the movie (the generator above derives them from the index), and slow Ken-Burns-style motion is just an animation whose duration matches the scene length.

Uploading the images first

If your images aren't publicly hosted, push them through POST /v1/assets: request a presigned upload slot, PUT the bytes, then use the returned assetUrl as src.

Render

Exactly as in the quickstartPOST /v1/renders with { "movie": … }, then poll or use a webhook.

On this page