How to Generate Personalized Video Ads from a CSV with TypeScript
July 8, 2026 · By VideoFlowLearn how to build a high-performance video generation pipeline that turns CSV data into personalized 1080p MP4 ads using VideoFlow and TypeScript.
How to Generate Personalized Video Ads from a CSV with TypeScript
Scaling video production for marketing is a notorious bottleneck. If you need to generate 500 variations of a video ad—each with a different customer name, local branch photo, or specific discount code—manual editing is out of the question. You need a pipeline that treats video like data.
In this tutorial, we will build a high-performance video generation pipeline that takes a standard CSV file and produces 1080p MP4 ads using VideoFlow and TypeScript. Unlike traditional solutions that rely on fragile FFmpeg shell scripts, we will use a typed, programmatic builder that renders identically in the browser and on the server.
The Architecture of Programmatic Video
When building personalized video ads, the goal is to separate the template from the data. We define the visual structure once—backgrounds, transitions, effects, and timing—and then inject variables at runtime.

VideoFlow makes this trivial because every project compiles to a portable VideoJSON document. This means you can preview your template in the Playground and then deploy it to a Node.js worker for batch processing.
Step 1: Parsing the CSV Data
First, let's assume we have a leads.csv file with columns for name, city, and profile_image. We can use a standard parser to turn these into a typed array of objects.
interface Lead {
name: string;
city: string;
imageUrl: string;
}
// Imagine parsing your CSV here...
const leads: Lead[] = [
{ name: 'Sarah', city: 'London', imageUrl: 'https://assets.dev/sarah.jpg' },
{ name: 'Alex', city: 'Berlin', imageUrl: 'https://assets.dev/alex.jpg' },
];
Step 2: Defining the Video Template
Now, we create a function that takes a Lead and returns a VideoFlow instance. This is where we define the cinematic look of our ad. We'll use the VideoFlow core API to layer our visuals.
import VideoFlow from '@videoflow/core';
function createAdTemplate(lead: Lead) {
const $ = new VideoFlow({ width: 1080, height: 1920, fps: 30 });
// 1. Add a background video with a blur effect
const bg = $.addVideo(
{ fit: 'cover', opacity: 0.8 },
{ source: 'https://assets.dev/marketing-bg.mp4' }
);
// 2. Add the personalized lead image
const avatar = $.addImage(
{
position: [0.5, 0.4],
scale: 0.8,
effects: [{ effect: 'bloom', params: { strength: 0.4 } }]
},
{
source: lead.imageUrl,
transitionIn: { transition: 'blurResolve', duration: '800ms' }
}
);
// 3. Add personalized text with normalized coordinates
const title = $.addText({
text: `Hey ${lead.name}!`,
fontSize: 8, // 8% of project width
color: '#FF5A1F',
position: [0.5, 0.65],
fontWeight: 700
});
title.fadeIn('500ms');
$.wait('3s');
title.fadeOut('500ms');
return $;
}
In the snippet above, notice how we use normalized coordinates ([0.5, 0.65]) and em-based sizing (fontSize: 8). This ensures that if you decide to change your ad from a vertical TikTok format to a square Instagram post, your layout remains perfectly scaled without manual math.
Step 3: Batch Rendering on the Server
With our template ready, we can loop through our CSV data and trigger the server-side renderer. VideoFlow's @videoflow/renderer-server uses headless Chromium via Playwright, meaning it handles complex GLSL effects and WebCodecs without requiring you to manage local FFmpeg binaries.
import '@videoflow/renderer-server';
async function runBatch() {
for (const lead of leads) {
const $ = createAdTemplate(lead);
const filename = `ad-${lead.name.toLowerCase()}.mp4`;
console.log(`Rendering ${filename}...`);
await $.renderVideo({
outputType: 'file',
output: `./renders/${filename}`,
});
}
}
Why VideoFlow for Ad Personalization?
Automating video at scale requires a tool that is both developer-friendly and visually capable. While you could attempt this with FFmpeg, you would lose access to high-level cinematic primitives like the 27 built-in transitions and 42 GLSL effects that VideoFlow provides out of the box.

Compared to proprietary platforms, VideoFlow is Apache-2.0 open source. This means you own your pipeline entirely. There are no per-render fees, no vendor lock-in, and you can run the rendering logic on your own infrastructure—whether that's a Lambda function, a dedicated GPU server, or even directly in the user's browser using @videoflow/renderer-browser.
For teams that need to build an internal tool for their marketing department, you can even drop in the React Video Editor. It allows non-technical users to tweak the template visually while still saving the result as the same portable VideoJSON your automated pipeline uses.
Conclusion
Generating personalized video ads from a CSV transforms video from a creative bottleneck into a scalable data asset. By leveraging TypeScript and VideoFlow, you can build a robust automation engine that delivers high-quality, cinematic content to every lead in your database.
Ready to start building? Head over to the VideoFlow GitHub to see the source, or try out your first template in the interactive Playground.