RenderIO
Concepts

Command Types

RenderIO supports single, chained, multiple, and yt-dlp command types for FFmpeg processing and public video downloads.

Command Types

RenderIO supports four public command patterns, each suited to different media workflows.

Single command

A single FFmpeg command that runs once. This is the most common type.

  • Type: FFMPEG_COMMAND
  • Endpoint: POST /api/v1/run-ffmpeg-command
  • Field: ffmpeg_command (string)
  • Returns: { "command_id": "..." }

Use this when you need to perform one FFmpeg operation, such as converting a format, resizing a video, or extracting audio.

curl -X POST https://renderio.dev/api/v1/run-ffmpeg-command \
  -H "X-API-KEY: ffsk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "input_files": {
      "in_video": "https://example.com/video.mov"
    },
    "output_files": {
      "out_video": "converted.mp4"
    },
    "ffmpeg_command": "-i {{in_video}} -c:v libx264 -c:a aac {{out_video}}"
  }'
curl -X POST https://renderio.dev/api/v1/run-ffmpeg-command \
  -H "X-API-KEY: ffsk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "input_files": {
      "in_video": "https://example.com/video.mov"
    },
    "output_files": {
      "out_video": "converted.mp4"
    },
    "ffmpeg_command": "-i <<in_video>> -c:v libx264 -c:a aac <<out_video>>"
  }'
const response = await fetch("https://renderio.dev/api/v1/run-ffmpeg-command", {
  method: "POST",
  headers: {
    "X-API-KEY": "ffsk_your_api_key",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    input_files: {
      in_video: "https://example.com/video.mov",
    },
    output_files: {
      out_video: "converted.mp4",
    },
    ffmpeg_command: "-i {{in_video}} -c:v libx264 -c:a aac {{out_video}}",
  }),
});

const { command_id } = await response.json();
const response = await fetch("https://renderio.dev/api/v1/run-ffmpeg-command", {
  method: "POST",
  headers: {
    "X-API-KEY": "ffsk_your_api_key",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    input_files: {
      in_video: "https://example.com/video.mov",
    },
    output_files: {
      out_video: "converted.mp4",
    },
    ffmpeg_command: "-i <<in_video>> -c:v libx264 -c:a aac <<out_video>>",
  }),
});

const { command_id } = await response.json();
import requests

response = requests.post(
    "https://renderio.dev/api/v1/run-ffmpeg-command",
    headers={"X-API-KEY": "ffsk_your_api_key"},
    json={
        "input_files": {
            "in_video": "https://example.com/video.mov"
        },
        "output_files": {
            "out_video": "converted.mp4"
        },
        "ffmpeg_command": "-i {{in_video}} -c:v libx264 -c:a aac {{out_video}}"
    }
)

command_id = response.json()["command_id"]
import requests

response = requests.post(
    "https://renderio.dev/api/v1/run-ffmpeg-command",
    headers={"X-API-KEY": "ffsk_your_api_key"},
    json={
        "input_files": {
            "in_video": "https://example.com/video.mov"
        },
        "output_files": {
            "out_video": "converted.mp4"
        },
        "ffmpeg_command": "-i {{in_video}} -c:v libx264 -c:a aac {{out_video}}"
    }
)

command_id = response.json()["command_id"]

Chained commands

Multiple FFmpeg commands that run sequentially in the same sandbox. The output of one step can be used as input to the next.

  • Type: CHAINED_COMMAND
  • Endpoint: POST /api/v1/run-chained-ffmpeg-commands
  • Field: ffmpeg_commands (array of strings, max 10)
  • Returns: { "command_id": "..." } (single ID for the whole chain)

Use this when your workflow requires multiple FFmpeg passes, such as transcoding followed by thumbnail extraction, or applying filters in stages.

