Batch Create Product Videos for TikTok

March 15, 2026 · RenderIO

One video per product. Thousands of products.

TikTok Shop sellers with product videos get 3-5x more conversions than those with static listings. But if you have 1,000 SKUs, creating 1,000 individual videos in Premiere or CapCut isn't realistic.

The pattern is simple: take a video template, overlay each product's image and text, output a unique video. FFmpeg does this in one command per product. RenderIO runs all 1,000 commands in parallel.

What you need

  1. A template video: 1080x1920 (9:16), 10-20 seconds, with designated areas for product content. This can be a motion graphics loop, a lifestyle background, or a simple gradient animation.

  2. Product data: For each SKU, you need:

    • Product image (PNG with transparent background works best)

    • Product name

    • Price

    • One key selling point

  3. A RenderIO API key: Sign up at renderio.dev, plans start at $9/month (500 commands).

The FFmpeg command

Basic: image overlay + text

ffmpeg -i template.mp4 -i product.png \
  -filter_complex "\
    [1:v]scale=500:-1[img];\
    [0:v][img]overlay=(W-w)/2:350,\
    drawtext=text='Product Name Here':fontsize=40:fontcolor=white:x=(w-text_w)/2:y=1200,\
    drawtext=text='$29.99':fontsize=52:fontcolor=#00FF88:x=(w-text_w)/2:y=1300,\
    drawtext=text='Free Shipping':fontsize=28:fontcolor=#AAAAAA:x=(w-text_w)/2:y=1400[v]" \
  -map "[v]" -map 0:a -c:v libx264 -crf 20 -c:a copy \
  -movflags +faststart -t 15 output.mp4

With animated entrance (fade in product)

ffmpeg -i template.mp4 -i product.png \
  -filter_complex "\
    [1:v]scale=500:-1,format=rgba,fade=t=in:st=0.5:d=0.8:alpha=1[img];\
    [0:v][img]overlay=(W-w)/2:350:enable='gte(t,0.5)'[v]" \
  -map "[v]" -map 0:a -c:v libx264 -crf 20 -c:a copy \
  -movflags +faststart output.mp4

The product image fades in at 0.5 seconds over 0.8 seconds. Gives a more polished look than a static overlay.

With price tag animation

ffmpeg -i template.mp4 -i product.png \
  -filter_complex "\
    [1:v]scale=500:-1[img];\
    [0:v][img]overlay=(W-w)/2:350,\
    drawtext=text='$29.99':fontsize=52:fontcolor=#00FF88:x=(w-text_w)/2:y=1300:enable='gte(t,1.5)',\
    drawtext=text='SHOP NOW':fontsize=36:fontcolor=white:x=(w-text_w)/2:y=1600:enable='gte(t,2.5)'[v]" \
  -map "[v]" -map 0:a -c:v libx264 -crf 20 -c:a copy \
  -movflags +faststart output.mp4

Text appears at specific timestamps: price at 1.5 seconds, CTA at 2.5 seconds.

Batch processing script

Step 1: Prepare product data

// products.json
const products = [
  {
    sku: "WH-001",
    name: "Wireless Headphones",
    price: "$49.99",
    feature: "40hr Battery",
    image: "https://cdn.example.com/products/wh-001.png"
  },
  {
    sku: "PC-002",
    name: "Phone Case",
    price: "$19.99",
    feature: "Military Grade",
    image: "https://cdn.example.com/products/pc-002.png"
  },
  // ... hundreds more
];

Step 2: Generate videos via RenderIO API

const TEMPLATE_URL = "https://storage.example.com/tiktok-template-v2.mp4";

