Org Status: π‘ Dormant Cloudflare: N/A Last Audited: 2026-04-28
Every day, faceless finance channels earn $300-$1,000 from videos nobody appeared in, nobody manually edited, and nobody spent more than $0.01 to render. The difference between creators who earn and creators who quit is not talent or equipment β it is a system. This guide is that system.
What you will learn:
- The economics that make programmatic video production a $10K/month business
- How to find trending topics before they peak and connect them to high-RPM niches
- The exact script formulas that drive 60%+ retention on short-form and long-form
- Two complete render pipelines: local FFmpeg ($0.01/video) and cloud API ($0.30-$6/video)
- Full working code for every step from script generation to finished MP4
- Platform-specific optimization for TikTok, YouTube, Instagram, and Content Rewards
- How to scale from 1 video/day to 10+ with AI agents and automation
- Compliance rules that keep your channels monetized and your content legal
- The Economics of Viral Video
- The Trend-First Content Model
- The Million-Dollar Script Formula
- Visual Language and Production Design
- The Render Pipeline
- The Hybrid Machine: Shorts Feed Longs
- Platform-Specific Optimization
- Niche Selection Matrix
- Scaling with AI Agents
- Monetization Playbook
- Compliance and Risk
- The First Video Checklist
- Comparisons
- Anti-Patterns
- References
The economics of programmatic video are unlike any other content format. The production cost approaches zero while the revenue scales linearly with views. No inventory. No fulfillment. No customer support. Just views converted to dollars.
Revenue Per Mille (RPM) by Platform
| Platform | Format | RPM Range | Notes |
|---|---|---|---|
| YouTube (finance) | Long-form (8-15 min) | $9-$25 | Highest RPM of any niche. Q4 peaks at $18-$30+ |
| YouTube (finance) | Shorts | $0.05-$0.15 | Low RPM but high volume, funnel to long-form |
| TikTok Creator Rewards | 1+ min videos | $0.40-$2.00 | Qualified views only (5s+ watch, FYP, unique) |
| TikTok Creator Fund (legacy) | Any length | $0.02-$0.04 | Nearly worthless, replaced by Creator Rewards |
| Content Rewards | Short-form UGC | $1-$2.50 | Per 1K views, brand campaigns, no audience needed |
| Instagram Reels | Short-form | $0.10-$0.50 | Inconsistent, better as traffic driver |
Cost Per Video
| Method | Cost | Quality | Speed |
|---|---|---|---|
| Local FFmpeg + edge-tts | $0.01 | Medium (robotic voice, basic compositing) | 30-60 seconds |
| Local FFmpeg + ElevenLabs | $0.15-$0.50 | High (natural voice, basic compositing) | 30-90 seconds |
| Creatomate + ElevenLabs | $0.50-$2.00 | High (natural voice, animations, captions) | 2-5 minutes |
| Creatomate + ElevenLabs (long-form) | $2.00-$6.00 | Production (full 10-min video) | 5-15 minutes |
| Remotion + ElevenLabs | $0.01-$0.50 | High (React components, custom animations) | 1-5 minutes |
| Manual (CapCut/Premiere) | $0 (time cost) | Highest | 2-8 hours |
The Math That Matters
Scenario: Finance niche, 10 short-form videos per day, 2 long-form per week.
Short-form (TikTok + Content Rewards):
10 videos/day x 30 days = 300 videos/month
Average 500 views/video = 150,000 views/month
TikTok Creator Rewards: 150K views x $0.80 RPM = $120/month
Content Rewards (top 50 videos): 50K views x $1.50 RPM = $75/month
Long-form (YouTube):
8 videos/month
Average 6,250 views/video = 50,000 views/month
Finance RPM: 50K views x $12 RPM = $600/month
Production cost:
300 short-form x $0.01 (local FFmpeg) = $3/month
8 long-form x $2.00 (Creatomate) = $16/month
ElevenLabs subscription = $22/month
Total: $41/month
Net: $795/month - $41/month = $754/month profit (95% margin)
At 500K views/month on YouTube alone (achievable within 6-12 months of consistent posting), the math shifts dramatically:
YouTube long-form: 500K views x $15 RPM (finance avg) = $7,500/month
TikTok shorts: 500K views x $0.80 RPM = $400/month
Content Rewards: 100K views x $1.50 RPM = $150/month
Affiliate links: $500-$2,000/month (finance products)
Sponsor integrations: $1,000-$5,000/month
Total: $9,550-$15,050/month
Cost: $100-$200/month (tools + API calls)
Key insight: The unit economics of programmatic video are absurd. A $0.01 video that gets 10,000 views generates $120 in YouTube finance RPM. That is a 1,200,000% return on production cost. The bottleneck is never cost β it is distribution and quality.
Revenue Stacking
No single revenue stream hits $10K/month easily. The strategy is to stack:
Layer 1: YouTube AdSense (long-form) $3,000-$7,500
Layer 2: TikTok Creator Rewards (shorts) $200-$800
Layer 3: Content Rewards campaigns $100-$500
Layer 4: Affiliate links (finance products) $500-$2,000
Layer 5: Sponsor integrations $500-$5,000
Layer 6: Funnel to owned products $500-$3,000
(calculators, tools, courses)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Total potential: $4,800-$18,800/month
Why Asset-First Fails
Most creators start with their content and try to find an audience for it. This is backwards.
Asset-first (broken):
"I have an LLC cost calculator" β "Let me make a video about LLC costs"
β Posts to TikTok β 47 views β "TikTok doesn't work"
Trend-first (works):
"LLC formation is trending on TikTok" β "Let me ride this wave"
β Creates content matching the trend format β 47,000 views
β Links to LLC calculator in bio β 200 tool page visits
Nobody searches TikTok for βLLC break-even calculator.β They scroll past videos about money, business failures, side hustles, and financial traps. The content that performs is content that matches what people are already watching, with your expertise woven in as the payoff.
The Trend Intelligence Stack
interface TrendSource {
name: string;
type: 'api' | 'manual' | 'scrape';
latency: string; // How quickly you get signal
cost: string;
signalQuality: 'high' | 'medium' | 'low';
}
const trendSources: TrendSource[] = [
{
name: 'Virlo API',
type: 'api',
latency: 'real-time',
cost: '$49-$199/month',
signalQuality: 'high',
// 2M+ indexed videos, 500K+ hashtags
// 7-dimension intelligence reports
// Viral outlier detection
// Early trend alerts before mainstream saturation
},
{
name: 'TikTok Discover (manual)',
type: 'manual',
latency: '1-2 hours',
cost: 'free',
signalQuality: 'medium',
// Check trending sounds, hashtags, formats
// Note: trends have 24-72 hour windows
},
{
name: 'YouTube Trending API',
type: 'api',
latency: 'hourly',
cost: 'free (quota)',
signalQuality: 'medium',
// YouTube Data API v3 trending endpoint
// Filter by category (finance, education, etc.)
},
{
name: 'Twitter/X Trending',
type: 'api',
latency: 'real-time',
cost: 'API tier dependent',
signalQuality: 'medium',
// Cross-platform signal: X trends predict TikTok trends by 12-24 hours
},
{
name: 'Google Trends',
type: 'api',
latency: 'daily',
cost: 'free',
signalQuality: 'low',
// Lagging indicator β by the time it shows up here, the TikTok wave is half over
},
];
The Angle: Connecting Trends to Your Niche
The magic is not finding trends. The magic is connecting trends to high-RPM niches. Finance content earns 5-10x more per view than entertainment content. Your job is to take whatever is trending and frame it through a finance lens.
interface TrendAngle {
trend: string;
nicheConnection: string;
hookExample: string;
rpm: string;
}
const angleExamples: TrendAngle[] = [
{
trend: 'Celebrity bankruptcy filing',
nicheConnection: 'LLC asset protection',
hookExample: '"[Celebrity] lost everything. An LLC would have saved $4.2 million."',
rpm: '$12-$18',
},
{
trend: 'Tech layoffs wave',
nicheConnection: 'Side hustle LLC formation',
hookExample: '"Google laid off 12,000 people. Here is how to never depend on a paycheck again."',
rpm: '$10-$15',
},
{
trend: 'New tax law passed',
nicheConnection: 'Direct tax content',
hookExample: '"This new law saves LLC owners $3,200 per year. Most accountants won\'t tell you."',
rpm: '$15-$25',
},
{
trend: 'Viral "money saving hack" video',
nicheConnection: 'Debunk with real numbers',
hookExample: '"This viral money hack is wrong. Here is the actual math."',
rpm: '$12-$20',
},
];
Speed Matters: The Trend Window
Hour 0: Trend emerges on X/Twitter or TikTok
Hour 6: Early creators notice it
Hour 12: First wave of content appears
Hour 24: Peak engagement window OPENS
Hour 48: Peak engagement window
Hour 72: Peak engagement window CLOSES
Hour 96: Trend is saturated, late entries get minimal views
Hour 168: Trend is dead, evergreen pivot only
Your pipeline must produce a finished video within 2-4 hours of identifying a trend. Manual editing takes 2-8 hours. Programmatic rendering takes 5-30 minutes. The speed advantage is existential.
Key insight: The trend-first model inverts the content creation process. Instead of βwhat do I want to say?β the question becomes βwhat does the audience want to hear right now, and how does my expertise add value to that conversation?β This is not pandering β it is relevance.
Long-Form: The 4-Act Structure
The highest-performing faceless YouTube videos follow a predictable 4-act structure. This is not theory β it maps to retention curves across thousands of finance videos.
interface LongFormScript {
/** Act 1: The Drop (0:00 - 0:30) */
theDrop: {
shockingResult: string; // Start with the outcome, not the setup
openLoop: string; // Create a question the viewer MUST answer
retention: '85-95%'; // Target: lose less than 15% in first 30s
};
/** Act 2: The Ascent (0:30 - 3:30) */
theAscent: {
origins: string; // How did we get here?
successPeriod: string; // The "everything was great" setup
dataPoints: string[]; // 3-5 specific numbers
retention: '65-80%';
};
/** Act 3: The Pivot/Crash (3:30 - 7:00) */
thePivot: {
hiddenMechanics: string; // What nobody tells you
dataVisualization: string; // Charts, comparisons, calculations
tension: string; // Build to "wait, what?"
retention: '55-70%';
};
/** Act 4: The Synthesis (7:00 - 8:30) */
theSynthesis: {
broaderImplications: string; // What this means for YOU
closeLoop: string; // Answer the question from Act 1
cta: string; // Subtle, value-driven
retention: '45-60%';
};
}
Example: βThe LLC Cost Trap Nobody Talks Aboutβ (8 minutes)
ACT 1 β THE DROP (0:00 - 0:30)
"Filing an LLC costs $50. Running one costs $4,000. And most of that
money goes to people who do nothing for you. Here's the breakdown
nobody in the LLC industry wants you to see."
[Visual: Dark background. Red "$4,000" flashes. Calculator animation.]
ACT 2 β THE ASCENT (0:30 - 3:30)
"When you first hear about LLCs, it sounds perfect. $50 filing fee.
Asset protection. Tax benefits. Every business guru tells you to
form one yesterday. But they always leave out the recurring costs..."
- State filing fee: $50-$500
- Registered agent: $100-$300/year
- EIN filing: free (but services charge $200)
- Operating agreement: free template vs. $2,000 lawyer
- Annual reports: $0-$800/year
[Visual: State-by-state map. Cost breakdown appearing line by line.]
ACT 3 β THE PIVOT (3:30 - 7:00)
"But here's where it gets interesting. California charges $800/year
just for the privilege of existing as an LLC. Even if you made zero
dollars. Wyoming charges $50 once. Same legal protection. That's a
$3,200 difference over 4 years for the exact same entity."
[Visual: Side-by-side comparison. California vs. Wyoming. Running total.]
"And the registered agent industry? $300/year for a service that
receives maybe 2 pieces of mail. That's $150 per envelope."
ACT 4 β THE SYNTHESIS (7:00 - 8:30)
"The LLC itself isn't expensive. The ecosystem around it is. Pick the
right state. Use free EIN filing. Template operating agreement. And
skip the $300 registered agent if you can use your own address. Total
first-year cost: under $200 instead of $4,000. Link in the description
for the free calculator that runs these numbers for your state."
[Visual: Side-by-side: $4,000 vs. $200. Calculator preview.]
Short-Form: The 60-Second Formula
Short-form scripts follow a compressed version. Every second earns its place.
interface ShortFormScript {
/** Hook: first 1-3 seconds */
hook: {
text: string; // 3-7 words on screen
narration: string; // Shocking stat or provocative claim
rule: 'Must stop the scroll in under 1 second';
};
/** Context: 3-10 seconds */
trendContext: {
narration: string; // Connect to what's trending
rule: 'Establish relevance to current conversation';
};
/** Value: 10-45 seconds */
valueBomb: {
points: string[]; // 3-5 rapid-fire facts with specific numbers
rule: 'Each sentence = one visual beat. No filler.';
};
/** CTA: last 3-5 seconds */
cta: {
text: string; // On-screen CTA
narration: string; // Engagement driver
rule: 'Follow, comment, or link-in-bio. Pick one.';
};
}
Rules for short-form scripts:
- Hook in 1 second (the βscroll stopperβ)
- No filler words ever (βhey guysβ, βso basicallyβ, βalright soβ)
- Each sentence = one visual beat (when narration changes, visual changes)
- Specific numbers always ($3,200, not βthousandsβ)
- No more than 200 words for a 60-second video (speak at 180 WPM)
- End with engagement, not information
The LLM Prompt Chain
Script generation is a three-step process, not a single prompt. Each step has a specific role and a specific output format.
Step 1: Fact Retrieval and Structuring
const factRetrievalPrompt = `You are a financial research assistant. Your job is to gather
and structure factual data about a topic for a video script.
TOPIC: {{topic}}
TREND CONTEXT: {{trendContext}}
NICHE: {{niche}}
Output a JSON array of facts. Each fact must include:
- "claim": the factual statement
- "number": the specific number (always use exact figures)
- "source": where this fact comes from
- "surprise_factor": 1-10 (how unexpected is this for the average viewer?)
Return 8-12 facts, sorted by surprise_factor descending.
RULES:
- Every claim must include a specific number
- No approximations ("about", "around", "roughly")
- No opinions β only verifiable facts
- Prefer counterintuitive facts (things people assume wrong)
Example output:
[
{
"claim": "California charges an $800 annual franchise tax even if LLC revenue is $0",
"number": "$800",
"source": "California Franchise Tax Board",
"surprise_factor": 9
}
]`;
Step 2: Hook and Open-Loop Generation
const hookGenerationPrompt = `You are a viral video hook specialist. Your job is to write
the first 30 seconds of a video that achieves 85%+ retention.
FACTS (from research step):
{{factsJson}}
TREND CONTEXT: {{trendContext}}
FORMAT: {{format}} (short-form: 3 seconds | long-form: 30 seconds)
For SHORT-FORM, output:
{
"screen_text": "3-7 word text overlay (ALL CAPS, punchy)",
"narration": "1-2 sentences that make the viewer NEED to keep watching",
"open_loop": "The implicit question the viewer must answer"
}
For LONG-FORM, output:
{
"shocking_result": "Start with the END result β the most surprising fact",
"contrast": "Juxtapose expectation vs. reality",
"open_loop": "Explicit question or 'here is what nobody tells you' frame",
"narration": "Full 30-second narration (50-75 words)"
}
HOOK FORMULAS (pick one):
1. "X costs $Y. But actually it costs $Z." (cost reveal)
2. "Everyone says X. They're wrong." (myth bust)
3. "[Specific person/company] just [shocking action]. Here's why." (news hook)
4. "I analyzed N [things]. Only M got it right." (data authority)
5. "$X,XXX in Y seconds. Here's how." (result first)
RULES:
- First word must grab attention (number, name, or "this")
- Never start with "hey", "so", "did you know", or any greeting
- Include at least one specific number in the first sentence
- The open loop must create genuine curiosity, not clickbait`;
Step 3: Body and Pacing Generation
const bodyGenerationPrompt = `You are a video scriptwriter who creates retention-optimized
scripts for faceless finance content.
HOOK (from previous step):
{{hookJson}}
FACTS (from research step):
{{factsJson}}
FORMAT: {{format}}
TARGET DURATION: {{durationSeconds}} seconds
TARGET WORD COUNT: {{Math.round(durationSeconds * 3)}} words (at 180 WPM)
OUTPUT FORMAT:
{
"scenes": [
{
"timestamp": "0:00-0:03",
"narration": "The spoken text for this scene",
"visual_directive": "Description of what should appear on screen",
"text_overlay": "Any text that appears on screen (null if none)",
"transition": "cut | fade | zoom | slide"
}
],
"total_words": number,
"estimated_duration_seconds": number,
"stock_footage_keywords": ["keyword1", "keyword2"]
}
PACING RULES:
- Scene changes every 3-5 seconds (short-form) or 8-15 seconds (long-form)
- Visual directive must change with each new fact
- Text overlays for NUMBERS only (show the $X,XXX on screen)
- Transitions: 80% cuts, 15% zooms, 5% fades (never slide for finance)
- Pattern interrupt every 90 seconds in long-form (unexpected visual, tone shift, question)
NARRATION RULES:
- Short sentences (8-15 words average)
- One idea per sentence
- Active voice only ("California charges" not "you are charged by California")
- Conversational but authoritative (no "um", no hedging, no "I think")
- Specific numbers spoken as words ("three thousand two hundred" not "3,200")
but displayed as numerals on screen
VISUAL DIRECTIVE RULES:
- Dark background default (#0B0C10)
- Numbers appear in accent color (#00FF00 or #FFD700)
- Comparison visuals: side-by-side, never sequential
- No human faces unless the subject of the video
- Stock footage: abstract business, money, documents (never cheesy handshakes)`;
Key insight: The prompt chain matters because each step produces structured output that feeds the next step. Single-prompt scripts are inconsistent. The chain gives you: (1) verified facts with surprise ranking, (2) a hook engineered for retention, (3) a paced script with visual directives that map directly to your render pipeline.
The Finance Aesthetic
Finance content that performs follows a specific visual language. It is not accidental β it signals authority and creates urgency.
interface VisualSystem {
palette: {
background: '#0B0C10'; // Deep Void β dark, cinematic
primary: '#C5C6C7'; // Light gray text
accent1: '#00FF00'; // Terminal Green β for money/positive numbers
accent2: '#FFD700'; // Gold β for highlights
warning: '#FF3B30'; // Warning Red β for costs/dangers
surface: '#1F2833'; // Slightly lighter surface
};
typography: {
headline: 'Inter Black'; // Bold, geometric, modern
data: 'JetBrains Mono'; // Monospace for numbers and data
body: 'Inter Regular'; // Clean reading
caption: 'Courier New'; // Terminal aesthetic for overlays
};
motion: {
textEntry: 'slide-up 0.3s ease-out';
numberCount: 'count-up 0.8s linear';
sceneTransition: 'cut'; // Hard cuts, not dissolves
emphasis: 'scale(1.1) 0.2s'; // Subtle pulse on key numbers
};
}
The Color Rules
Background: ALWAYS dark (#0B0C10 or #1a1a2e)
Never white. Never light gray. Dark = authority in finance.
Money UP: Terminal Green (#00FF00) or Gold (#FFD700)
Use when showing positive numbers, gains, savings
Money DOWN: Warning Red (#FF3B30)
Use when showing costs, losses, traps, fees
Comparisons: Green vs. Red side-by-side
The viewer's eye immediately understands the story
Text: White (#FFFFFF) or light gray (#C5C6C7)
High contrast on dark background. No colored body text.
Accents: Use sparingly. One accent color per scene maximum.
Too many colors = cheap. Restraint = premium.
The 3-Second Rule
Every video starts in media res. No logos, no intros, no βwelcome to my channel.β The first frame is already content.
BAD first 3 seconds:
[Logo animation] β [Channel name] β [Subscribe reminder]
Result: 40% drop in first 3 seconds
GOOD first 3 seconds:
[Dark screen] β [Red "$4,000" fills screen] β [Voice: "Filing an LLC costs $50..."]
Result: 5% drop in first 3 seconds
Pattern Interrupts (Long-Form)
Retention drops steadily in long-form content unless you interrupt the pattern every 60-90 seconds. Each interrupt resets the viewerβs attention.
const patternInterrupts = [
{
type: 'visual_shift',
description: 'Change the background color or scene composition dramatically',
when: 'Every 60-90 seconds',
example: 'Switch from dark bg to a stock footage montage for 3 seconds',
},
{
type: 'rhetorical_question',
description: 'Ask a question the viewer answers internally',
when: 'Before introducing a new major point',
example: '"But here is the question nobody asks: why does it cost that much?"',
},
{
type: 'number_reveal',
description: 'Build up to a surprising number, then reveal it with animation',
when: 'At the climax of each data point',
example: 'Count-up animation from $0 to $3,200',
},
{
type: 'contrast_cut',
description: 'Jump-cut between two opposing visuals',
when: 'When comparing two options',
example: 'California flag ($800/yr) β Wyoming flag ($50 once)',
},
{
type: 'silence_beat',
description: '0.5-1 second of silence after a major claim',
when: 'After the most surprising fact in each section',
example: '"...even if you made zero dollars." [0.8s silence] "And it gets worse."',
},
];
Stock Footage Treatment
Raw stock footage looks generic. The treatment makes it yours.
Filter chain (FFmpeg):
1. Darken: brightness=-0.15
2. Contrast boost: contrast=1.2
3. Color temperature: cool shift (blues)
4. Vignette: subtle edge darkening
5. Grain: add film grain overlay at 10% opacity
6. Speed: 1.2x-1.5x (stock footage always feels slow)
FFmpeg command:
-vf "eq=brightness=-0.15:contrast=1.2,\
colorbalance=bs=0.1:ms=0.05,\
vignette=PI/4,\
noise=alls=10:allf=t,\
setpts=PTS/1.3"
Thumbnail Design Principles
Thumbnails are the other half of the click decision. For faceless finance content:
Rules:
1. Maximum 4 words (6 absolute max)
2. One dominant color against dark background
3. Number must be visible at thumbnail size (mobile)
4. No human faces (unless the subject β e.g., celebrity bankruptcy)
5. High contrast: text must pop at 120x90px (mobile search)
6. Warning Red for negative topics, Gold for positive topics
Layout:
ββββββββββββββββββββββββ
β β
β $4,000 β β Large number in accent color
β LLC TRAP β β 2-3 word title in white
β β
β [icon] β β Simple icon (calculator, warning, etc.)
ββββββββββββββββββββββββ
Two paths exist. Choose based on your quality needs, budget, and scale.
Path A: Local FFmpeg ($0.01/video)
This is the zero-cost path. It uses free TTS, free stock footage, and local GPU rendering. Quality is lower than cloud rendering but sufficient for TikTok and testing.
Hardware requirements:
- Any modern GPU (NVIDIA RTX 3060+ recommended, RTX 4070 ideal)
- 16GB+ RAM
- FFmpeg compiled with NVENC support
- Python 3.10+ or Node.js 20+
The Stack:
Script (JSON) β edge-tts (free TTS) β Pexels API (stock footage)
β FFmpeg composite β MP4 (1080x1920 for shorts, 1920x1080 for longs)
Complete produce.py β Topic to Finished MP4:
#!/usr/bin/env python3
"""
produce.py β Generate a complete short-form video from a topic.
Dependencies: pip install edge-tts httpx openai pydub
System: ffmpeg with NVENC support
"""
import asyncio
import json
import subprocess
import tempfile
from pathlib import Path
from dataclasses import dataclass
from typing import Optional
import edge_tts
import httpx
PEXELS_API_KEY = "YOUR_PEXELS_API_KEY" # Free at pexels.com/api
OPENAI_API_KEY = "YOUR_OPENAI_API_KEY" # Or use any OpenAI-compatible API
OUTPUT_DIR = Path("./output")
OUTPUT_DIR.mkdir(exist_ok=True)
BG_COLOR = "0x0B0C10"
ACCENT_COLOR = "0x00FF00"
WARNING_COLOR = "0xFF3B30"
TEXT_COLOR = "0xFFFFFF"
FONT_PATH = "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf"
VOICE = "en-US-GuyNeural" # Male, authoritative
WIDTH, HEIGHT = 1080, 1920 # 9:16 portrait
@dataclass
class VideoScene:
timestamp: str
narration: str
visual_directive: str
text_overlay: Optional[str]
stock_keyword: str
@dataclass
class VideoScript:
title: str
hook_text: str
cta_text: str
scenes: list[VideoScene]
hashtags: list[str]
async def generate_script(topic: str, trend_context: str) -> VideoScript:
"""Generate a structured video script using an LLM."""
client = httpx.AsyncClient()
prompt = f"""You are a viral finance video scriptwriter. Create a 45-60 second
TikTok script about: {topic}
Trend context: {trend_context}
Output ONLY valid JSON with this structure:
{{
"title": "Video title for posting",
"hook_text": "3-5 word screen text for first 3 seconds (ALL CAPS)",
"cta_text": "CTA text for last 3 seconds",
"scenes": [
{{
"timestamp": "0:00-0:05",
"narration": "Spoken text for this scene",
"visual_directive": "What appears on screen",
"text_overlay": "$X,XXX number overlay or null",
"stock_keyword": "one keyword for stock footage search"
}}
],
"hashtags": ["hashtag1", "hashtag2"]
}}
RULES:
- 6-8 scenes total, each 5-8 seconds
- Total narration: 130-160 words (45-55 seconds at 180 WPM)
- Hook in scene 1: shocking number or provocative claim
- Every scene has a different stock_keyword
- text_overlay only for numbers (show dollars/percentages)
- CTA: "Follow for more" or "Link in bio" style
- No filler words, no greetings, no "hey guys"
- Use specific numbers, never approximations"""
response = await client.post(
"https://api.openai.com/v1/chat/completions",
headers={"Authorization": f"Bearer {OPENAI_API_KEY}"},
json={
"model": "gpt-4o-mini",
"messages": [{"role": "user", "content": prompt}],
"response_format": {"type": "json_object"},
"temperature": 0.7,
},
timeout=30.0,
)
data = response.json()["choices"][0]["message"]["content"]
parsed = json.loads(data)
scenes = [
VideoScene(
timestamp=s["timestamp"],
narration=s["narration"],
visual_directive=s["visual_directive"],
text_overlay=s.get("text_overlay"),
stock_keyword=s["stock_keyword"],
)
for s in parsed["scenes"]
]
return VideoScript(
title=parsed["title"],
hook_text=parsed["hook_text"],
cta_text=parsed["cta_text"],
scenes=scenes,
hashtags=parsed.get("hashtags", []),
)
async def generate_tts(text: str, output_path: Path) -> float:
"""Generate TTS audio using Microsoft Edge's free TTS service.
Returns duration in seconds."""
communicate = edge_tts.Communicate(text, VOICE, rate="+10%")
await communicate.save(str(output_path))
# Get duration via ffprobe
result = subprocess.run(
["ffprobe", "-v", "error", "-show_entries", "format=duration",
"-of", "default=noprint_wrappers=1:nokey=1", str(output_path)],
capture_output=True, text=True,
)
return float(result.stdout.strip())
async def search_stock_video(keyword: str) -> Optional[str]:
"""Search Pexels for vertical stock video. Returns download URL."""
async with httpx.AsyncClient() as client:
response = await client.get(
"https://api.pexels.com/videos/search",
params={"query": keyword, "per_page": 3, "orientation": "portrait"},
headers={"Authorization": PEXELS_API_KEY},
)
if response.status_code != 200:
return None
videos = response.json().get("videos", [])
if not videos:
return None
# Pick best quality MP4, prefer closest to 1080p height
video = videos[0]
files = sorted(
[f for f in video["video_files"] if f["file_type"] == "video/mp4"],
key=lambda f: abs(f.get("height", 0) - 1920),
)
return files[0]["link"] if files else None
async def download_video(url: str, output_path: Path) -> None:
"""Download a video file to disk."""
async with httpx.AsyncClient(follow_redirects=True) as client:
response = await client.get(url)
output_path.write_bytes(response.content)
def composite_video(
audio_path: Path,
clips: list[Path],
hook_text: str,
cta_text: str,
text_overlays: list[Optional[str]],
output_path: Path,
duration: float,
) -> None:
"""Composite stock clips with audio, text overlays, and captions."""
# Calculate clip duration (divide total duration evenly)
clip_duration = duration / max(len(clips), 1)
# Build FFmpeg filter complex
inputs = []
filter_parts = []
# Input: audio
inputs.extend(["-i", str(audio_path)])
# Input: each stock clip
for i, clip in enumerate(clips):
inputs.extend(["-i", str(clip)])
# Trim and scale each clip, apply visual treatment
for i in range(len(clips)):
input_idx = i + 1 # 0 is audio
start = i * clip_duration
filter_parts.append(
f"[{input_idx}:v]"
f"trim=0:{clip_duration},setpts=PTS-STARTPTS,"
f"scale={WIDTH}:{HEIGHT}:force_original_aspect_ratio=increase,"
f"crop={WIDTH}:{HEIGHT},"
f"eq=brightness=-0.15:contrast=1.2,"
f"setpts=PTS/1.2"
f"[clip{i}]"
)
# Concatenate clips
concat_inputs = "".join(f"[clip{i}]" for i in range(len(clips)))
filter_parts.append(
f"{concat_inputs}concat=n={len(clips)}:v=1:a=0[bgvideo]"
)
# Add hook text overlay (first 3 seconds)
filter_parts.append(
f"[bgvideo]drawtext="
f"fontfile={FONT_PATH}:"
f"text='{hook_text}':"
f"fontcolor=white:"
f"fontsize=72:"
f"x=(w-text_w)/2:y=h*0.15:"
f"enable='between(t,0,3)'"
f"[withhook]"
)
# Add CTA text overlay (last 4 seconds)
cta_start = max(0, duration - 4)
filter_parts.append(
f"[withhook]drawtext="
f"fontfile={FONT_PATH}:"
f"text='{cta_text}':"
f"fontcolor=white:"
f"fontsize=56:"
f"box=1:boxcolor={WARNING_COLOR}@0.8:boxborderw=15:"
f"x=(w-text_w)/2:y=h*0.40:"
f"enable='between(t,{cta_start},{duration})'"
f"[final]"
)
filter_complex = ";".join(filter_parts)
cmd = [
"ffmpeg", "-y",
*inputs,
"-filter_complex", filter_complex,
"-map", "[final]",
"-map", "0:a",
"-c:v", "h264_nvenc", # NVIDIA GPU encoding
"-preset", "p4",
"-b:v", "8M",
"-c:a", "aac",
"-b:a", "192k",
"-shortest",
"-movflags", "+faststart",
str(output_path),
]
subprocess.run(cmd, check=True, capture_output=True)
async def produce(topic: str, trend_context: str = "") -> Path:
"""Full pipeline: topic -> finished MP4."""
print(f"[1/4] Generating script for: {topic}")
script = await generate_script(topic, trend_context)
print(f" Title: {script.title}")
print(f" Scenes: {len(script.scenes)}")
# Generate TTS for full narration
print("[2/4] Generating TTS audio...")
full_narration = " ".join(scene.narration for scene in script.scenes)
audio_path = OUTPUT_DIR / "narration.mp3"
duration = await generate_tts(full_narration, audio_path)
print(f" Duration: {duration:.1f}s")
# Search and download stock footage for each scene
print("[3/4] Downloading stock footage...")
clip_paths: list[Path] = []
text_overlays: list[Optional[str]] = []
for i, scene in enumerate(script.scenes):
url = await search_stock_video(scene.stock_keyword)
if url:
clip_path = OUTPUT_DIR / f"clip_{i}.mp4"
await download_video(url, clip_path)
clip_paths.append(clip_path)
text_overlays.append(scene.text_overlay)
print(f" Scene {i}: '{scene.stock_keyword}' -> downloaded")
else:
print(f" Scene {i}: '{scene.stock_keyword}' -> no footage found")
if not clip_paths:
raise RuntimeError("No stock footage found for any scene")
# Composite final video
print("[4/4] Compositing final video...")
output_path = OUTPUT_DIR / f"{topic.lower().replace(' ', '-')}.mp4"
composite_video(
audio_path=audio_path,
clips=clip_paths,
hook_text=script.hook_text,
cta_text=script.cta_text,
text_overlays=text_overlays,
output_path=output_path,
duration=duration,
)
print(f"\nDone! Output: {output_path}")
print(f"Title: {script.title}")
print(f"Hashtags: {' '.join('#' + h for h in script.hashtags)}")
# Save script metadata
meta_path = output_path.with_suffix(".json")
meta_path.write_text(json.dumps({
"title": script.title,
"hook_text": script.hook_text,
"cta_text": script.cta_text,
"hashtags": script.hashtags,
"duration": duration,
"scenes": [
{
"timestamp": s.timestamp,
"narration": s.narration,
"text_overlay": s.text_overlay,
"stock_keyword": s.stock_keyword,
}
for s in script.scenes
],
}, indent=2))
return output_path
if __name__ == "__main__":
import sys
topic = sys.argv[1] if len(sys.argv) > 1 else "LLC cost breakdown"
trend = sys.argv[2] if len(sys.argv) > 2 else "small business formation trending"
asyncio.run(produce(topic, trend))
Path B: Cloud API (Creatomate β $0.30-$6/video)
The cloud path trades cost for quality. Creatomate handles TTS (via ElevenLabs integration), animated captions, text overlays, transitions, and final rendering β all via a single API call.
The Stack:
Script (JSON) β buildRenderScript() β Creatomate POST /renders
β webhook notification β download MP4 from Creatomate CDN
Complete video-renderer.ts β Production-Grade Cloud Rendering:
/**
* video-renderer.ts β Dual backend: local (FFmpeg) or Creatomate cloud.
*
* Local flow: script JSON β POST /render/async β poll /status/<id> β MP4
* Cloud flow: script JSON β RenderScript β Creatomate POST /renders β webhook β MP4
*/
// --- Types ---
export interface VideoScript {
/** Brand slug for attribution */
brand_slug: string;
/** Social account handle */
handle: string;
/** Unique draft ID */
draft_id: string;
/** The narration text (read aloud via TTS) */
narration: string;
/** Hook text overlay (first 3 seconds) */
hook_text: string;
/** CTA text overlay (last 3 seconds) */
cta_text: string;
/** Background video URL (Pexels or similar) */
background_url?: string;
/** Brand color hex */
brand_color?: string;
/** Scene-level breakdown for complex videos */
scenes?: SceneConfig[];
}
export interface SceneConfig {
narration: string;
text_overlay?: string;
background_url?: string;
duration?: number;
}
export interface RenderResponse {
id: string;
status: 'planned' | 'rendering' | 'succeeded' | 'failed';
url?: string;
error_message?: string;
}
// --- RenderScript Builder ---
/**
* Build a Creatomate RenderScript for a short-form vertical video.
* Output: 1080x1920 (9:16), up to 90 seconds, voiceover + captions + background.
*/
export function buildRenderScript(
script: VideoScript,
webhookUrl: string
): Record<string, unknown> {
const brandColor = script.brand_color || '#1a1a2e';
const accentColor = '#e94560';
const elements: Record<string, unknown>[] = [
// Background β video if provided, solid color fallback
...(script.background_url
? [
{
type: 'video',
track: 1,
source: script.background_url,
fit: 'cover',
color_filter: [{ type: 'brightness', value: '60%' }],
},
]
: [
{
type: 'shape',
track: 1,
fill_color: brandColor,
},
]),
// Voiceover via ElevenLabs (built into Creatomate)
{
name: 'Voiceover',
type: 'audio',
track: 2,
provider:
'elevenlabs model_id=eleven_multilingual_v2 voice_id=pNInz6obpgDQGcFmaJgB stability=0.5 similarity_boost=0.75',
source: script.narration,
},
// Auto-synced captions from voiceover
{
type: 'text',
track: 3,
y: '75%',
width: '90%',
height: '20%',
x_alignment: '50%',
y_alignment: '50%',
fill_color: '#ffffff',
stroke_color: '#000000',
stroke_width: '0.8 vmin',
font_family: 'Montserrat',
font_weight: '800',
font_size: '6.5 vmin',
line_height: '150%',
text_transform: 'uppercase',
transcript_source: 'Voiceover',
transcript_effect: 'highlight',
transcript_color: accentColor,
},
// Hook text overlay (first 3 seconds)
{
type: 'text',
track: 4,
time: 0,
duration: 3,
y: '15%',
width: '85%',
height: '15%',
x_alignment: '50%',
y_alignment: '50%',
fill_color: '#ffffff',
font_family: 'Montserrat',
font_weight: '900',
font_size: '8 vmin',
text_transform: 'uppercase',
text: script.hook_text,
animations: [
{
time: 0,
duration: 0.5,
easing: 'quadratic-out',
type: 'text-slide',
scope: 'split-clip',
split: 'word',
},
{
time: 'end',
duration: 0.3,
type: 'fade',
},
],
},
// CTA text overlay (last 4 seconds)
{
type: 'text',
track: 5,
time: 'end',
duration: 4,
y: '40%',
width: '80%',
height: '10%',
x_alignment: '50%',
y_alignment: '50%',
fill_color: accentColor,
font_family: 'Montserrat',
font_weight: '700',
font_size: '5.5 vmin',
background_color: '#ffffff',
background_x_padding: '50%',
background_y_padding: '30%',
background_border_radius: '30%',
text: script.cta_text,
animations: [
{
time: 0,
duration: 0.5,
easing: 'quadratic-out',
type: 'slide',
direction: 'up',
},
],
},
];
return {
output_format: 'mp4',
width: 1080,
height: 1920,
max_duration: 90,
elements,
webhook_url: webhookUrl,
metadata: JSON.stringify({
draft_id: script.draft_id,
handle: script.handle,
brand_slug: script.brand_slug,
}),
};
}
// --- Creatomate API Client ---
const CREATOMATE_API_KEY = process.env.CREATOMATE_API_KEY!;
const CREATOMATE_BASE = 'https://api.creatomate.com/v2';
export async function submitCloudRender(
script: VideoScript,
webhookUrl: string
): Promise<RenderResponse> {
const renderScript = buildRenderScript(script, webhookUrl);
const res = await fetch(`${CREATOMATE_BASE}/renders`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${CREATOMATE_API_KEY}`,
},
body: JSON.stringify(renderScript),
});
if (!res.ok) {
const errText = await res.text();
throw new Error(`Creatomate render failed (${res.status}): ${errText}`);
}
const data = (await res.json()) as RenderResponse[] | RenderResponse;
return Array.isArray(data) ? data[0] : data;
}
// --- Local Render Backend ---
export async function submitLocalRender(
script: VideoScript,
baseUrl: string
): Promise<RenderResponse> {
// Start async render
const startRes = await fetch(`${baseUrl}/render/async`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
narration: script.narration,
hook_text: script.hook_text,
cta_text: script.cta_text,
bg_color: script.brand_color?.replace('#', '0x') || '0x1a1a2e',
background_url: script.background_url,
}),
});
if (!startRes.ok) {
const errText = await startRes.text();
throw new Error(`Local render failed (${startRes.status}): ${errText}`);
}
const { job_id } = (await startRes.json()) as { job_id: string };
// Poll for completion (max 120s)
for (let i = 0; i < 60; i++) {
await new Promise((r) => setTimeout(r, 2000));
const statusRes = await fetch(`${baseUrl}/status/${job_id}`);
if (statusRes.status === 200) {
return { id: job_id, status: 'succeeded', url: `${baseUrl}/output/${job_id}.mp4` };
}
if (statusRes.status === 500) {
const err = (await statusRes.json()) as { error: string };
throw new Error(`Local render failed: ${err.error}`);
}
// 202 = still rendering, continue polling
}
throw new Error(`Local render timed out (job_id=${job_id})`);
}
// --- Auto-Select Backend ---
export async function submitRender(
script: VideoScript,
webhookUrl: string
): Promise<RenderResponse> {
const localUrl = process.env.VIDEO_RENDER_URL;
if (localUrl) {
return submitLocalRender(script, localUrl);
}
return submitCloudRender(script, webhookUrl);
}
Stock Footage Search
Both paths need stock footage. Here is a complete search function that works with Pexels and falls back to Pixabay.
interface StockVideo {
id: string;
url: string;
width: number;
height: number;
duration: number;
source: 'pexels' | 'pixabay';
}
async function searchStockVideo(
keyword: string,
orientation: 'portrait' | 'landscape' = 'portrait'
): Promise<StockVideo | null> {
// Try Pexels first
const pexelsResult = await searchPexels(keyword, orientation);
if (pexelsResult) return pexelsResult;
// Fallback to Pixabay
return searchPixabay(keyword, orientation);
}
async function searchPexels(
keyword: string,
orientation: string
): Promise<StockVideo | null> {
const res = await fetch(
`https://api.pexels.com/videos/search?query=${encodeURIComponent(keyword)}&per_page=5&orientation=${orientation}`,
{ headers: { Authorization: process.env.PEXELS_API_KEY! } }
);
if (!res.ok) return null;
const data = await res.json() as {
videos: Array<{
id: number;
duration: number;
video_files: Array<{
quality: string;
file_type: string;
width: number;
height: number;
link: string;
}>;
}>;
};
if (!data.videos?.length) return null;
const video = data.videos[0];
const file = video.video_files
.filter((f) => f.file_type === 'video/mp4')
.sort((a, b) => Math.abs(a.height - 1920) - Math.abs(b.height - 1920))[0];
if (!file) return null;
return {
id: String(video.id),
url: file.link,
width: file.width,
height: file.height,
duration: video.duration,
source: 'pexels',
};
}
async function searchPixabay(
keyword: string,
orientation: string
): Promise<StockVideo | null> {
const pixabayOrientation = orientation === 'portrait' ? 'vertical' : 'horizontal';
const res = await fetch(
`https://pixabay.com/api/videos/?key=${process.env.PIXABAY_API_KEY}&q=${encodeURIComponent(keyword)}&per_page=5&video_type=all`
);
if (!res.ok) return null;
const data = await res.json() as {
hits: Array<{
id: number;
duration: number;
videos: {
large: { url: string; width: number; height: number };
medium: { url: string; width: number; height: number };
};
}>;
};
if (!data.hits?.length) return null;
const hit = data.hits[0];
const file = hit.videos.large || hit.videos.medium;
return {
id: String(hit.id),
url: file.url,
width: file.width,
height: file.height,
duration: hit.duration,
source: 'pixabay',
};
}
TTS Options Compared
interface TTSOption {
name: string;
cost: string;
quality: 'low' | 'medium' | 'high' | 'premium';
latency: string;
voices: number;
integration: string;
}
const ttsOptions: TTSOption[] = [
{
name: 'edge-tts (Python)',
cost: 'Free',
quality: 'medium',
latency: '1-3s per paragraph',
voices: 300,
integration: 'pip install edge-tts',
// Uses Microsoft Edge's online TTS service
// No API key needed
// Good enough for TikTok, not for premium YouTube
},
{
name: 'edge-tts-universal (Node.js)',
cost: 'Free',
quality: 'medium',
latency: '1-3s per paragraph',
voices: 300,
integration: 'npm install edge-tts-universal',
// TypeScript port of the Python package
// Works in Node.js, Deno, Bun
},
{
name: 'ElevenLabs',
cost: '$0.30/1K chars ($5-$99/mo plans)',
quality: 'premium',
latency: '2-5s per paragraph',
voices: 1000,
integration: 'REST API or Creatomate built-in',
// Best quality on market
// Voice cloning available
// Built into Creatomate β no separate API call needed
},
{
name: 'Google Cloud TTS',
cost: '$4/1M chars (Standard), $16/1M chars (WaveNet)',
quality: 'high',
latency: '1-2s per paragraph',
voices: 400,
integration: 'REST API + client libraries',
},
{
name: 'Amazon Polly',
cost: '$4/1M chars (Standard), $16/1M chars (Neural)',
quality: 'high',
latency: '1-2s per paragraph',
voices: 60,
integration: 'AWS SDK',
},
];
Key insight: For testing and TikTok, use edge-tts (free). For YouTube long-form where voice quality directly affects retention, use ElevenLabs ($5/mo starter plan gives 30,000 characters β enough for ~10 long-form videos). The quality difference is significant: edge-tts has audible robotic artifacts that sophisticated viewers notice.
FFmpeg Composite Commands Reference
These are the building-block FFmpeg commands for local rendering.
Overlay text on video:
ffmpeg -i background.mp4 \
-vf "drawtext=fontfile=/path/to/Inter-Black.ttf:\
text='THE LLC TRAP':\
fontcolor=white:\
fontsize=72:\
x=(w-text_w)/2:y=h*0.15:\
enable='between(t,0,3)'" \
-c:a copy output.mp4
Merge TTS audio with video:
ffmpeg -i video.mp4 -i narration.mp3 \
-c:v copy -c:a aac \
-map 0:v:0 -map 1:a:0 \
-shortest \
output.mp4
Concatenate clips with transitions:
echo "file 'clip1.mp4'" > clips.txt
echo "file 'clip2.mp4'" >> clips.txt
echo "file 'clip3.mp4'" >> clips.txt
ffmpeg -f concat -safe 0 -i clips.txt \
-c:v h264_nvenc -preset p4 -b:v 8M \
-c:a aac -b:a 192k \
concatenated.mp4
Apply the finance aesthetic filter chain:
ffmpeg -i raw_stock.mp4 \
-vf "eq=brightness=-0.15:contrast=1.2,\
colorbalance=bs=0.1:ms=0.05,\
vignette=PI/4,\
setpts=PTS/1.3" \
-c:v h264_nvenc -preset p4 \
treated.mp4
Scale and crop to 9:16 portrait:
ffmpeg -i landscape.mp4 \
-vf "scale=1080:1920:force_original_aspect_ratio=increase,\
crop=1080:1920" \
portrait.mp4
Add animated number counter overlay (using drawtext with timecodes):
ffmpeg -i background.mp4 \
-vf "drawtext=fontfile=/path/to/JetBrainsMono-Bold.ttf:\
text='$%{eif\\:min(3200\\,3200*t/2)\\:d}':\
fontcolor=#00FF00:\
fontsize=96:\
x=(w-text_w)/2:y=(h-text_h)/2:\
enable='between(t,2,4)'" \
-c:a copy output.mp4
The most effective video strategy is not choosing between short-form and long-form. It is using short-form as a funnel to long-form.
The Architecture
βββββββββββββββββββ
β LONG-FORM β β Cash engine
β YouTube 8-15m β $9-$25 RPM
β 2-3x per week β
ββββββββββ¬βββββββββ
β
Extract 3 best segments
β
ββββββββββββββββΌβββββββββββββββ
β β β
ββββββΌβββββ ββββββΌβββββ ββββββΌβββββ
β SHORT 1 β β SHORT 2 β β SHORT 3 β β Amplification
β TikTok β β YT Shortβ β IG Reel β $0.40-$2.00 RPM
β 60s β β 60s β β 60s β But drives subs
βββββββββββ βββββββββββ βββββββββββ to long-form
Why This Works
-
Long-form is the cash engine. Finance YouTube RPM is $9-$25. A single 10-minute video with 50K views = $450-$1,250. Nothing else comes close.
-
Shorts are top-of-funnel. They do not earn much directly but drive subscriptions. A viewer who discovers you via a Short and subscribes will watch your long-form content for years.
-
Shorts validate topics. Before investing $2-$6 in a long-form render, post a Short on the same topic. If it gets 10K+ views, the topic has demand. If it gets 200 views, skip the long-form.
-
Same assets, zero marginal cost. The stock footage, research, and script are already done for the long-form video. Extracting 3 shorts is a prompt + a render, not a production.
Extracting Shorts from Longs
interface ShortExtraction {
segment: string;
startTime: number;
endTime: number;
hookLine: string;
viralitySignal: string;
}
const extractionPrompt = `You are analyzing a long-form video script to find the 3 best
60-second segments that would perform as standalone TikTok/Shorts.
FULL SCRIPT:
{{longFormScript}}
For each segment, identify:
1. The most SHOCKING or COUNTERINTUITIVE claim (this becomes the hook)
2. A self-contained narrative arc (problem β insight β takeaway)
3. A natural ending point that creates urgency to learn more
Output JSON array of 3 segments:
[
{
"segment": "The exact narration text for this 60-second clip",
"start_time": 45,
"end_time": 105,
"hook_line": "The first sentence, rewritten as a scroll-stopping hook",
"virality_signal": "Why this segment would perform (e.g., 'counterintuitive claim about California LLC cost')"
}
]
RULES:
- Each segment must work WITHOUT context from the rest of the video
- The hook must be the FIRST sentence (no buildup)
- Prefer segments with specific dollar amounts
- Avoid segments that reference "earlier in this video"
- Each segment should cover a DIFFERENT subtopic`;
Auto-Rendering 9:16 Crops
If your long-form video is 16:9, you can auto-crop to 9:16 for Shorts without re-rendering the entire video.
ffmpeg -i longform.mp4 \
-ss 00:00:45 -t 60 \
-vf "crop=ih*9/16:ih,scale=1080:1920" \
-c:v h264_nvenc -preset p4 \
-c:a aac \
short_segment_1.mp4
This replaces tools like OpusClip ($15-$29/month) for basic extraction. OpusClip adds AI-powered selection of the best moments and auto-captions, which is valuable at scale but unnecessary when you already have the script and know which segments to extract.
The Posting Cadence
Monday: 1 Short (TikTok + YT Shorts + IG Reels)
Tuesday: 1 Long-form (YouTube) + 1 Short (extracted)
Wednesday: 1 Short
Thursday: 1 Long-form (YouTube) + 1 Short (extracted)
Friday: 1 Short
Saturday: 1 Long-form (YouTube) + 1 Short (extracted)
Sunday: 1 Short (recap/compilation)
Weekly total: 3 long-form + 7 shorts = 10 videos
Monthly total: 12 long-form + 28 shorts = 40 videos
Production time (automated pipeline):
12 long-form x 15 min = 3 hours
28 shorts x 5 min = 2.3 hours
Review + approval: 2-3 hours
Total: ~8 hours/month for 40 videos
TikTok
interface TikTokOptimization {
hook: {
timing: '0.5 seconds to grab attention';
rule: 'First frame must be visually arresting β text, color, or motion';
antiPattern: 'Fade-in from black (instant scroll)';
};
sound: {
strategy: 'Use trending sounds when possible β 2.3x algorithm boost';
rule: 'If using original audio (TTS), add trending sound at 5% volume underneath';
discovery: 'Check TikTok Creative Center for trending sounds weekly';
};
hashtags: {
count: '5-8 hashtags';
mix: '2 broad (#finance #money) + 3 niche (#llctax #sidehustle) + 2 trending';
rule: 'Never use #fyp or #foryou β they do nothing and signal amateur';
};
format: {
length: '60-90 seconds for Creator Rewards eligibility (minimum 1 minute)';
ratio: '9:16 always, 1080x1920';
captions: 'Required β 80% of TikTok is watched without sound';
textPlacement: 'Keep text in safe zone (top 15% and bottom 20% are covered by UI)';
};
contentRewards: {
eligibility: '10K+ followers, 100K+ views in last 30 days, 1+ minute videos';
rpm: '$0.40-$2.00 per 1K qualified views';
qualifiedViews: 'Unique FYP views, 5+ seconds watched, not promoted/paid';
tip: 'Videos that get shared (not just viewed) earn higher RPM';
};
}
YouTube Shorts
interface YouTubeShortsOptimization {
seo: {
title: 'Include primary keyword β YouTube Shorts ARE searchable';
description: 'Full description with keywords, links, timestamps';
rule: 'Shorts appear in regular search results β treat SEO seriously';
};
format: {
length: '30-60 seconds optimal (max 3 minutes)';
ratio: '9:16, 1080x1920';
looping: 'Design for seamless loop β last frame should connect to first';
};
monetization: {
rpm: '$0.05-$0.15 (much lower than long-form)';
purpose: 'Not for direct revenue β for subscriber acquisition';
funnel: 'End card pointing to full video in description';
};
algorithm: {
retentionTarget: '70%+ average view duration for Shorts';
swipeThroughRate: 'Lower is better β means people watch instead of swipe';
tip: 'Shorts that drive viewers to your long-form get algorithmic boost';
};
}
YouTube Long-Form
interface YouTubeLongFormOptimization {
structure: {
chapters: 'Add chapters every 2-3 minutes β required for modern YouTube';
intro: 'Skip it. Start with the content. Intros kill retention.';
midRollAds: 'Place manually at natural breaks (every 3-4 minutes)';
endScreen: 'Last 20 seconds: subscribe CTA + next video recommendation';
};
seo: {
title: 'Primary keyword in first 60 chars, number if possible';
description: 'First 150 chars = keyword-rich summary (shows in search)';
tags: '10-15 tags, mix of broad and specific';
thumbnail: 'Custom always. A/B test with YouTube Studio experiments.';
};
retention: {
target: '40-50% average view duration (industry benchmark for 10-min)';
hooks: 'Preview the payoff in first 30 seconds';
patternInterrupt: 'Every 60-90 seconds: visual change, question, or tone shift';
pacing: '180 WPM narration, 8-15 second scenes, no dead air';
};
monetization: {
threshold: '1,000 subscribers + 4,000 watch hours (or 10M Shorts views)';
financeRpm: '$9-$25 RPM (US audience)';
q4Boost: 'October-December RPM is 1.5-2x higher than Q1';
tip: 'Post more in Q4, less in Q1 β same effort, more revenue';
};
}
Instagram Reels
interface InstagramReelsOptimization {
format: {
length: '30-60 seconds (Reels up to 90 seconds, but shorter performs better)';
ratio: '9:16, 1080x1920';
coverImage: 'Custom cover that looks good in the grid (squared crop)';
};
engagement: {
cta: 'Ask a question in the caption β comments boost distribution';
carousel: 'Carousel posts with video = 2x engagement vs. standalone Reels';
textOverlays: 'Essential β Instagram is sound-off by default';
};
crossPosting: {
rule: 'Remove TikTok watermark before posting (Instagram penalizes)';
timing: 'Post to TikTok first, Instagram 24-48 hours later';
tool: 'SnapTik or similar for watermark removal, or render separate copy';
};
monetization: {
rpm: '$0.10-$0.50 (inconsistent, not primary revenue source)';
purpose: 'Brand building + traffic driver to YouTube/tools';
};
}
Cross-Posting Strategy
One video β All platforms simultaneously (with platform-specific tweaks):
1. RENDER: Produce one 9:16 MP4 at 1080x1920
2. TIKTOK: Post with trending sound layered underneath, TikTok-specific hashtags
3. YOUTUBE SHORTS: Post with SEO title, full description, link to long-form
4. INSTAGRAM REELS: Post with engagement CTA in caption, custom cover
5. CONTENT REWARDS: If matching a campaign, post there too for extra RPM
Timing:
- TikTok: Post first (fastest feedback loop, 6-24 hours to see results)
- YouTube Shorts: 2-4 hours later
- Instagram Reels: 24-48 hours later (avoid duplicate content signals)
Never:
- Post the same video at the exact same time everywhere
- Use TikTok watermark on other platforms
- Use the same caption/description across platforms
Not all niches are worth automating. A niche must pass three filters to be viable for programmatic video production.
The Three Filters
interface NicheFilter {
name: string;
threshold: string;
why: string;
}
const filters: NicheFilter[] = [
{
name: 'RPM Ceiling',
threshold: '>$8 RPM on YouTube',
why: 'Below $8 RPM, you need millions of views to hit $10K/mo. Above $8, you need 500K-1M views β achievable in 6-12 months.',
},
{
name: 'Data Extraction Feasibility',
threshold: 'Historical/analytical topics, not breaking news',
why: 'Programmatic videos rely on LLM-generated scripts. LLMs are good at analyzing data, terrible at breaking news. Pick niches where the content is analytical, not time-sensitive.',
},
{
name: 'Stock Footage Feasibility',
threshold: 'Abstract concepts, not specific clips',
why: 'You need Pexels/Pixabay footage to match your script. Finance = generic office/money footage (abundant). Sports highlights = specific game clips (impossible to source).',
},
];
Niche Scorecard
| Niche | RPM Range | Data Feasibility | Stock Feasibility | Overall Score |
|---|---|---|---|---|
| Personal Finance | $15-$25 | High (tax data, rates, calculators) | High (money, offices, documents) | A+ |
| Software/SaaS Reviews | $12-$20 | High (features, pricing, comparisons) | Medium (screen recordings) | A |
| Business Cases | $10-$18 | High (company data, revenue, strategy) | High (offices, cities, products) | A |
| AI/Tech Explainers | $8-$15 | High (benchmarks, features, workflows) | Medium (abstract tech, code) | A- |
| Real Estate | $10-$20 | High (market data, mortgage rates) | High (houses, neighborhoods) | A |
| Credit Cards/Banking | $20-$45 | High (rewards, rates, comparisons) | Low (specific card imagery) | B+ |
| Health/Fitness | $4-$8 | Medium (studies, nutrition data) | High (gym, food, exercises) | B |
| Gaming | $2-$5 | Low (gameplay is king, not analysis) | Low (need specific game footage) | C |
| Entertainment/Comedy | $2-$4 | Low (personality-driven) | Low (need specific clips) | D |
| Music | $1-$3 | Low (subjective, copyright issues) | Low (need specific performances) | D |
Sub-Niche RPM Deep Dive (Finance)
| Sub-Niche | YouTube RPM | TikTok RPM | Search Volume | Competition |
|---|---|---|---|---|
| Credit card comparisons | $20-$45 | $1.00-$2.00 | High | Very High |
| Tax planning/LLC | $15-$25 | $0.80-$1.50 | High (seasonal) | Medium |
| Investment strategy | $12-$20 | $0.60-$1.20 | Very High | High |
| Business formation | $10-$18 | $0.50-$1.00 | Medium | Medium |
| Debt management | $10-$15 | $0.40-$0.80 | High | Medium |
| Budgeting basics | $8-$12 | $0.30-$0.60 | Very High | Very High |
| Side hustle guides | $8-$15 | $0.40-$1.00 | Very High | Very High |
| Crypto/DeFi | $8-$15 | $0.30-$0.80 | High | High |
Key insight: Credit card comparison content has the highest RPM of any niche on YouTube ($20-$45 in Q4), but it requires specific card imagery and detailed comparison data that is hard to generate programmatically. LLC/tax content is the sweet spot: high RPM ($15-$25), easy to generate with LLMs (tax code is public data), and stock footage is abundant (documents, offices, money). Start there.
Once your pipeline works for one video, the next step is scaling it to produce 5-10+ videos per day without proportional time investment. This is where AI agents come in.
The Agent Architecture
interface VideoAgent {
role: string;
trigger: string;
input: string;
output: string;
automation: 'full' | 'semi' | 'human-in-loop';
}
const agentPipeline: VideoAgent[] = [
{
role: 'Trend Scout',
trigger: 'Cron: every 6 hours',
input: 'Virlo API + YouTube Trending + X/Twitter trending',
output: 'Ranked list of trending topics with niche angles',
automation: 'full',
},
{
role: 'Script Writer',
trigger: 'New trending topic identified',
input: 'Topic + trend context + niche connection',
output: 'Structured VideoScript JSON',
automation: 'full',
},
{
role: 'Asset Gatherer',
trigger: 'Script approved',
input: 'Stock footage keywords from script',
output: 'Downloaded clips + TTS audio',
automation: 'full',
},
{
role: 'Renderer',
trigger: 'Assets ready',
input: 'VideoScript + clips + audio',
output: 'Finished MP4',
automation: 'full',
},
{
role: 'Quality Gate',
trigger: 'Render complete',
input: 'Finished MP4 + script metadata',
output: 'Approved or rejected with feedback',
automation: 'human-in-loop',
// CRITICAL: Human reviews every video before posting
// AI generates, human approves
},
{
role: 'Publisher',
trigger: 'Human approval',
input: 'Approved MP4 + platform metadata',
output: 'Posted to TikTok, YouTube, Instagram',
automation: 'semi',
// Human clicks "approve" β agent posts to all platforms
},
];
Issue-Per-Video System
Each video is tracked as a GitHub issue. This gives you version history, comments for feedback, labels for categorization, and automation hooks.
interface VideoIssue {
title: string; // "VF042: The 401K Calculator Hack"
labels: string[]; // ["video", "short-form", "llc-tax", "automated"]
body: {
topic: string;
trend_context: string;
script: string; // JSON script
render_status: 'pending' | 'rendering' | 'complete' | 'failed';
render_url?: string; // Link to MP4 in R2/CDN
posted_platforms?: string[];
views_48h?: number; // Performance tracking
};
}
// Example GitHub Issue body:
const exampleIssue = `
**Topic:** 401K contribution calculator reveals most people under-contribute by $4,200/year
**Trend:** "Retirement savings" trending on TikTok finance after viral post about $1M by 65
**Format:** Short-form (60 seconds)
**Brand:** llc-tax
### Script
\`\`\`json
{
"hook_text": "YOU'RE LOSING $4,200/YEAR",
"narration": "Most people think they're maxing out their 401K...",
"cta_text": "FREE CALCULATOR IN BIO"
}
\`\`\`
### Render Status
- [ ] Script generated
- [ ] TTS rendered
- [ ] Stock footage downloaded
- [ ] Video composited
- [ ] Human review passed
- [ ] Posted to TikTok
- [ ] Posted to YouTube Shorts
- [ ] Posted to Instagram Reels
### Performance (48h)
- TikTok views: pending
- YouTube views: pending
`;
Cron-Based Production
// video-factory.ts β Cron job that produces N videos per day
interface ProductionConfig {
videosPerDay: number;
formats: ('short-form' | 'long-form')[];
niches: string[];
renderBackend: 'local' | 'cloud';
requireHumanReview: true; // Always true. Never auto-post.
}
const config: ProductionConfig = {
videosPerDay: 5,
formats: ['short-form'],
niches: ['personal-finance', 'llc-tax', 'side-hustle'],
renderBackend: 'local',
requireHumanReview: true,
};
// Cron schedule:
// 06:00 β Trend Scout runs, identifies top 10 topics
// 07:00 β Script Writer generates 5 scripts
// 08:00 β Asset Gatherer downloads footage + TTS
// 09:00 β Renderer produces 5 MP4s
// 10:00 β Human reviews queue (GitHub issues labeled "needs-review")
// 11:00 β Publisher posts approved videos
// Implementation: each step is a separate function triggered by cron
// or by the completion of the previous step (event-driven)
Quality Rules for Automated Content
These are non-negotiable rules that every generated video must pass before posting.
const qualityRules = [
{
rule: 'No fabricated data',
check: 'Every number in the script must trace to a real source',
consequence: 'One fake stat destroys channel credibility permanently',
},
{
rule: 'Financial disclaimers',
check: 'Video description includes: "This is not financial advice"',
consequence: 'FTC violation, potential legal liability',
},
{
rule: 'No expert claims',
check: 'Script never says "I am a CPA/attorney/financial advisor"',
consequence: 'Misrepresentation of credentials, legal liability',
},
{
rule: 'YouTube AI disclosure',
check: 'Video uses YouTube Studio "altered content" disclosure',
consequence: 'Policy violation, potential demonetization',
},
{
rule: 'Duration check',
check: 'Short-form: 60-90 seconds. Long-form: 8-15 minutes.',
consequence: 'Under 60s = no TikTok Creator Rewards. Over 15m = retention drops.',
},
{
rule: 'Hook verification',
check: 'First 3 seconds contain visual hook + specific number',
consequence: 'No hook = no retention = no views',
},
{
rule: 'Stock footage relevance',
check: 'Each clip matches the narration topic (not generic filler)',
consequence: 'Irrelevant footage signals low quality to algorithm',
},
{
rule: 'Audio quality',
check: 'No clipping, no dead air > 1.5s, consistent volume',
consequence: 'Bad audio = immediate scroll',
},
];
Key insight: The human review gate is not optional. AI-generated content without human oversight leads to embarrassing mistakes, compliance violations, and channel termination. The agent system generates 5-10 videos per day; the human reviews and approves 3-7 of them. This is 10-15 minutes of review time per day, not hours of production time. That is the efficiency gain.
Layer 1: YouTube AdSense (Long-Form)
The primary revenue driver. Finance long-form YouTube content earns the highest RPM of any niche.
Requirements:
- YouTube Partner Program: 1,000 subscribers + 4,000 watch hours
- Or: 1,000 subscribers + 10 million Shorts views in 90 days
- Time to qualify: 2-4 months with consistent posting
Revenue projection (finance niche):
Month 1-2: Building catalog, 0 revenue (not yet monetized)
Month 3: Hit 1K subs + 4K watch hours β monetization ON
Month 4-6: 10K-50K views/month β $100-$625/month
Month 7-12: 50K-200K views/month β $625-$5,000/month
Year 2: 200K-500K views/month β $2,500-$12,500/month
Seasonal adjustments (finance):
Q1 (Jan-Mar): RPM $8-$15 (post-holiday budget reset)
Q2 (Apr-Jun): RPM $12-$18 (tax season advertising)
Q3 (Jul-Sep): RPM $10-$14 (summer slump)
Q4 (Oct-Dec): RPM $18-$30+ (holiday + year-end spending)
Strategy: Post MORE content in Q4 when RPM is highest.
Use Q1 to build catalog for Q4 search traffic.
Layer 2: TikTok Creator Rewards
Requirements:
- 10K+ followers
- 100K+ views in last 30 days
- Videos must be 1+ minute
- Original content only
Revenue:
$0.40-$2.00 per 1K qualified views
"Qualified" = unique, from FYP, 5+ seconds watched, not promoted
Projection:
100K views/month: $40-$200
500K views/month: $200-$1,000
1M views/month: $400-$2,000
Strategy: Focus on 60-90 second videos (minimum 1 minute for eligibility)
Higher retention = higher RPM within the program
Layer 3: Content Rewards
Content Rewards pays creators to make UGC-style content for brand campaigns. It is performance-based: more views = more money.
How it works:
1. Browse active campaigns on contentrewards.com
2. Create content matching the campaign brief
3. Post to TikTok/Instagram with campaign requirements
4. Get paid per 1K views ($1-$2.50 RPM)
Revenue:
No audience needed β payment is per view, not per follower
10 campaigns x 5K views each = 50K views = $50-$125/month
Strategy: Low-effort supplement. Use same video pipeline.
Some campaigns align with your niche (finance apps, side hustle tools).
Cherry-pick campaigns that match your brand.
Layer 4: Affiliate Links
Finance affiliate programs:
- NerdWallet referrals: $5-$50 per sign-up
- Credit card offers: $50-$200 per approval
- LLC formation services (LegalZoom, Northwest): $20-$100 per sign-up
- Tax software (TurboTax, H&R Block): $15-$40 per sale
- Business bank accounts: $25-$100 per account opened
Placement:
- YouTube description (first 3 lines are visible without clicking "more")
- TikTok bio link (link-in-bio tool: Linktree, Stan Store)
- Instagram bio link
- Pinned comments
Projection:
1% click-through on 50K monthly views = 500 clicks
5% conversion on clicks = 25 sales
Average $40 per sale = $1,000/month
Strategy: Every video naturally leads to a recommendation.
"Link in the description for the calculator/tool/service"
Never hard-sell in the video itself β the CTA is soft and natural.
Layer 5: Sponsor Integrations
Finance niche sponsor rates:
- 10K subscribers: $200-$500 per integration
- 50K subscribers: $500-$2,000 per integration
- 100K subscribers: $2,000-$5,000 per integration
- 500K subscribers: $5,000-$15,000 per integration
Common sponsors for finance channels:
- Fintech apps (Robinhood, SoFi, Webull)
- Tax services
- LLC formation services
- Business tools (QuickBooks, FreshBooks)
- Educational platforms
Strategy: Don't seek sponsors until 25K+ subscribers.
Focus on AdSense and affiliate until then.
When sponsors come, integrate naturally into content.
Never let sponsors dictate content β it kills the audience.
Layer 6: Funnel to Owned Products
This is where the real leverage lives. Every video is a top-of-funnel entry point to products you own.
Owned products for finance niche:
- Calculator tools (free, drives traffic, builds email list)
- Spreadsheet templates ($5-$29 on Gumroad/Etsy)
- Online courses ($49-$499)
- eBooks/guides ($9-$29)
- Consulting/coaching ($100-$500/hour)
- SaaS tools ($9-$49/month)
Example funnel:
TikTok video: "The LLC Cost Trap" (47K views)
β Link in bio: "Free LLC Cost Calculator"
β Calculator page: 2,000 visitors
β Email capture: 400 signups (20% conversion on free tool)
β Email sequence: "LLC Tax Handbook" ($19)
β Purchases: 40 sales ($760)
One video β $760 in product sales, plus AdSense, plus affiliate, plus Content Rewards
The $10K/Month Math
Conservative scenario (Month 12, single channel):
YouTube AdSense (long-form): $3,000 (200K views x $15 RPM)
TikTok Creator Rewards: $400 (400K views x $1.00 RPM)
Content Rewards: $100 (50K views across campaigns)
Affiliate links: $1,200 (30 conversions x $40 avg)
Owned products: $800 (40 sales x $20 avg)
ββββββββββββββββββββββββββββββββββββββββ
Total: $5,500/month
Aggressive scenario (Month 18, two channels):
YouTube AdSense (2 channels): $6,000 (400K views x $15 RPM)
TikTok Creator Rewards: $800 (800K views x $1.00 RPM)
Content Rewards: $200 (100K views)
Affiliate links: $2,000 (50 conversions x $40 avg)
Sponsor integration: $1,500 (1 per month at 50K subs)
Owned products: $1,500 (75 sales x $20 avg)
ββββββββββββββββββββββββββββββββββββββββ
Total: $12,000/month
Production cost: $200/month
Net profit: $11,800/month (98% margin)
YouTube AI Content Policy (July 2025)
YouTubeβs most significant policy change for AI content creators went into effect July 15, 2025. Understanding it is mandatory.
What changed:
- "Inauthentic content" rule targets mass-produced, repetitive AI content
- YouTube Partner Program now requires content to be "significantly original
and authentic" to remain eligible for monetization
- Mandatory disclosure for altered/synthetic content via YouTube Studio
- In January 2026, YouTube wiped 4.7 billion views across 16 channels
(35M combined subscribers) in a single enforcement wave
What is ALLOWED:
- AI-assisted content with genuine editorial oversight
- AI-generated scripts rewritten/refined by a human
- AI voiceover with human-selected content and structure
- AI-generated visuals combined with original commentary/analysis
What gets DEMONETIZED:
- Mass-produced AI content with no original insight
- Repetitive videos that are essentially the same template with swapped data
- Pure AI narration reading facts with no editorial layer
- Content that doesn't add "substantial value" beyond what AI generated
How to stay compliant:
1. ALWAYS use the "altered content" disclosure in YouTube Studio
2. Add genuine editorial value: analysis, opinions, context
3. Vary your templates β don't use the same layout for every video
4. Include original research or unique data points
5. Human reviews and modifies every script before rendering
6. Each video should feel intentionally crafted, not factory-produced
The βReused Contentβ Flag
This is separate from the AI policy. YouTube flags "reused content" when:
- Multiple channels post the same or very similar content
- Content is compiled from other sources without transformation
- Videos are cookie-cutter templates with only data swapped
How to avoid it:
- Unique visual templates per channel (different color schemes, fonts)
- Unique intro patterns (don't start every video the same way)
- Mix video styles: explainers, comparisons, deep-dives, breakdowns
- Original analysis β don't just restate what other videos say
- Your voice/TTS voice should be consistent per channel (builds identity)
FTC Compliance for Finance Content
Required disclosures:
1. "This is not financial advice" β in video description AND spoken/shown
2. Affiliate links β must disclose: "Some links below are affiliate links"
3. Sponsored content β must disclose: "This video is sponsored by [brand]"
4. Material connections β any payment, free product, or relationship
Placement:
- Video: spoken disclosure within first 30 seconds for sponsored content
- Description: first 3 lines (visible without clicking "more")
- Pinned comment: additional disclosure for affiliate links
Penalties:
- FTC maximum civil penalty: $53,088 per violation (2025)
- Platform demonetization
- Channel termination for repeat violations
Finance-specific rules:
- Never claim to be a CPA, tax attorney, financial advisor (unless you are)
- Never guarantee returns or specific outcomes
- Always include "consult a qualified professional" language
- No specific investment recommendations without proper licensing
Platform-Specific Content Policies
| Platform | Key Risk | Mitigation |
|---|---|---|
| YouTube | AI content demonetization | Editorial layer, disclosure, varied templates |
| YouTube | Reused content flag | Unique visuals per channel, original analysis |
| TikTok | Community guidelines (finance misinformation) | Factual claims only, disclaimers, sources |
| TikTok | Creator Rewards clawback | No bought views, no engagement pods, organic only |
| Reach throttling for reposted content | Render separate copies, no TikTok watermark | |
| All platforms | Copyright strikes (music/footage) | Pexels/Pixabay only (CC0), royalty-free music |
The Credential Rule
This is critical and non-negotiable.
NEVER:
- Claim to be a CPA, EA (Enrolled Agent), tax attorney, or financial advisor
- Use titles like "tax expert" or "finance professional" unless verifiable
- Imply that your AI-generated analysis is professional advice
- Display fake credentials, certifications, or affiliations
ALWAYS:
- Present content as "educational" and "informational"
- Include "not financial/tax/legal advice" disclaimer
- Recommend viewers "consult a qualified professional"
- Be transparent that analysis is research-based, not professional opinion
Why this matters:
One channel got sued for $1.26M for implying credentials they didn't have.
The FTC specifically targets finance creators for credential claims.
AI-generated content that claims authority it doesn't have is a fast path
to legal trouble.
This is the step-by-step process for producing your first video today. No automation, no agents β just you and the tools.
Step 1: Find a Trending Topic (15 minutes)
Manual process:
1. Open TikTok β search "money" or "business" β sort by "This week"
2. Note the top 5 videos: what topics? what hooks? what format?
3. Open YouTube Trending β filter by "Education" or "Howto & Style"
4. Cross-reference: topics appearing on BOTH TikTok and YouTube = high signal
5. Pick one topic that connects to your niche
Example finding:
TikTok trending: "Things that cost more than you think"
YouTube trending: "Hidden costs of starting a business"
Your angle: "The LLC Cost Trap Nobody Talks About"
Connection: Your LLC calculator tool / content
Step 2: Write the Script (20 minutes)
Use the prompt chain from Section 3:
1. Run Step 1 prompt (fact retrieval) β get 8-12 facts with numbers
2. Run Step 2 prompt (hook generation) β get scroll-stopping opening
3. Run Step 3 prompt (body + pacing) β get scene-by-scene script
Review checklist:
β‘ Hook in first 1 second (specific number or provocative claim)
β‘ No filler words ("hey guys", "so basically", "alright")
β‘ Every sentence has ONE idea
β‘ Specific numbers throughout ($3,200, not "thousands")
β‘ Total word count: 130-160 words (for 60-second short-form)
β‘ CTA is natural, not salesy
β‘ No expert claims or financial advice language
Step 3: Gather Stock Footage (10 minutes)
Process:
1. Extract stock keywords from each scene (from script output)
2. Search Pexels.com or Pixabay.com for each keyword
3. Download 6-8 clips (portrait/vertical preferred for short-form)
4. Each clip: 5-10 seconds, matching the scene topic
Search tips:
- Add "dark" to keywords for finance aesthetic (e.g., "dark office")
- "Money" + specific context (e.g., "money counting", "money calculator")
- Avoid clips with identifiable faces (licensing issues)
- Download at highest available resolution
Step 4: Generate TTS Audio (5 minutes)
pip install edge-tts
edge-tts --voice "en-US-GuyNeural" --rate "+10%" \
--text "Filing an LLC costs fifty dollars..." \
--write-media narration.mp3
curl -X POST "https://api.elevenlabs.io/v1/text-to-speech/pNInz6obpgDQGcFmaJgB" \
-H "xi-api-key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"text": "Filing an LLC costs fifty dollars...", "model_id": "eleven_multilingual_v2"}' \
--output narration.mp3
Step 5: Render the Video (5-15 minutes)
ffmpeg -f concat -safe 0 -i clips.txt \
-vf "scale=1080:1920:force_original_aspect_ratio=increase,crop=1080:1920,\
eq=brightness=-0.15:contrast=1.2" \
-c:v h264_nvenc -preset p4 -t 60 background.mp4
ffmpeg -i background.mp4 \
-vf "drawtext=fontfile=Inter-Black.ttf:text='THE LLC TRAP':fontcolor=white:\
fontsize=72:x=(w-text_w)/2:y=h*0.15:enable='between(t,0,3)'" \
-c:a copy with_text.mp4
ffmpeg -i with_text.mp4 -i narration.mp3 \
-c:v copy -c:a aac -map 0:v:0 -map 1:a:0 -shortest final.mp4
curl -X POST "https://api.creatomate.com/v2/renders" \
-H "Authorization: Bearer YOUR_CREATOMATE_KEY" \
-H "Content-Type: application/json" \
-d @renderscript.json
Step 6: Review (5 minutes)
Quality check:
β‘ Duration: 60-90 seconds (for TikTok Creator Rewards eligibility)
β‘ Hook: first 1 second grabs attention
β‘ Audio: clear, no clipping, consistent volume
β‘ Visuals: dark aesthetic, text readable, no awkward clip transitions
β‘ Numbers: all on-screen numbers match narration
β‘ CTA: visible and natural
β‘ No expert claims or financial advice language
β‘ Disclaimer: "Not financial advice" in planned description
Step 7: Post (5 minutes)
TikTok:
- Upload MP4
- Title: hook line from script
- Hashtags: 5-8 (2 broad + 3 niche + 2 trending)
- Add trending sound at 5% volume (optional but helps)
- Description: 1-2 sentences + hashtags + disclaimer
YouTube Shorts:
- Upload same MP4
- Title: SEO-optimized (include primary keyword)
- Description: full description with links, disclaimer, hashtags
- Tags: 10-15 relevant tags
Instagram Reels:
- Upload MP4 (ensure no TikTok watermark)
- Caption: engagement question + relevant hashtags
- Custom cover image
Step 8: Measure (48 hours later)
Metrics to track:
- Views in first 24 hours (TikTok: >500 = good, >5K = great, >50K = viral)
- Average watch time (>50% = script is working)
- Engagement rate (likes + comments + shares / views)
- Click-through to bio link (if tracking)
- Profile visits (proxy for brand awareness)
Decision tree:
Views > 10K β Topic works. Make a long-form version.
Views 1K-10K β Format works but hook needs improvement. Iterate.
Views < 1K β Topic or hook failed. Try different angle.
Views < 100 β Something is wrong (shadow ban, posting time, or account issue)
Total Time: ~65 minutes for your first video
After the first 3-5 videos, this drops to 20-30 minutes as you build templates and muscle memory. After automation (Section 9), it drops to 5-10 minutes of review time per video.
Video Rendering API Comparison
| Feature | Creatomate | Shotstack | Remotion | FFmpeg (local) |
|---|---|---|---|---|
| Type | Cloud API | Cloud API | React framework | CLI tool |
| Cost | ~$0.20-$0.50/min rendered | $0.20-$0.30/min rendered | Free (individuals), $0.01/render (business) | Free |
| TTS Built-in | Yes (ElevenLabs integrated) | No (bring your own audio) | No (bring your own audio) | No |
| Captions | Auto-synced from voiceover | Manual positioning | Programmatic (React components) | Manual (drawtext filter) |
| Template Editor | Yes (visual + JSON) | Yes (visual + JSON) | Code-only (React) | Code-only (CLI) |
| Quality | Production-grade | Production-grade | Production-grade | Depends on effort |
| Latency | 2-10 min per render | 2-10 min per render | 1-5 min (local), 2-10 min (Lambda) | 30s-2min (GPU) |
| Scaling | Unlimited (cloud) | Unlimited (cloud) | Lambda or local fleet | Limited by hardware |
| Learning Curve | Low (JSON templates) | Low (JSON timelines) | Medium (React + video concepts) | High (FFmpeg filters) |
| Best For | Quick start, TTS integration | Timeline-based editing | Custom animations, React devs | Zero-cost, maximum control |
| Docs | creatomate.com/docs | shotstack.io/docs | remotion.dev/docs | ffmpeg.org/documentation |
TTS Provider Comparison
| Feature | edge-tts | ElevenLabs | Google Cloud TTS | Amazon Polly |
|---|---|---|---|---|
| Cost | Free | $0.30/1K chars ($5-$99/mo) | $4-$16/1M chars | $4-$16/1M chars |
| Quality | Medium | Premium | High | High |
| Voices | 300+ | 1000+ (cloning available) | 400+ | 60+ |
| Latency | 1-3s | 2-5s | 1-2s | 1-2s |
| Languages | 45+ | 29+ | 40+ | 30+ |
| API Key | Not required | Required | Required | Required |
| Best For | Testing, TikTok, zero budget | YouTube, premium quality | Enterprise, batch | Enterprise, AWS stack |
| Gotcha | Unofficial API, may break | Expensive at scale | Per-character billing | Fewer voice options |
Video Clipping Tool Comparison (Long-to-Short)
| Feature | OpusClip | Vizard | Manual FFmpeg | DIY (prompt + render) |
|---|---|---|---|---|
| Cost | $15-$29/mo | $14.50/mo | Free | Free |
| AI Clipping | Yes (ClipAnything) | Yes | No | Prompt-based |
| Virality Score | Yes (paid only) | No | No | No |
| Caption Quality | 97%+ accuracy | High | Manual | Via Creatomate |
| Batch Processing | Yes | Yes | Script-based | Script-based |
| Platform Export | All major | All major | Manual | Manual |
| Best For | Non-technical creators | Budget-conscious | Full control | Developers with pipeline |
Trend Intelligence Comparison
| Feature | Virlo | TikTok Creative Center | YouTube Trending API | Manual Discovery |
|---|---|---|---|---|
| Cost | $49-$199/mo | Free | Free (quota) | Free (time cost) |
| Coverage | TikTok + YT + IG | TikTok only | YouTube only | Multi-platform |
| API | Yes (REST) | No | Yes | No |
| Early Signal | 12-24h before mainstream | Real-time | 6-12h delay | 2-4h delay |
| Niche Filtering | Yes | Limited | Category only | Manual |
| Best For | Automated pipeline, speed | Manual research | YouTube focus | Getting started |
| Docs | virlo.ai/developers | ads.tiktok.com | developers.google.com | N/A |
Full Pipeline Cost Comparison
| Pipeline | Monthly Cost | Videos/Month | Cost/Video | Quality | Automation |
|---|---|---|---|---|---|
| Zero Budget (edge-tts + FFmpeg + manual) | $0 | 30 | $0 | Medium | None |
| Starter (edge-tts + FFmpeg + scripts) | $20 (OpenAI API) | 100 | $0.20 | Medium | Partial |
| Growth (ElevenLabs + Creatomate) | $50-$100 | 100 | $0.50-$1.00 | High | Mostly |
| Scale (ElevenLabs + Creatomate + Virlo) | $200-$400 | 300+ | $0.67-$1.33 | High | Full |
| Premium (ElevenLabs + Remotion + custom) | $100-$300 | 200+ | $0.50-$1.50 | Premium | Full |
These are real mistakes that kill channels. Every one of them has been observed in the wild.
| Donβt | Do Instead | Why |
|---|---|---|
| Start every video with βHey guys, welcome backβ | Start with a specific number or provocative claim | First-word retention: βHeyβ = 35% drop. β$3,200β = 5% drop. |
| Use the same template for every video | Vary layouts, color accents, and intro patterns | YouTube flags identical templates as βreused contentβ and demonetizes |
| Auto-post without human review | Generate with AI, approve with human eyes | One factual error, one compliance violation, one embarrassing mistake can destroy a channel permanently |
| Claim credentials you donβt have | Say βresearch showsβ or βbased on IRS dataβ | FTC penalties up to $53,088 per violation. One creator fined $1.26M. |
| Post the same video to all platforms simultaneously | Stagger: TikTok first, then YT Shorts (4h later), then IG Reels (24h later) | Algorithms penalize duplicate content detected across platforms |
| Use trending sounds at full volume | Layer trending sound at 5% volume under your TTS | TikTok algorithm boosts trending sounds, but the sound should not overpower your narration |
| Optimize for views only | Optimize for retention (average view duration) | High views with low retention = algorithm stops promoting. High retention = exponential growth. |
| Use approximations (βabout $3,000β) | Use exact numbers (β$3,247β) | Specific numbers signal authority. Round numbers signal guessing. |
| Skip financial disclaimers | Include βNot financial adviceβ in description AND spoken | FTC is actively auditing finance creators. One missed disclaimer = one violation. |
| Mass-produce 50 low-quality videos/day | Produce 5-10 quality videos/day with editorial layer | YouTubeβs July 2025 policy explicitly targets βmass-producedβ AI content |
| Use TikTok watermark on Instagram | Render separate copies or remove watermark before cross-posting | Instagram throttles reach for TikTok-watermarked content |
| Fade in from black as your opening | Start in media res: first frame = content | Fade-in = 2-3 seconds of nothing = viewer scrolls away |
| Put links in TikTok video (they donβt work) | Use βlink in bioβ CTA and optimize your bio link page | TikTok videos donβt support clickable links; bio link is the only path |
| Ignore Q4 seasonality | Double your posting cadence October-December | Finance RPM is 1.5-2x higher in Q4. Same content, twice the revenue. |
| Generate long-form videos without chapters | Add chapters every 2-3 minutes in description | Chapters improve SEO, user experience, and YouTubeβs understanding of your content |
| Use copyrighted music or footage | Use only Pexels, Pixabay (CC0), or royalty-free libraries | One copyright strike = channel warning. Three = channel termination. |
Official Documentation
- Creatomate API Reference β REST API for automated video generation with JSON templates and RenderScript
- Creatomate RenderScript JSON Structure β Complete documentation of the JSON-to-video format
- Shotstack Video Editing API β Cloud video composition API with timeline-based editing at $0.20-$0.30/min
- Remotion Documentation β React framework for programmatic video creation
- Pexels API Documentation β Free stock video and photo search API
- Pixabay API Documentation β Free stock video API with 5.6M+ assets
- ElevenLabs TTS API β Premium AI text-to-speech with voice cloning
- ElevenLabs API Pricing β Per-character pricing for TTS API usage
- FFmpeg Documentation β Complete reference for the FFmpeg multimedia framework
- YouTube Data API v3 β Official YouTube API for trending, search, and analytics
- YouTube AI Content Disclosure β Official help page for disclosing altered or synthetic content
Trend Intelligence
- Virlo β Short-form video analytics platform: 2M+ indexed videos, 500K+ hashtags, trend prediction
- Virlo Developers API β REST API for viral trends data with 7-dimension intelligence reports
- Virlo: TikTok Trend Discovery Guide β How to find viral trends before they peak
- Virlo: Highest RPM Niches on YouTube β Data-backed RPM analysis by niche
Platform Policies and Monetization
- YouTube AI Monetization Policy 2025 β Comprehensive guide to staying compliant with YouTubeβs AI content rules
- YouTube Demonetization Policy 2026 β Updated compliance guide for AI-generated content
- YouTubeβs AI Disclosure Requirements β Complete 2025 guide to mandatory AI content disclosure
- YouTube Blog: Disclosing AI-Generated Content β Official YouTube blog post on disclosure requirements
- TikTok Creator Rewards Program Guide β Complete guide to eligibility, RPM, and optimization
- Content Rewards β Performance-based UGC marketplace ($1-$2.50 per 1K views)
- FTC Disclosures 101 for Social Media Influencers β Official FTC guidelines for content creators
- FTC Endorsement Guides β FAQ on disclosure requirements
RPM and Earnings Data
- YouTube RPM Finance Niche 2026 Guide β Real earnings data with seasonal breakdowns
- YouTube CPM and RPM Rates 2026 β Average rates by niche and country
- Most Profitable YouTube Niches 2025 β Niche profitability ranked by CPM
- TikTok Creator Fund Earnings Statistics 2026 β Earnings breakdown by view count
- How Much Does TikTok Pay in 2026 β Complete TikTok income breakdown with calculator
TTS and Voice Tools
- edge-tts (Python) β Free Microsoft Edge TTS from Python, no API key needed
- edge-tts on PyPI β Python package for free TTS with 300+ voices
- edge-tts-universal (Node.js) β Universal TypeScript port for Node.js, Deno, Bun
- edge-tts npm package β Node.js implementation of Microsoft Edge TTS
Video Clipping and Repurposing
- OpusClip β AI video clipping for long-to-short conversion ($15-$29/mo)
- OpusClip Pricing β Detailed plan comparison
- Vizard.ai β AI video clipping alternative to OpusClip ($14.50/mo for 600 minutes)
- Vizard: Best Video Repurposing Tools 2025 β Comparison of 7 leading clipping tools
Automation and Programmatic Video
- Creatomate: How to Automate Video Generation with Python β Step-by-step Python automation guide
- Creatomate: JSON-to-Video Guide β Building videos from JSON programmatically
- Shotstack: Best AI Tools for YouTube Automation 2026 β Overview of automation tools
- Shotstack: Best AI Video Generator APIs β Comparison of 7 video generation APIs
- Remotion + Claude Code Video Generation β Using AI agents to generate Remotion videos
- Remotion GitHub β Open-source React video framework (18K+ stars)
- ffmpeg-python Documentation β Python bindings for FFmpeg
- Automating Content Creation with Python and FFmpeg β Practical automation tutorial
Faceless Channel Strategy
- Make: How to Make Faceless YouTube Videos with AI β Complete workflow for faceless video production
- AutoClips: Faceless YouTube Automation Guide 2026 β Comprehensive guide to building automated channels
- Fliki: Top 17 Tools for Faceless YouTube Videos 2026 β Tool comparison for faceless creators
- Fliki: How to Write a Video Script That Goes Viral β Script formula guide
- Subscribr β AI script writer and video idea generator for YouTube
Stock Footage and Media APIs
- Pexels API β Free image and video API with portrait/landscape filters
- Pixabay API β Free stock media API with 5.6M+ assets
- Shotstack: Best Stock Video APIs β Review of top 10 stock footage APIs
- Plainly Videos: Stock Video API Comparison β Detailed API feature comparison
This article reflects the state of platforms, APIs, and policies as of March 2026. Platform policies, RPM rates, and API pricing change frequently. Always verify current terms before launching a production pipeline.