curl -X POST https://renderio.dev/api/v1/run-chained-ffmpeg-commands \
  -H "X-API-KEY: ffsk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "input_files": {
      "in_video": "https://example.com/raw-footage.mov"
    },
    "output_files": {
      "out_video": "compressed.mp4",
      "out_thumb": "thumbnail.jpg"
    },
    "ffmpeg_commands": [
      "-i {{in_video}} -c:v libx264 -crf 28 -c:a aac {{out_video}}",
      "-i {{out_video}} -ss 00:00:02 -vframes 1 {{out_thumb}}"
    ]
  }'
curl -X POST https://renderio.dev/api/v1/run-chained-ffmpeg-commands \
  -H "X-API-KEY: ffsk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "input_files": {
      "in_video": "https://example.com/raw-footage.mov"
    },
    "output_files": {
      "out_video": "compressed.mp4",
      "out_thumb": "thumbnail.jpg"
    },
    "ffmpeg_commands": [
      "-i <<in_video>> -c:v libx264 -crf 28 -c:a aac <<out_video>>",
      "-i <<out_video>> -ss 00:00:02 -vframes 1 <<out_thumb>>"
    ]
  }'
const response = await fetch("https://renderio.dev/api/v1/run-chained-ffmpeg-commands", {
  method: "POST",
  headers: {
    "X-API-KEY": "ffsk_your_api_key",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    input_files: {
      in_video: "https://example.com/raw-footage.mov",
    },
    output_files: {
      out_video: "compressed.mp4",
      out_thumb: "thumbnail.jpg",
    },
    ffmpeg_commands: [
      "-i {{in_video}} -c:v libx264 -crf 28 -c:a aac {{out_video}}",
      "-i {{out_video}} -ss 00:00:02 -vframes 1 {{out_thumb}}",
    ],
  }),
});

const { command_id } = await response.json();
const response = await fetch("https://renderio.dev/api/v1/run-chained-ffmpeg-commands", {
  method: "POST",
  headers: {
    "X-API-KEY": "ffsk_your_api_key",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    input_files: {
      in_video: "https://example.com/raw-footage.mov",
    },
    output_files: {
      out_video: "compressed.mp4",
      out_thumb: "thumbnail.jpg",
    },
    ffmpeg_commands: [
      "-i <<in_video>> -c:v libx264 -crf 28 -c:a aac <<out_video>>",
      "-i <<out_video>> -ss 00:00:02 -vframes 1 <<out_thumb>>",
    ],
  }),
});

const { command_id } = await response.json();
import requests

response = requests.post(
    "https://renderio.dev/api/v1/run-chained-ffmpeg-commands",
    headers={"X-API-KEY": "ffsk_your_api_key"},
    json={
        "input_files": {
            "in_video": "https://example.com/raw-footage.mov"
        },
        "output_files": {
            "out_video": "compressed.mp4",
            "out_thumb": "thumbnail.jpg"
        },
        "ffmpeg_commands": [
            "-i {{in_video}} -c:v libx264 -crf 28 -c:a aac {{out_video}}",
            "-i {{out_video}} -ss 00:00:02 -vframes 1 {{out_thumb}}"
        ]
    }
)

command_id = response.json()["command_id"]
import requests

response = requests.post(
    "https://renderio.dev/api/v1/run-chained-ffmpeg-commands",
    headers={"X-API-KEY": "ffsk_your_api_key"},
    json={
        "input_files": {
            "in_video": "https://example.com/raw-footage.mov"
        },
        "output_files": {
            "out_video": "compressed.mp4",
            "out_thumb": "thumbnail.jpg"
        },
        "ffmpeg_commands": [
            "-i {{in_video}} -c:v libx264 -crf 28 -c:a aac {{out_video}}",
            "-i {{out_video}} -ss 00:00:02 -vframes 1 {{out_thumb}}"
        ]
    }
)

command_id = response.json()["command_id"]

Notice how the out_video alias from the first command is used as input in the second command. All commands share the same sandbox filesystem, so intermediate outputs are available to subsequent steps.

