📋 Overview

What it does: Automates end-to-end UGC video production from product analysis to final video delivery

Time saved: 95% reduction (from 2-3 days to 10 minutes)

Cost savings: $500+ per campaign → ~$2 per campaign

Ideal for: E-commerce brands, Marketing agencies, Content creators, Solo marketers

Key Features

🤖 AI-Powered Pipeline

  • Product Analysis — GPT-4 analyzes your product image and extracts key features

  • Character Generation — Creates consistent AI character that matches your brand

  • Scene Planning — Generates 3-5 scene campaign with complete storyboard

  • Video Generation — Produces professional videos using Google’s Veo 3

  • Automated Delivery — Emails all videos with download links

🎯 Output Quality

  • 9:16 Format — Optimized for Instagram Reels, TikTok, YouTube Shorts

  • Professional — Cinematic quality with consistent character and branding

  • Campaign Ready — Multi-scene narrative with clear messaging

  • High Resolution — 1080p MP4 files ready for immediate use

🔧 How It Works

Step 1: Product Input

Fill in the form with:

  • Product Name

  • Product Category (e.g., “Beauty”, “Tech”, “Fashion”)

  • Product Image (clear photo, max 10MB)

  • Target Audience (who you’re targeting)

  • Brand Tone (e.g., “Professional”, “Fun”, “Luxury”)

  • Campaign Goals (what you want to achieve)

Step 2: AI Processing

The workflow automatically:

  1. Analyzes your product image with GPT-4 Vision

  2. Generates a consistent AI character for your brand

  3. Plans 3-5 video scenes with complete scripts

  4. Produces each scene using Google Veo 3

  5. Aggregates all videos with metadata

Step 3: Delivery

You receive an email containing:

  • Campaign overview (product, audience, tone)

  • Download links for each video scene

  • Scene details (type, duration, description)

  • Usage tips and editing suggestions

  • Timestamp and workflow metadata

📊 Technical Architecture

Workflow Nodes (14 total)

📝 Form Trigger → 🔍 Product Analysis → 👤 Character Creation
                                              ↓
📧 Email Delivery ← 📦 Aggregate Videos ← 🎬 Scene Planning
                                              ↓
                                        🎥 Video Generation

AI Models Used

Model

Purpose

Provider

GPT-4o

Product image analysis

OpenAI

GPT-4-mini

Campaign planning & scene scripts

OpenAI

Veo 3

Video generation (3-5 scenes)

Google Gemini

Claude 3.5 Sonnet

Product analysis (alternative)

Anthropic

Integrations

  • Gmail — Email delivery system

  • AWS S3 — Product image storage

  • n8n — Workflow orchestration

  • Google Gemini — Veo 3 video generation API

💰 Cost Breakdown

Per Campaign Execution

Service

Cost

Notes

OpenAI GPT-4

~$0.50

Product analysis + planning

Google Veo 3

TBD

Currently in preview/beta

Gmail

$0

Free tier sufficient

AWS S3

~$0.02

Storage negligible

Total

~$2-5

vs $500+ for agencies

API Rate Limits

  • OpenAI: 10,000 RPM (requests per minute) on paid tier

  • Gemini/Veo 3: Varies by tier and model access

  • Gmail: 100 messages per day (free tier)

⏱️ Execution Timeline

Stage

Duration

Bottleneck

Product Analysis

10-20 sec

GPT-4o API

Character Generation

30-60 sec

Image generation

Scene Planning

15-30 sec

GPT-4-mini API

Video Generation (per scene)

3-5 min

Veo 3 processing

Email Delivery

5-10 sec

Gmail API

Total (3-5 scenes)

~10-15 min

Parallelizable

🎯 Use Cases

E-commerce Brands

Scenario: Launching new product line

  • Generate 5 videos per product

  • A/B test different messaging

  • Scale to 100+ products

  • Cost: $200 vs $50,000 agency

Marketing Agencies

Scenario: Client campaigns

  • Offer UGC video as service

  • 10x faster turnaround

  • Higher margins

  • Differentiation from competitors

Content Creators

Scenario: Sponsored content

  • Brand deal deliverables

  • Consistent quality

  • Quick iterations

  • Professional results

Solo Marketers

Scenario: Limited budget

  • DIY video production

  • No video editing skills needed

  • Agency-quality output

  • Immediate results

🛠️ Setup Requirements

Prerequisites

  1. n8n Instance (self-hosted or cloud)

  2. OpenAI Account with GPT-4 API access

  3. Google Cloud Account with Gemini/Veo 3 access

  4. Gmail Account with OAuth2 configured

  5. Optional: AWS S3 for file storage

Credentials Needed

  • OpenAI API Key (sk-proj-...)

  • Google Gemini API Key (AIza...)

  • Gmail OAuth2 (Client ID + Secret)

  • AWS S3 (if using external storage)

Installation Time

  • Import workflow: 2 minutes

  • Configure credentials: 15 minutes

  • Test execution: 10 minutes

  • Total setup: ~30 minutes

📈 Performance Metrics

Speed

  • 95% faster than manual video production

  • 90% faster than traditional agencies

  • 10 minutes vs 2-3 days turnaround

Cost

  • 98% cost reduction vs agencies

  • $2-5 per campaign vs $500+ per video

  • ROI breakeven: 1-2 campaigns

Quality

  • Professional-grade output

  • Consistent character & branding

  • Platform-optimized (9:16, 1080p)

  • Campaign-ready with narrative flow

🎨 Customization Options

Adjust Scene Count

Default: 3-5 scenes

Modify: Edit the planning prompt in “🎬 UGC Scene Planning” node

Generate a detailed plan for 4-5 video scenes
→ Change to: Generate a detailed plan for 2-3 video scenes

Change Video Style

Default: Professional UGC style

