Skip to main content

Documentation Index

Fetch the complete documentation index at: https://rendi.dev/docs/llms.txt

Use this file to discover all available pages before exploring further.

Combine a set of images and an audio track into a single video. Each image displays for a fixed duration and the audio plays over the top — finishing when the audio ends.

Code

const API_KEY = process.env.RENDI_API_KEY;

const submit = await fetch("https://api.rendi.dev/v1/run-ffmpeg-command", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-API-KEY": API_KEY,
  },
  body: JSON.stringify({
    input_files: {
      in_img_1: "https://storage.rendi.dev/sample/bbb-splash.png",
      in_img_2: "https://storage.rendi.dev/sample/rodents.png",
      in_img_3: "https://storage.rendi.dev/sample/evil-frank.png",
      in_audio_1: "https://storage.rendi.dev/sample/Neon%20Lights.mp3",
    },
    output_files: {
      out_1: "slideshow.mp4",
    },
    ffmpeg_command:
      '-loop 1 -t 5 -i {{in_img_1}} -loop 1 -t 5 -i {{in_img_2}} -loop 1 -t 5 -i {{in_img_3}} -i {{in_audio_1}} -filter_complex "[0:v][1:v][2:v]concat=n=3:v=1:a=0,format=yuv420p[v]" -map [v] -map 3:a -c:v libx264 -c:a aac -shortest {{out_1}}',
  }),
});
const { command_id } = await submit.json();

while (true) {
  const res = await fetch(`https://api.rendi.dev/v1/commands/${command_id}`, {
    headers: { "X-API-KEY": API_KEY },
  });
  const data = await res.json();
  if (data.status === "SUCCESS") {
    console.log("Slideshow URL:", data.output_files.out_1.storage_url);
    break;
  }
  if (data.status === "FAILED") throw new Error("Command failed");
  await new Promise((r) => setTimeout(r, 2000));
}

How the FFmpeg command works

  • -loop 1 -t 5 -i {{in_img_1}} — loop each image for 5 seconds (repeat per image)
  • -i {{in_audio_1}} — audio track as the last input
  • concat=n=3:v=1:a=0 — concatenate the 3 video streams, 1 video, 0 audio
  • format=yuv420p — pixel format compatible with most players
  • -map [v] -map 3:a — pick the concatenated video + audio from input index 3
  • -shortest — stop when the shortest stream ends (typically when video runs out)
  • {{out_1}} — output file
For longer images, increase -t 5 per input. For crossfades between images, replace concat with xfade.

Response

{
  "output_files": {
    "out_1": {
      "file_id": "10cfed0c-...",
      "size_mbytes": 1.09,
      "duration": 15.001,
      "file_type": "video",
      "file_format": "mp4",
      "storage_url": "https://storage.rendi.dev/temp_files/.../slideshow.mp4",
      "width": 1920,
      "height": 1080,
      "codec": "h264",
      "frame_rate": 25.0,
      "bitrate_video_kb": 453.5,
      "bitrate_audio_kb": 132.6
    }
  },
  "status": "SUCCESS",
  "command_type": "FFMPEG_COMMAND"
}