Multiple commands

Multiple independent commands that run in parallel. Each command gets its own sandbox and its own command_id.

  • Type: MULTIPLE_COMMAND
  • Endpoint: POST /api/v1/run-multiple-ffmpeg-commands
  • Field: commands (array of single command requests, max 10)
  • Returns: { "command_ids": ["...", "..."] }

Use this when you need to process several files independently at the same time, such as generating multiple renditions of different source videos.

curl -X POST https://renderio.dev/api/v1/run-multiple-ffmpeg-commands \
  -H "X-API-KEY: ffsk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "commands": [
      {
        "input_files": { "in_video": "https://example.com/video1.mov" },
        "output_files": { "out_video": "video1.mp4" },
        "ffmpeg_command": "-i {{in_video}} -c:v libx264 {{out_video}}"
      },
      {
        "input_files": { "in_video": "https://example.com/video2.mov" },
        "output_files": { "out_video": "video2.mp4" },
        "ffmpeg_command": "-i {{in_video}} -c:v libx264 {{out_video}}"
      }
    ]
  }'
curl -X POST https://renderio.dev/api/v1/run-multiple-ffmpeg-commands \
  -H "X-API-KEY: ffsk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "commands": [
      {
        "input_files": { "in_video": "https://example.com/video1.mov" },
        "output_files": { "out_video": "video1.mp4" },
        "ffmpeg_command": "-i <<in_video>> -c:v libx264 <<out_video>>"
      },
      {
        "input_files": { "in_video": "https://example.com/video2.mov" },
        "output_files": { "out_video": "video2.mp4" },
        "ffmpeg_command": "-i <<in_video>> -c:v libx264 <<out_video>>"
      }
    ]
  }'
const response = await fetch("https://renderio.dev/api/v1/run-multiple-ffmpeg-commands", {
  method: "POST",
  headers: {
    "X-API-KEY": "ffsk_your_api_key",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    commands: [
      {
        input_files: { in_video: "https://example.com/video1.mov" },
        output_files: { out_video: "video1.mp4" },
        ffmpeg_command: "-i {{in_video}} -c:v libx264 {{out_video}}",
      },
      {
        input_files: { in_video: "https://example.com/video2.mov" },
        output_files: { out_video: "video2.mp4" },
        ffmpeg_command: "-i {{in_video}} -c:v libx264 {{out_video}}",
      },
    ],
  }),
});

const { command_ids } = await response.json();
// command_ids = ["id-1", "id-2"]
const response = await fetch("https://renderio.dev/api/v1/run-multiple-ffmpeg-commands", {
  method: "POST",
  headers: {
    "X-API-KEY": "ffsk_your_api_key",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    commands: [
      {
        input_files: { in_video: "https://example.com/video1.mov" },
        output_files: { out_video: "video1.mp4" },
        ffmpeg_command: "-i <<in_video>> -c:v libx264 <<out_video>>",
      },
      {
        input_files: { in_video: "https://example.com/video2.mov" },
        output_files: { out_video: "video2.mp4" },
        ffmpeg_command: "-i <<in_video>> -c:v libx264 <<out_video>>",
      },
    ],
  }),
});

const { command_ids } = await response.json();
// command_ids = ["id-1", "id-2"]
import requests

response = requests.post(
    "https://renderio.dev/api/v1/run-multiple-ffmpeg-commands",
    headers={"X-API-KEY": "ffsk_your_api_key"},
    json={
        "commands": [
            {
                "input_files": {"in_video": "https://example.com/video1.mov"},
                "output_files": {"out_video": "video1.mp4"},
                "ffmpeg_command": "-i {{in_video}} -c:v libx264 {{out_video}}"
            },
            {
                "input_files": {"in_video": "https://example.com/video2.mov"},
                "output_files": {"out_video": "video2.mp4"},
                "ffmpeg_command": "-i {{in_video}} -c:v libx264 {{out_video}}"
            }
        ]
    }
)