Modify: Edit Veo 3 prompts in “Split Into Individual Scenes” node

veo3_prompt: s.description ?? '' Add style: `${s.description} cinematic lighting, minimalist background`

Custom Email Template

Default: Branded HTML email

Modify: Edit HTML in “📧 Video Delivery & Notification” node

  • Update colors, fonts, layout

  • Add your branding elements

  • Customize messaging

Alternative AI Models

GPT-4 → Claude: Switch planning to Claude 3.5 Sonnet for different creative approach GPT-4-mini → GPT-4: Increase quality (higher cost) for planning stage

🐛 Troubleshooting

Videos Not Generating

Problem: Veo 3 API errors or timeouts

Solutions:

  • Check Gemini API quota and remaining credits

  • Verify Veo 3 access (may require waitlist approval)

  • Reduce scene count (from 5 to 3)

  • Shorten video duration per scene

  • Check prompt length (max ~2000 characters)

  • Retry with simpler scene descriptions

Email Not Sending

Problem: Gmail node fails to deliver

Solutions:

  • Verify OAuth2 credentials are properly configured

  • Check Gmail API is enabled in Google Cloud Console

  • Ensure “sendTo” email address is correct

  • Check spam/junk folder

  • Verify Gmail daily sending limit not exceeded

Character Inconsistency

Problem: Character looks different across scenes

Solutions:

  • Use same character reference image for all scenes

  • Add character description to every Veo 3 prompt

  • Include specific details (age, style, clothing, ethnicity)

  • Reference “consistency_elements” in scene planning

  • Keep character profile concise but detailed

Workflow Times Out

Problem: Execution exceeds timeout limit

Solutions:

  • Increase n8n execution timeout (Settings → Executions)

  • Reduce number of scenes generated (from 5 to 3)

  • Split workflow into two parts (planning → generation)

  • Enable workflow resumption on timeout

  • Process scenes in batches

Poor Video Quality

Problem: Videos don’t meet expectations

Solutions:

  • Improve product image quality (higher resolution)

  • Add more detail to scene descriptions

  • Specify lighting, camera angles, mood explicitly

  • Reference successful video examples in prompts

  • Iterate on character profile for better results

📚 Code Examples

Scene Planning Prompt Template

Create a comprehensive UGC video campaign plan based on:**Product:** {{ $('Code in JavaScript').item.json['Product Name'] }}
**Category:** {{ $('Code in JavaScript').item.json['Product Category'] }}
**Target Audience:** {{ $('Code in JavaScript').item.json['Target Audience'] }}
**Campaign Goals:** {{ $('Code in JavaScript').item.json['Campaign Goals'] }}
**Product Analysis:** {{ $('🔍 AI Product Analysis').item.json.content }}
**Character Profile:** {{ $json.id }}
Generate a detailed plan for 4-5 video scenes that tell a complete brand story.**Scene Types to Include:**1. Opening Hook (3-5 seconds) - Attention grabber
2. Product Introduction (8-10 seconds) - Showcase/unboxing
3. Feature Demonstration (10-15 seconds) - Key benefits
4. Lifestyle Integration (8-12 seconds) - Real-world usage
5. Call-to-Action (3-5 seconds) - Purchase motivation

Video Aggregation Logic

// Aggregate all generated videosconst videoData = items.map((item, index) => ({
  scene_number: item.json.scene_id || (index + 1),  scene_type: item.json.scene_type || 'scene',  duration: item.json.duration || 'N/A',  url: item.json.video_url || item.json.url,  description: item.json.description || ''}));return [{
  json: {
    product_name: items[0].json.product_name,    product_category: items[0].json.product_category,    target_audience: items[0].json.target_audience,    brand_tone: items[0].json.brand_tone,    scene_count: videoData.length,    video_links: videoData,    generated_at: new Date().toISOString()
  }
}];

🔐 Security & Privacy

Data Handling

  • Product images: Temporarily stored, can be auto-deleted

  • API keys: Stored securely in n8n credentials manager

  • Generated videos: Delivered via email, not stored long-term

  • User data: No PII collected beyond email address

Best Practices

Use environment variables for all credentials

Enable n8n authentication and HTTPS

Rotate API keys regularly (quarterly)

Monitor API usage and set billing alerts

Review and audit workflow logs

Implement rate limiting to prevent abuse

🚀 Scaling Strategies

Horizontal Scaling

Batch Processing: Connect to Google Sheets for bulk product processing

Google Sheets (products) → Loop → UGC Workflow → Collect Results

Vertical Scaling

Parallel Generation: Generate multiple scenes simultaneously

  • Split scenes into batches

  • Use n8n’s built-in parallelization

  • Reduce total execution time by 50%

Integration Scaling

API Access: Expose workflow via webhook for programmatic access

Webhook Trigger → Validate Input → UGC Workflow → Return JSON

Team Scaling

Multi-user: Set up dedicated n8n instance for team

  • Role-based access control

  • Shared credential management

  • Centralized monitoring

🎓 Learning Resources

n8n Documentation

AI APIs

Video Marketing

📝 Changelog

v1.0 (Current)

  • End-to-end UGC video generation

  • GPT-4 product analysis

  • Character generation and consistency

  • Multi-scene campaign planning

  • Veo 3 video generation

  • Automated email delivery

  • Error handling and validation

Planned Features

  • 🔄 Webhook API access

  • 🔄 Batch processing via Google Sheets

  • 🔄 Video preview before generation

  • 🔄 Custom character upload

  • 🔄 Alternative video styles

  • 🔄 Multi-language support

🏆 Why This Workflow?

Technical Excellence

Robust Error Handling — Validates inputs, handles API failures gracefully

Defensive Coding — Safe access patterns, fallback values

Modular Design — Easy to customize individual nodes