async function createProductVideo(product) {
  // Replace spaces with underscores for FFmpeg drawtext
  const safeName = product.name.replace(/ /g, "\\ ");
  const safeFeature = product.feature.replace(/ /g, "\\ ");

  const command = `-i {in_template} -i {in_product} -filter_complex "[1:v]scale=500:-1,format=rgba,fade=t=in:st=0.5:d=0.8:alpha=1[img];[0:v][img]overlay=(W-w)/2:350:enable='gte(t,0.5)',drawtext=text='${safeName}':fontsize=40:fontcolor=white:x=(w-text_w)/2:y=1200:enable='gte(t,1)',drawtext=text='${product.price}':fontsize=52:fontcolor=#00FF88:x=(w-text_w)/2:y=1300:enable='gte(t,1.5)',drawtext=text='${safeFeature}':fontsize=28:fontcolor=#AAAAAA:x=(w-text_w)/2:y=1400:enable='gte(t,2)'[v]" -map "[v]" -map 0:a -c:v libx264 -crf 20 -c:a copy -movflags +faststart -t 15 {out_video}`;

  const response = await fetch("https://renderio.dev/api/v1/run-ffmpeg-command", {
    method: "POST",
    headers: {
      "X-API-KEY": process.env.RENDERIO_API_KEY,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      ffmpeg_command: command,
      input_files: {
        in_template: TEMPLATE_URL,
        in_product: product.image,
      },
      output_files: { out_video: `${product.sku}-tiktok.mp4` },
    }),
  });

  return response.json();
}

// Process all products in parallel
async function batchCreateVideos(products) {
  const BATCH_SIZE = 50; // Process 50 at a time
  const results = [];

  for (let i = 0; i < products.length; i += BATCH_SIZE) {
    const batch = products.slice(i, i + BATCH_SIZE);
    const batchResults = await Promise.all(
      batch.map(p => createProductVideo(p))
    );
    results.push(...batchResults);
    console.log(`Processed ${Math.min(i + BATCH_SIZE, products.length)}/${products.length}`);
  }

  return results;
}

const results = await batchCreateVideos(products);

Step 3: Poll for completion

async function waitForCompletion(commandId) {
  while (true) {
    const response = await fetch(
      `https://renderio.dev/api/v1/commands/${commandId}`,
      { headers: { "X-API-KEY": process.env.RENDERIO_API_KEY } }
    );
    const data = await response.json();

    if (data.status === "completed") return data;
    if (data.status === "failed") throw new Error(`Command ${commandId} failed`);

    await new Promise(r => setTimeout(r, 2000)); // Wait 2 seconds
  }
}

Multiple templates for variety

Using one template for all products looks repetitive. Create 3-5 templates and rotate:

const templates = [
  "https://storage.example.com/template-gradient.mp4",
  "https://storage.example.com/template-lifestyle.mp4",
  "https://storage.example.com/template-minimal.mp4",
  "https://storage.example.com/template-bold.mp4",
];

async function createProductVideoWithRotation(product, index) {
  const templateUrl = templates[index % templates.length];
  // ... same API call with rotated template
}

4 templates across 1,000 products means each template is used ~250 times. Different enough to not look repetitive on a user's feed.

Cost breakdown

Catalog sizeVideos createdAPI callsPlanMonthly cost
100 SKUs100100Starter$9/mo
500 SKUs500500Growth$29/mo
1,000 SKUs1,0001,000Growth$29/mo
5,000 SKUs5,0005,000Pro$49/mo
10,000 SKUs10,00010,000Business$99/mo

Even at 10,000 SKUs, you're within the Business plan at $99/month (20,000 commands). Zero egress fees.

Compare to freelance video editors: 1,000 videos at 5each=5 each = 5,000. The API costs 2929-49.

Processing thousands of product videos? The Business plan at $99/mo covers 20,000 commands. Get your API key at renderio.dev.

Tips for better product videos

  1. Keep templates under 15 seconds. TikTok completion rate matters more than length.

  2. Use PNG images with transparent backgrounds. They overlay cleanly on any template.

  3. Put the price in the first 2 seconds. Users decide to watch based on price relevance.

  4. Update templates monthly. Fresh templates prevent creative fatigue.

  5. A/B test: Create 2 versions per product and let TikTok's algorithm pick the winner.

Build once, run forever. Every new product in your catalog gets a TikTok video automatically.