command_ids = response.json()["command_ids"]
import requests

response = requests.post(
    "https://renderio.dev/api/v1/run-multiple-ffmpeg-commands",
    headers={"X-API-KEY": "ffsk_your_api_key"},
    json={
        "commands": [
            {
                "input_files": {"in_video": "https://example.com/video1.mov"},
                "output_files": {"out_video": "video1.mp4"},
                "ffmpeg_command": "-i {{in_video}} -c:v libx264 {{out_video}}"
            },
            {
                "input_files": {"in_video": "https://example.com/video2.mov"},
                "output_files": {"out_video": "video2.mp4"},
                "ffmpeg_command": "-i {{in_video}} -c:v libx264 {{out_video}}"
            }
        ]
    }
)

command_ids = response.json()["command_ids"]

Each command in the array is validated independently and runs in its own isolated sandbox. You poll each command_id separately.

yt-dlp commands

yt-dlp commands download public platform videos. They use input_urls instead of input_files because the source is a YouTube, TikTok, Instagram, X/Twitter, Reddit, Vimeo, Twitch, Facebook, or other yt-dlp-supported page URL.

  • Type: YTDLP_COMMAND
  • Download endpoint: POST /api/v1/ytdlp-download
  • Download + process endpoint: POST /api/v1/run-ytdlp-command
  • Field: input_urls (object with in_ keys)
  • Returns: { "command_id": "..." }

Use /api/v1/ytdlp-download when you only need the downloaded video file:

curl -X POST https://renderio.dev/api/v1/ytdlp-download \
  -H "X-API-KEY: ffsk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "input_urls": {
      "in_video": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
    }
  }'

When the command reaches SUCCESS, the downloaded file is available at output_files.out_video.storage_url. The output key mirrors the input key: in_clip becomes out_clip, in_source becomes out_source, and so on.

Use /api/v1/run-ytdlp-command when you want to download and immediately run FFmpeg on the result:

curl -X POST https://renderio.dev/api/v1/run-ytdlp-command \
  -H "X-API-KEY: ffsk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "input_urls": {
      "in_video": "https://www.tiktok.com/@user/video/7123456789"
    },
    "ffmpeg_command": "-i {{in_video}} -vn -c:a libmp3lame -q:a 2 {{out_audio}}",
    "output_files": {
      "out_audio": "audio.mp3"
    }
  }'
curl -X POST https://renderio.dev/api/v1/run-ytdlp-command \
  -H "X-API-KEY: ffsk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "input_urls": {
      "in_video": "https://www.tiktok.com/@user/video/7123456789"
    },
    "ffmpeg_command": "-i <<in_video>> -vn -c:a libmp3lame -q:a 2 <<out_audio>>",
    "output_files": {
      "out_audio": "audio.mp3"
    }
  }'

Only public content is supported. RenderIO does not bypass DRM, paywalls, private accounts, or content that requires a login.

When to use which type

ScenarioCommand typeWhy
Convert a video to MP4SingleOne operation, one output
Transcode then extract thumbnailChainedSecond step depends on first step's output
Apply a two-pass encodeChainedSecond pass needs data from the first
Process a batch of user uploadsMultipleEach file is independent
Generate 720p and 1080p renditions of different videosMultipleNo dependencies between commands
Merge two videos then add watermarkChainedSequential operations on related files
Download a public YouTube, TikTok, or Instagram videoyt-dlp downloadSource is a platform page URL, not a direct file URL
Download a public video then extract MP3 audioyt-dlp + FFmpegOne async job handles both download and processing

Limits

  • Chained commands: Maximum of 10 commands in the ffmpeg_commands array
  • Multiple commands: Maximum of 10 commands in the commands array
  • yt-dlp commands: Available during trials and on the Growth plan or higher
  • Timeout: Command timeout is determined by your subscription plan

On this page