Well-Documented — Clear naming, detailed comments

Business Value

💰 Cost-Effective — 98% cheaper than agencies

Fast — 95% time reduction

🎯 Consistent — Same quality every time

📦 Complete — End-to-end automation

Community Impact

🌟 Open Source — Free for everyone

📚 Educational — Learn advanced n8n patterns

🤝 Supportive — Active community help

🚀 Portfolio-Ready — Showcase-quality work

📦 Download & Install

Quick Start

  1. Download the sanitized JSON from below.

  2. Import into your n8n instance (Settings → Import → From File)

  3. Configure credentials in n8n’s credential manager

  4. Update email address in Gmail node

  5. Test with sample product data

Full JSON Workflow

{
  "name": "\ud83c\udfac AI UGC Video Campaign Generator",
  "nodes": [
    {
      "parameters": {
        "sendTo": "{{ USER_EMAIL }}",
        "subject": "=\ud83c\udfac {{ $json.scene_count }} UGC Video Scenes Ready \u2014 {{ $json.product_name }}",
        "message": "=<div style=\"font-family: Arial, sans-serif; max-width: 620px; margin: 0 auto; background-color: #f5f5f5; padding: 20px;\">\n  <div style=\"background:#ffffff; border-radius:10px; padding:30px; box-shadow:0 2px 10px rgba(0,0,0,0.1);\">\n    \n    <!-- Header -->\n    <h2 style=\"color:#333; border-bottom:3px solid #4CAF50; padding-bottom:10px; margin:0;\">\n      \ud83c\udfac Your UGC Campaign Videos Are Ready!\n    </h2>\n\n    <!-- Campaign Details -->\n    <div style=\"background:#f9f9f9; padding:20px; border-radius:8px; margin:20px 0;\">\n      <h3 style=\"color:#4CAF50; margin:0 0 10px;\">\ud83d\udce6 Campaign Details</h3>\n      <table style=\"width:100%; border-collapse:collapse;\">\n        <tr>\n          <td style=\"padding:8px 0; font-weight:bold; color:#666;\">Product:</td>\n          <td style=\"padding:8px 0;\">{{ $json.product_name }}</td>\n        </tr>\n        <tr>\n          <td style=\"padding:8px 0; font-weight:bold; color:#666;\">Category:</td>\n          <td style=\"padding:8px 0;\">{{ $json.product_category }}</td>\n        </tr>\n        <tr>\n          <td style=\"padding:8px 0; font-weight:bold; color:#666;\">Target Audience:</td>\n          <td style=\"padding:8px 0;\">{{ $json.target_audience }}</td>\n        </tr>\n        <tr>\n          <td style=\"padding:8px 0; font-weight:bold; color:#666;\">Brand Tone:</td>\n          <td style=\"padding:8px 0;\">{{ $json.brand_tone }}</td>\n        </tr>\n        <tr>\n          <td style=\"padding:8px 0; font-weight:bold; color:#666;\">Total Scenes:</td>\n          <td style=\"padding:8px 0;\">{{ $json.scene_count }} professional UGC videos</td>\n        </tr>\n      </table>\n    </div>\n\n    <!-- Video Downloads -->\n    <div style=\"background:#e8f5e8; padding:20px; border-radius:8px; margin:20px 0;\">\n      <h3 style=\"color:#2e7d32; margin:0 0 10px;\">\ud83d\udce5 Download Your Video Scenes</h3>\n      <p style=\"color:#555; margin:0 0 15px;\">Click the buttons below to download each scene:</p>\n\n      {{ $json.video_links.map(video => `\n        <div style='margin:10px 0; padding:15px; background:#ffffff; border-radius:6px; border-left:4px solid #4CAF50;'>\n          <div style='display:flex; justify-content:space-between; align-items:center; gap:12px;'>\n            <div style='min-width:0;'>\n              <strong style='color:#333; font-size:16px; display:block;'>Scene ${video.scene_number}</strong>\n              <span style='color:#666; font-size:14px;'>${video.scene_type} \u2022 ${video.duration}</span>\n            </div>\n            <a href='${video.url}'\n               style='background:#4CAF50; color:#ffffff; padding:10px 16px; text-decoration:none; border-radius:5px; font-weight:bold; display:inline-block; white-space:nowrap;'>\n              \u2b07\ufe0f Download\n            </a>\n          </div>\n        </div>\n      `).join('') }}\n    </div>\n\n    <!-- Usage Tips -->\n    <div style=\"background:#fff3cd; padding:20px; border-radius:8px; margin:20px 0; border-left:4px solid #ffc107;\">\n      <h3 style=\"color:#856404; margin:0 0 8px;\">\ud83d\udca1 Usage Tips</h3>\n      <ul style=\"color:#856404; margin:0; padding-left:20px;\">\n        <li style=\"margin:8px 0;\">Optimized for 9:16 (Reels, TikTok, Shorts)</li>\n        <li style=\"margin:8px 0;\">Character & product consistency across scenes</li>\n        <li style=\"margin:8px 0;\">Import into CapCut / Premiere / iMovie to combine</li>\n        <li style=\"margin:8px 0;\">High-resolution MP4 files</li>\n        <li style=\"margin:8px 0;\">Links may expire in 30 days \u2014 download now</li>\n      </ul>\n    </div>\n\n    <!-- Editing Suggestions -->\n    <div style=\"background:#e3f2fd; padding:20px; border-radius:8px; margin:20px 0; border-left:4px solid #2196F3;\">\n      <h3 style=\"color:#1565C0; margin:0 0 8px;\">\ud83c\udfac Recommended Editing Flow</h3>\n      <ol style=\"color:#1565C0; margin:0; padding-left:20px;\">\n        <li style=\"margin:8px 0;\">Download all scenes</li>\n        <li style=\"margin:8px 0;\">Import into your video editor</li>\n        <li style=\"margin:8px 0;\">Add transitions (fade recommended)</li>\n        <li style=\"margin:8px 0;\">Add background music</li>\n        <li style=\"margin:8px 0;\">Export as MP4 (9:16 aspect ratio)</li>\n      </ol>\n    </div>\n\n    <!-- Footer -->\n    <div style=\"text-align:center; margin-top:30px; padding-top:20px; border-top:1px solid #ddd;\">\n      <p style=\"color:#666; font-size:14px; margin:5px 0;\">\u2728 Generated by AI UGC Video Campaign Generator</p>\n      <p style=\"color:#666; font-size:14px; margin:5px 0;\">\ud83e\udd77 Created by Rananjay</p>\n      <p style=\"color:#999; font-size:12px; margin:5px 0;\">Powered by Veo 3 \u2022 Generated on {{ $json.generated_at.split('T')[0] }}</p>\n      <p style=\"color:#999; font-size:12px; margin:5px 0;\">Need modifications? Reply to this email with your feedback.</p>\n    </div>\n\n  </div>\n</div>\n",
        "options": {}
      },
      "id": "node_1",
      "name": "\ud83d\udce7 Video Delivery & Notification",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        -8832,
        656
      ],
      "webhookId": "{{ WEBHOOK_ID }}",
      "credentials": {
        "gmailOAuth2": {
          "id": "{{ CREDENTIAL_ID }}",
          "name": "Gmail account 2"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// Defensive Split Into Individual Scenes (paste into Code node)\n\n// ---------- Helper: safe node getter ----------\nfunction safeNodeJson(nodeName) {\n  try {\n    // prefer $node which is available in n8n code nodes\n    const node = $node ? $node[nodeName] : undefined;\n    if (node && node.json) return node.json;\n    // fallback to legacy $('nodeName').item.json if used elsewhere\n    const alt = typeof $ === 'function' ? $(nodeName) : undefined;\n    if (alt && alt.item && alt.item.json) return alt.item.json;\n  } catch (e) {\n    // ignore\n  }\n  return undefined;\n}\n\n// ---------- 1) Read planning response robustly ----------\nlet planningResponseRaw;\ntry {\n  // prefer incoming item (items[] from previous node)\n  const first = items && items[0] && items[0].json ? items[0].json : undefined;\n\n  if (!first) {\n    throw new Error('No incoming item found on the node input.');\n  }\n\n  // common OpenAI shape: choices[0].message.content\n  if (first.choices && Array.isArray(first.choices) && first.choices[0]?.message?.content) {\n    planningResponseRaw = first.choices[0].message.content;\n  }\n  // some nodes expose message directly: message.content\n  else if (first.message && first.message.content) {\n    planningResponseRaw = first.message.content;\n  }\n  // sometimes the node returns content at .content\n  else if (first.content && typeof first.content === 'string') {\n    planningResponseRaw = first.content;\n  }\n  // fallback: try stringify entire object\n  else {\n    planningResponseRaw = JSON.stringify(first);\n  }\n} catch (err) {\n  throw new Error('Failed reading planning response: ' + String(err));\n}\n\n// ---------- 2) Extract JSON block (```json ... ``` ) or parse plain JSON ----------\nlet scenePlan;\ntry {\n  const jsonBlockMatch = typeof planningResponseRaw === 'string' && planningResponseRaw.match(/```json\\s*([\\s\\S]*?)\\s*```/i);\n  const jsonToParse = jsonBlockMatch ? jsonBlockMatch[1] : planningResponseRaw;\n\n  // Some model outputs include escaped newlines or extra quoting; try a couple of safe parsing attempts\n  try {\n    scenePlan = JSON.parse(jsonToParse);\n  } catch (e1) {\n    // attempt to unescape if wrapped in an extra string\n    const attempt2 = jsonToParse.replace(/\\n+/g, '\\n').trim();\n    scenePlan = JSON.parse(attempt2);\n  }\n} catch (e) {\n  // fallback minimal scene plan so workflow can continue\n  console.warn('Failed to parse scene plan JSON \u2014 using fallback. Error:', e);\n  scenePlan = {\n    campaign_overview: {\n      total_duration: \"45 seconds\",\n      narrative_flow: \"Product introduction to lifestyle integration\",\n      brand_message: \"Quality and innovation\"\n    },\n    scenes: [\n      {\n        scene_id: 1,\n        type: \"opening_hook\",\n        duration: \"5 seconds\",\n        description: \"Character holds product with excitement\",\n        character_action: \"Hold product and smile\",\n        camera_setup: \"Close-up\",\n        environment: \"Studio\",\n        props: [],\n        dialogue: \"\",\n        voice_over: \"\"\n      }\n    ],\n    consistency_elements: {}\n  };\n}\n\n// Ensure scenes array exists\nif (!scenePlan.scenes || !Array.isArray(scenePlan.scenes) || scenePlan.scenes.length === 0) {\n  // nothing to split \u2014 return empty so downstream nodes don't fail\n  return [];\n}\n\n// ---------- 3) Get other node outputs safely (update names if you renamed nodes) ----------\nconst characterNodeName = 'Message a model'; // replace if you renamed\nconst productFormNodeName = 'Code in JavaScript'; // this node sets product_image etc\nconst productAnalysisNodeName = '\ud83d\udd0d AI Product Analysis';\n\nconst characterData = safeNodeJson(characterNodeName) || {};\nconst productData = safeNodeJson(productFormNodeName) || {};\nconst productAnalysisNode = safeNodeJson(productAnalysisNodeName) || {};\n\n// productAnalysis might be nested (e.g. .content or .message.content)\nlet productAnalysis = null;\nif (productAnalysisNode.choices && productAnalysisNode.choices[0]?.message?.content) {\n  productAnalysis = productAnalysisNode.choices[0].message.content;\n} else if (productAnalysisNode.message && productAnalysisNode.message.content) {\n  productAnalysis = productAnalysisNode.message.content;\n} else if (productAnalysisNode.content) {\n  productAnalysis = productAnalysisNode.content;\n} else {\n  productAnalysis = JSON.stringify(productAnalysisNode).slice(0, 1000); // small fallback\n}\n\n// ---------- 4) Build scene items with safe access and defaults ----------\nconst sceneItems = scenePlan.scenes.map((scene, index) => {\n  // ensure minimal structure per scene\n  const s = scene || {};\n  return {\n    json: {\n      scene_id: s.scene_id ?? (index + 1),\n      scene_type: s.type ?? s.scene_type ?? 'scene',\n      duration: s.duration ?? s.estimated_duration ?? null,\n      description: s.description ?? '',\n      character_action: s.character_action ?? '',\n      camera_setup: s.camera_setup ?? '',\n      environment: s.environment ?? '',\n      props: s.props ?? [],\n      dialogue: s.dialogue ?? '',\n      voice_over: s.voice_over ?? '',\n      veo3_prompt: s.veo3_prompt ?? s.prompt ?? `${s.description ?? ''}`,\n\n      // Campaign context\n      campaign_overview: scenePlan.campaign_overview ?? {},\n      consistency_elements: scenePlan.consistency_elements ?? {},\n\n      // Character reference (safe)\n      character_id: characterData.character_id ?? null,\n      character_image_url: characterData.character_image_url ?? characterData.character_image ?? null,\n      character_profile: characterData.character_profile ?? characterData,\n\n      // Product context (safe keys \u2014 adapt to your form fields if different)\n      product_name: productData['Product Name'] ?? productData.product_name ?? productData.ProductName ?? null,\n      product_image: productData.product_image ?? productData.product_image_direct ?? null,\n      product_category: productData['Product Category'] ?? productData.product_category ?? null,\n      target_audience: productData['Target Audience'] ?? productData.target_audience ?? null,\n      brand_tone: productData['Brand Tone'] ?? productData.brand_tone ?? null,\n      campaign_goals: productData['Campaign Goals'] ?? productData.campaign_goals ?? null,\n\n      // Analysis data\n      product_analysis: productAnalysis,\n\n      // Metadata\n      total_scenes: (Array.isArray(scenePlan.scenes) ? scenePlan.scenes.length : 1),\n      processing_timestamp: new Date().toISOString(),\n      workflow_id: ($workflow && $workflow.id) ? $workflow.id : 'manual-execution'\n    }\n  };\n});\n\n// return array of items\nreturn sceneItems;\n"
      },
      "id": "node_2",
      "name": "Split Into Individual Scenes",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -10544,
        656
      ]
    },
    {
      "parameters": {
        "modelId": {
          "__rl": true,
          "value": "gpt-4.1-mini",
          "mode": "list",
          "cachedResultName": "GPT-4.1-MINI"
        },
        "messages": {
          "values": [
            {
              "content": "=\"Create a comprehensive UGC video campaign plan based on:\\\\n\\\\n**Product:** {{ $('Code in JavaScript').item.json['Product Name'] }}\\\\n**Category:**{{ $('Code in JavaScript').item.json['Product Category'] }} \\\\n**Target Audience:** {{ $('Code in JavaScript').item.json['Target Audience'] }}\\\\n**Campaign Goals:** {{ $('Code in JavaScript').item.json['Campaign Goals'] }}\\\\n\\\\n**Product Analysis:** {{ $('\ud83d\udd0d AI Product Analysis').item.json.content }}\\\\n\\\\n**Character Profile:** {{ $json.id }}\\\\n\\\\nGenerate a detailed plan for 4-5 video scenes that tell a complete brand story:\\\\n\\\\n**Scene Types to Include:**\\\\n1. **Opening Hook** (3-5 seconds) - Attention grabber\\\\n2. **Product Introduction** (8-10 seconds) - Showcase/unboxing\\\\n3. **Feature Demonstration** (10-15 seconds) - Key benefits\\\\n4. **Lifestyle Integration** (8-12 seconds) - Real-world usage\\\\n5. **Call-to-Action** (3-5 seconds) - Purchase motivation\\\\n\\\\nFor each scene provide:\\\\n- Scene description and purpose\\\\n- Character actions and expressions\\\\n- Camera angles and movements\\\\n- Environment and lighting\\\\n- Props and product positioning\\\\n- Dialogue/voice-over text\\\\n- Transition elements\\\\n\\\\nFormat as JSON:\\\\n```json\\\\n{\\\\n  \\\\\\\"campaign_overview\\\\\\\": {\\\\n    \\\\\\\"total_duration\\\\\\\": \\\\\\\"40-45 seconds\\\\\\\",\\\\n    \\\\\\\"narrative_flow\\\\\\\": \\\\\\\"\\\\\\\",\\\\n    \\\\\\\"brand_message\\\\\\\": \\\\\\\"\\\\\\\"\\\\n  },\\\\n  \\\\\\\"scenes\\\\\\\": [\\\\n    {\\\\n      \\\\\\\"scene_id\\\\\\\": 1,\\\\n      \\\\\\\"type\\\\\\\": \\\\\\\"opening_hook\\\\\\\",\\\\n      \\\\\\\"duration\\\\\\\": \\\\\\\"3-5 seconds\\\\\\\",\\\\n      \\\\\\\"description\\\\\\\": \\\\\\\"\\\\\\\",\\\\n      \\\\\\\"character_action\\\\\\\": \\\\\\\"\\\\\\\",\\\\n      \\\\\\\"camera_setup\\\\\\\": \\\\\\\"\\\\\\\",\\\\n      \\\\\\\"environment\\\\\\\": \\\\\\\"\\\\\\\",\\\\n      \\\\\\\"props\\\\\\\": [],\\\\n      \\\\\\\"dialogue\\\\\\\": \\\\\\\"\\\\\\\",\\\\n      \\\\\\\"veo3_prompt\\\\\\\": \\\\\\\"\\\\\\\"\\\\n    }\\\\n  ],\\\\n  \\\\\\\"consistency_elements\\\\\\\": {\\\\n    \\\\\\\"character_appearance\\\\\\\": \\\\\\\"\\\\\\\",\\\\n    \\\\\\\"color_scheme\\\\\\\": [],\\\\n    \\\\\\\"lighting_style\\\\\\\": \\\\\\\"\\\\\\\",\\\\n    \\\\\\\"brand_elements\\\\\\\": []\\\\n  }\\\\n}\\\\n```\""
            }
          ]
        },
        "options": {}
      },
      "id": "node_3",
      "name": "\ud83d\udcdd UGC Scene Planning",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "typeVersion": 1.8,
      "position": [
        -10832,
        656
      ],
      "credentials": {
        "openAiApi": {
          "id": "{{ CREDENTIAL_ID }}",
          "name": "OpenAi"
        }
      }
    },
    {
      "parameters": {
        "resource": "image",
        "operation": "analyze",
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o"
        },
        "text": "=Analyze this product image and provide detailed insights for UGC video creation:\n\n**Product Context:**\n- Product Name: {{ $json['Product Name'] }}\n- Category: {{ $json['Product Category'] }}\n- Target Audience: {{ $json['Target Audience'] }}\n- Campaign Goals: {{ $json['Campaign Goals'] }}\n- Brand Tone - {{ $json['Brand Tone'] }}\n\n**Product Analysis:**\n1. Product type and key features visible in the image\n2. Visual characteristics (colors, materials, design style)\n3. Positioning and angle suggestions for video\n4. Key selling points to highlight\n5. How well the product aligns with the stated target audience\n6. Brand personality indicators that match the desired brand tone\n\n**UGC Video Recommendations:**\n1. Ideal character demographics (age, style, personality) that match the target audience\n2. Recommended video scenarios (unboxing, demo, lifestyle) based on campaign goals\n3. Environment suggestions (indoor/outdoor, background style) matching brand tone\n4. Props and accessories needed\n5. Lighting and mood preferences that align with the brand\n\nFormat response as JSON:\n```json\n{\n  \"product\": {\n    \"type\": \"\",\n    \"features\": [],\n    \"visual_characteristics\": {},\n    \"selling_points\": []\n  },\n  \"character_brief\": {\n    \"age_range\": \"\",\n    \"style\": \"\",\n    \"personality\": \"\",\n    \"demographic\": \"\"\n  },\n  \"video_scenarios\": [\n    {\n      \"type\": \"unboxing\",\n      \"description\": \"\",\n      \"environment\": \"\",\n      \"props\": []\n    }\n  ],\n  \"brand_guidelines\": {\n    \"colors\": [],\n    \"mood\": \"\",\n    \"lighting\": \"\"\n  }\n}\n```",
        "imageUrls": "={{ $json.product_image_direct }}",
        "options": {}
      },
      "id": "node_4",
      "name": "\ud83d\udd0d AI Product Analysis",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "typeVersion": 1.8,
      "position": [
        -10320,
        320
      ],
      "credentials": {
        "openAiApi": {
          "id": "{{ CREDENTIAL_ID }}",
          "name": "OpenAi"
        }
      }
    },
    {
      "parameters": {
        "formTitle": "\ud83c\udfac UGC Video Campaign Generator",
        "formDescription": "Upload your product image to generate professional UGC campaign videos with consistent AI characters. Supported formats: JPG, PNG, WebP (max 10MB)",
        "formFields": {
          "values": [
            {
              "fieldLabel": "Product Name",
              "placeholder": "e.g., Wireless Bluetooth Headphones",
              "requiredField": true
            },
            {
              "fieldLabel": "Product Category",
              "fieldType": "dropdown",
              "fieldOptions": {
                "values": [
                  {
                    "option": "Electronics"
                  },
                  {
                    "option": "Fashion & Accessories"
                  },
                  {
                    "option": "Health & Beauty"
                  },
                  {
                    "option": "Home & Garden"
                  },
                  {
                    "option": "Sports & Outdoors"
                  },
                  {
                    "option": "Food & Beverage"
                  },
                  {
                    "option": "Books & Media"
                  },
                  {
                    "option": "Other"
                  }
                ]
              },
              "requiredField": true
            },
            {
              "fieldLabel": "Target Audience",
              "fieldType": "dropdown",
              "fieldOptions": {
                "values": [
                  {
                    "option": "Young Adults (18-29)"
                  },
                  {
                    "option": "Millennials (30-39)"
                  },
                  {
                    "option": "Gen X (40-54)"
                  },
                  {
                    "option": "Professionals"
                  },
                  {
                    "option": "Parents"
                  },
                  {
                    "option": "Fitness Enthusiasts"
                  },
                  {
                    "option": "Tech Savvy"
                  },
                  {
                    "option": "General Consumer"
                  }
                ]
              },
              "requiredField": true
            },
            {
              "fieldLabel": "Brand Tone",
              "fieldType": "dropdown",
              "fieldOptions": {
                "values": [
                  {
                    "option": "Professional"
                  },
                  {
                    "option": "Friendly & Casual"
                  },
                  {
                    "option": "Energetic & Fun"
                  },
                  {
                    "option": "Luxury & Premium"
                  },
                  {
                    "option": "Minimalist & Clean"
                  },
                  {
                    "option": "Bold & Edgy"
                  }
                ]
              }
            },
            {
              "fieldLabel": "Campaign Goals",
              "fieldType": "multiselect"
            },
            {
              "fieldLabel": "Image URL",
              "placeholder": "Enter the Image URL here. ",
              "requiredField": true
            }
          ]
        },
        "responseMode": "lastNode",
        "options": {}
      },
      "id": "node_5",
      "name": "Product Upload Form",
      "type": "n8n-nodes-base.formTrigger",
      "typeVersion": 2.3,
      "position": [
        -10768,
        320
      ],
      "webhookId": "{{ WEBHOOK_ID }}"
    },
    {
      "parameters": {
        "jsCode": "const item = items[0];\nconst driveUrl = item.json['Image URL'];\n\n// Extract file ID from Google Drive URL\nconst fileIdMatch = driveUrl.match(/\\/d\\/([a-zA-Z0-9_-]+)/);\nif (!fileIdMatch) {\n  throw new Error('Invalid Google Drive URL');\n}\n\nconst fileId = fileIdMatch[1];\n\n// Convert to direct image URL\nconst directUrl = `https://drive.google.com/uc?export=view&id=${fileId}`;\n\nreturn [{\n  json: {\n    ...item.json,\n    product_image: directUrl,\n    product_image_direct: directUrl\n  }\n}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -10544,
        320
      ],
      "id": "node_6",
      "name": "Code in JavaScript"
    },
    {
      "parameters": {
        "resource": "image",
        "modelId": {
          "__rl": true,
          "value": "models/imagen-3.0-generate-002",
          "mode": "list",
          "cachedResultName": "models/imagen-3.0-generate-002"
        },
        "prompt": "=\"Professional portrait photo of {{ $json.content.parts[0].text }}. High quality, 4K, studio lighting, neutral background, realistic, photography style suitable for UGC content creation.\"",
        "options": {
          "sampleCount": 1
        }
      },
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "typeVersion": 1,
      "position": [
        -10080,
        320
      ],
      "id": "node_7",
      "name": "Generate an image",
      "credentials": {
        "googlePalmApi": {
          "id": "{{ CREDENTIAL_ID }}",
          "name": "Google Gemini(PaLM) Api account"
        }
      }
    },
    {
      "parameters": {
        "resource": "video",
        "modelId": {
          "__rl": true,
          "value": "models/veo-3.1-generate-preview",
          "mode": "list",
          "cachedResultName": "models/veo-3.1-generate-preview"
        },
        "prompt": "={\n  \"prompt\": \"{{ $json.veo3_prompt }}\\n\\nCharacter Reference: {{ $json.character_profile?.content?.parts?.[0]?.text ?? $json.character_profile ?? '' }}\\nProduct: {{ $json.product_name }}\\nScene Type: {{ $json.scene_type }}\\nDuration: {{ $json.duration }}\\nEnvironment: {{ $json.environment }}\\nCamera: {{ $json.camera_setup }}\\nBrand Tone: {{ $json.brand_tone }}\",\n  \"character_reference\": {\n    \"character_id\": \"{{ $json.character_id ?? '' }}\",\n    \"character_image\": {{ $('Generate an image').item.json.fileName }},\n    \"consistency_mode\": \"strict\"\n  },\n  \"product_reference\": {\n    \"product_image\": {{ $json.product_image }},\n    \"product_name\": \"{{ $json.product_name }}\",\n    \"integration_mode\": \"prominent\"\n  },\n  \"generation_settings\": {\n    \"duration\": {{ (() => { const d = $json.duration ?? ''; const m = (''+d).match(/\\\\d+/); return m ? Number(m[0]) : 5; })() }},\n    \"resolution\": \"1080p\",\n    \"frame_rate\": 30,\n    \"quality\": \"high\",\n    \"style\": \"realistic_ugc\",\n    \"aspect_ratio\": \"9:16\"\n  },\n  \"consistency_controls\": {\n    \"character_appearance\": \"{{ $json.consistency_elements?.character_appearance ?? '' }}\",\n    \"lighting_style\": \"{{ $json.consistency_elements?.lighting_style ?? '' }}\",\n    \"color_scheme\": {{ Array.isArray($json.consistency_elements?.color_scheme) ? $json.consistency_elements.color_scheme.join(', ') : ($json.consistency_elements?.color_scheme ?? '') }},\n    \"brand_elements\": {{ (() => { const v = $json.consistency_elements?.brand_elements; return v ? (Array.isArray(v) ? v : [v]) : []; })() }}\n  },\n  \"metadata\": {\n    \"scene_id\": \"{{ $json.scene_id }}\",\n    \"scene_type\": \"{{ $json.scene_type }}\",\n    \"campaign_id\": \"{{ $json.workflow_id }}\",\n    \"processing_batch\": \"{{ $json.processing_timestamp }}\"\n  }\n}\n",
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "typeVersion": 1,
      "position": [
        -10304,
        784
      ],
      "id": "node_8",
      "name": "Generate a video",
      "credentials": {
        "googlePalmApi": {
          "id": "{{ CREDENTIAL_ID }}",
          "name": "Google Gemini(PaLM) Api account"
        }
      }
    },
    {
      "parameters": {
        "operation": "upload",
        "bucketName": "ugc-video-storage",
        "fileName": "={{ $('Build R2 Key').item.json.r2Key }}",
        "additionalFields": {}
      },
      "type": "n8n-nodes-base.s3",
      "typeVersion": 1,
      "position": [
        -9744,
        528
      ],
      "id": "node_9",
      "name": "Upload a file",
      "alwaysOutputData": true,
      "credentials": {
        "s3": {
          "id": "{{ CREDENTIAL_ID }}",
          "name": "S3 Account"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "return $input.all().map((item, idx) => {\n  // prefer the scene item\u2019s product_name; fall back to the form if needed\n  const form = $items('Code in JavaScript')[0]?.json || {};\n  const rawName =\n    item.json.product_name ||\n    item.json['Product Name'] ||\n    form['Product Name'] ||\n    'unknown';\n\n  const ts = new Date().toISOString().replace(/[:.]/g, '-');\n  const slug = String(rawName).toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');\n  const scene = item.json.scene_id ?? (idx + 1);\n\n  const r2Key = item.json.r2Key || `videos/${ts}/${slug}-scene-${scene}.mp4`;\n\n  return {\n    json: { ...item.json, r2Key },\n    binary: item.binary, // keep the 'data' binary\n  };\n});\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -10304,
        592
      ],
      "id": "node_10",
      "name": "Build R2 Key"
    },
    {
      "parameters": {
        "mode": "combine",
        "combineBy": "combineByPosition",
        "options": {}
      },
      "type": "n8n-nodes-base.merge",
      "typeVersion": 3.2,
      "position": [
        -10032,
        656
      ],
      "id": "node_11",
      "name": "Merge"
    },
    {
      "parameters": {
        "jsCode": "const base = 'https://pub-2963c4b8a825436383342e84f66644b7.r2.dev';\nreturn items.map(item => ({\n  json: {\n    ...item.json,\n    download_url: `${base}/${item.json.r2Key}`\n  }\n}));\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -9296,
        656
      ],
      "id": "node_12",
      "name": "Build Final Video URL"
    },
    {
      "parameters": {
        "mode": "combine",
        "combineBy": "combineByPosition",
        "options": {}
      },
      "type": "n8n-nodes-base.merge",
      "typeVersion": 3.2,
      "position": [
        -9520,
        656
      ],
      "id": "node_13",
      "name": "Merge after Upload"
    },
    {
      "parameters": {
        "jsCode": "const itemsIn = $input.all();\nconst links = itemsIn.map(it => ({\n  scene_number: it.json.scene_id,\n  scene_type: it.json.scene_type,\n  duration: it.json.duration,\n  url: it.json.download_url\n}));\nreturn [{\n  json: {\n    product_name: itemsIn[0]?.json?.product_name,\n    product_category: itemsIn[0]?.json?.product_category,\n    target_audience: itemsIn[0]?.json?.target_audience,\n    brand_tone: itemsIn[0]?.json?.brand_tone,\n    scene_count: links.length,\n    video_links: links,\n    generated_at: new Date().toISOString()\n  }\n}];\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -9088,
        656
      ],
      "id": "node_14",
      "name": "Aggregate Video Links"
    }
  ],
  "pinData": {
    "Product Upload Form": [
      {
        "json": {
          "Product Name": "iPhone 17 Pro Max",
          "Product Category": "Electronics",
          "Target Audience": "Tech Savvy",
          "Brand Tone": "Friendly & Casual",
          "Campaign Goals": "Product Sales",
          "Image URL": "https://drive.google.com/file/d/1I9z1zwGz7qt_O1I1z_tPH4hw78swQGp6/view?usp=sharing",
          "submittedAt": "2025-11-05T19:16:10.922+05:30",
          "formMode": "test"
        }
      }
    ]
  },
  "connections": {
    "\ud83d\udce7 Video Delivery & Notification": {
      "main": [
        []
      ]
    },
    "Split Into Individual Scenes": {
      "main": [
        [
          {
            "node": "Build R2 Key",
            "type": "main",
            "index": 0
          },
          {
            "node": "Generate a video",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udd0d AI Product Analysis": {
      "main": [
        [
          {
            "node": "Generate an image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Product Upload Form": {
      "main": [
        [
          {
            "node": "Code in JavaScript",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udcdd UGC Scene Planning": {
      "main": [
        [
          {
            "node": "Split Into Individual Scenes",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code in JavaScript": {
      "main": [
        [
          {
            "node": "\ud83d\udd0d AI Product Analysis",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate an image": {
      "main": [
        [
          {
            "node": "\ud83d\udcdd UGC Scene Planning",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate a video": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Upload a file": {
      "main": [
        [
          {
            "node": "Merge after Upload",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge": {
      "main": [
        [
          {
            "node": "Upload a file",
            "type": "main",
            "index": 0
          },
          {
            "node": "Merge after Upload",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Build R2 Key": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Final Video URL": {
      "main": [
        [
          {
            "node": "Aggregate Video Links",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge after Upload": {
      "main": [
        [
          {
            "node": "Build Final Video URL",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate Video Links": {
      "main": [
        [
          {
            "node": "\ud83d\udce7 Video Delivery & Notification",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "{{ VERSION_ID }}",
  "meta": {
    "templateCredsSetupCompleted": true,
    "instanceId": "{{ INSTANCE_ID }}"
  },
  "id": "{{ WORKFLOW_ID }}",
  "tags": [
    {
      "createdAt": "2025-09-21T13:10:32.954Z",
      "updatedAt": "2025-09-21T13:10:32.954Z",
      "id": "PRSR5amilTnECOSs",
      "name": "Video Automation"
    },
    {
      "createdAt": "2025-09-21T13:10:33.006Z",
      "updatedAt": "2025-09-21T13:10:33.006Z",
      "id": "Z1EhapVEvgVGZB2V",
      "name": "UGC Generation"
    },
    {
      "createdAt": "2025-09-21T13:10:33.031Z",
      "updatedAt": "2025-09-21T13:10:33.031Z",
      "id": "bb9cchy99IYqF5Xk",
      "name": "AI Content Creation"
    },
    {
      "createdAt": "2025-09-21T13:10:32.981Z",
      "updatedAt": "2025-09-21T13:10:32.981Z",
      "id": "qESgqtpRYmzgdn9w",
      "name": "E-commerce"
    }
  ]
}