> ## Content Index
> Fetch the complete content index at: https://buildwire.ai/llms.txt
> Use this file to discover other available public pages before exploring further.

# 🎬 YouTube Shorts Automation with Veo 3
- URL: https://buildwire.ai/blog/youtube-shorts-automation-with-veo-3/
- Published: 2026-01-14T04:30:03.000Z
- Updated: 2026-06-14T07:31:15.000Z
- Description: Automate the creation of high-performing YouTube Shorts in minutes using AI-powered script generation, Veo 3 video creation, and professional voiceovers.
- Author: Rananjay Raj
- Tags: #beehiiv, #Migrated-1781422191461, #Import 2026-06-14 13:00

## 🎯 Overview

This n8n workflow automates the entire YouTube Shorts creation process:

1. **User submits** video idea via web form
2. **AI generates** SEO-optimized script (OpenAI GPT-4)
3. **AI creates** professional voiceover (ElevenLabs)
4. **Veo 3 generates** high-quality vertical video (Google Gemini)
5. **System merges** audio + video
6. **User receives** download link via email

**Total Processing Time:** 2-3 minutes per video

---

## ✨ Features

### 🤖 AI-Powered Content Generation

- **Smart Script Writing:** GPT-4 creates engaging, viral-ready scripts
- **SEO Optimization:** Automatic keyword extraction and title suggestions
- **Content Analysis:** AI determines optimal video style based on topic

### 🎬 Veo 3 Video Generation

- **Cinematic Quality:** 720p vertical videos (9:16 aspect ratio)
- **Style Flexibility:** Realistic, animated, or mixed based on content
- **8-second clips:** Perfect for short-form content(Currently Gemini API limits the video to 8 seconds default, but it can be by-passed by creating multiple 8-sec videos and stitching them together FFmpeg

### 🎤 Professional Voiceovers

- **Natural Speech:** ElevenLabs Turbo v2.5 for realistic narration
- **Voice Options:** Multiple voice styles (professional, energetic, warm)
- **Perfect Timing:** Voiceover synced with video length

### 📊 Complete Workflow

- **Web Form Interface:** Easy-to-use submission form
- **Automated Processing:** No manual intervention required
- **Email Delivery:** Downloadable links with full video details
- **7-Day Storage:** Videos accessible for a week

---

## 🔧 Prerequisites

### Required Services:

1. **n8n Instance** (v1.0+)
  - Self-hosted or cloud (n8n.cloud)
2. **API Keys:**
  - Google Gemini API - Veo 3 access
  - OpenAI API - GPT-4 script generation
  - ElevenLabs API - Voiceover generation
3. **Storage Solution:**
  - Cloudflare R2 (recommended - free tier available)
  - OR AWS S3
4. **Email Service:**
  - Gmail account with OAuth2 configured in n8n

### Recommended:

- **FFmpeg** installed on n8n server (for audio-video merging)
- **At least 2GB RAM** on n8n server
- **Fast internet connection** (for video downloads)

---

## 🚀 Quick Start

### 1\. Import Workflow

```
# In n8n UI:
1. Go to Workflows
2. Click "Import from File"
3. Select: youtube-shorts-veo3-workflow.json
4. Click "Import"

```

### 2\. Configure Environment Variables

```
# Copy example file
cp .env.example .env

# Edit with your API keys
nano .env

```

Add your API keys:

```
GOOGLE_API_KEY=your_actual_google_key
OPENAI_API_KEY=your_actual_openai_key
ELEVENLABS_API_KEY=your_actual_elevenlabs_key
CLOUDFLARE_R2_ENDPOINT=your_r2_endpoint

```

### 3\. Set Up Credentials in n8n

**DO NOT paste credentials directly into nodes!** Use n8n’s credential manager:

1. **Google Gemini/Veo 3:**
  - Go to: Credentials → Add Credential → HTTP Header Auth
  - Name: `Google Veo 3 API`
  - Header Name: `x-goog-api-key`
  - Value: Your Google API key
2. **OpenAI:**
  - Go to: Credentials → Add Credential → OpenAI API
  - Name: `OpenAI GPT-4`
  - API Key: Your OpenAI key
3. **ElevenLabs:**
  - Go to: Credentials → Add Credential → HTTP Header Auth
  - Name: `ElevenLabs Voice`
  - Header Name: `xi-api-key`
  - Value: Your ElevenLabs key
4. **Gmail:**
  - Go to: Credentials → Add Credential → Gmail OAuth2
  - Follow the OAuth setup wizard

### 4\. Attach Credentials to Nodes

In the n8n workflow editor:

1. Click each node that requires credentials
2. Select the appropriate credential from dropdown
3. Save the workflow

### 5\. Activate Workflow

```
# In n8n UI:
1. Open the workflow
2. Toggle "Active" switch to ON
3. Copy the webhook URL

```

---

## 📖 Detailed Setup

### Step 1: Install n8n (if not already installed)

**Option A: Self-hosted (Docker)**

```
docker run -it --rm \\
  --name n8n \\
  -p 5678:5678 \\
  -v ~/.n8n:/home/node/.n8n \\
  n8nio/n8n

```

**Option B: n8n Cloud**

- Sign up at [n8n.cloud](https://n8n.cloud/?utm%5Fsource=theaidrivenmarketer.beehiiv.com&utm%5Fmedium=referral&utm%5Fcampaign=youtube-shorts-automation-with-veo-3)
- Follow guided setup

### Step 2: Get API Keys

### Google Gemini API (Veo 3)

1. Go to [Google AI Studio](https://aistudio.google.com/apikey?utm%5Fsource=theaidrivenmarketer.beehiiv.com&utm%5Fmedium=referral&utm%5Fcampaign=youtube-shorts-automation-with-veo-3)
2. Click “Get API Key”
3. Create new API key
4. Copy and save securely

**Cost:** Pay-per-use (see [pricing](http://about:blank#api-costs))

### OpenAI API (GPT-4)

1. Go to [OpenAI Platform](https://platform.openai.com/api-keys?utm%5Fsource=theaidrivenmarketer.beehiiv.com&utm%5Fmedium=referral&utm%5Fcampaign=youtube-shorts-automation-with-veo-3)
2. Create new secret key
3. Copy immediately (shown only once)

**Cost:** \~$0.01-0.03 per video script

### ElevenLabs API

1. Go to [ElevenLabs](https://elevenlabs.io/?utm%5Fsource=theaidrivenmarketer.beehiiv.com&utm%5Fmedium=referral&utm%5Fcampaign=youtube-shorts-automation-with-veo-3)
2. Sign up and navigate to API settings
3. Generate API key

**Cost:** \~10,000 characters free/month, then pay-per-use

### Step 3: Set Up Cloudflare R2 Storage

1. **Create R2 Bucket:**
2. **Get API Credentials:**
3. **Configure Public URL:**

### Step 4: Configure FFmpeg (for audio-video merging)

**Linux/Mac:**

```
# Install FFmpeg
sudo apt-get install ffmpeg  # Ubuntu/Debian
brew install ffmpeg          # macOS

# Verify installation
ffmpeg -version

```

**Docker n8n:**

```
# Add to Dockerfile
RUN apk add --no-cache ffmpeg

```

**Note:** The workflow includes a code node that simulates merging. Replace with actual FFmpeg command in production.

### Step 5: Configure Gmail OAuth

1. **In n8n:**
  - Go to Credentials → Gmail OAuth2
  - Click “Create New Credential”
2. **Google Cloud Console:**
  - Create project
  - Enable Gmail API
  - Create OAuth 2.0 credentials
  - Add authorized redirect: `https://your-n8n.com/rest/oauth2-credential/callback`
3. **Connect in n8n:**
  - Enter Client ID + Secret
  - Click “Connect my account”
  - Authorize access

---

## 💻 Usage

### Method 1: Web Form (Recommended)

1. **Get Webhook URL:**
2. **Share with Team:**
  - Send URL to content creators
  - Embed in internal tools
  - Add to website
3. **Submit Video Idea:**
  - Fill out form
  - Click “Generate Video”
  - Wait 2-3 minutes
  - Receive email with download link

### Method 2: API Call

```
curl -X POST '<https://your-n8n.com/webhook/youtube-shorts>' \\
  -H 'Content-Type: application/json' \\
  -d '{
    "video_idea": "Top 5 productivity hacks for remote workers",
    "target_audience": "Millennials (25-40)",
    "video_style": "Energetic & Fast-paced",
    "duration": "30 seconds",
    "voice_type": "Young Energetic Female",
    "email": "creator@company.com"
  }'

```

### Method 3: Manual Execution (Testing)

1. Open workflow in n8n
2. Click “Execute Workflow”
3. Manually enter test data
4. Check execution log for results

---

## 💰 API Costs

### Estimated Cost Per Video:

| Service           | Cost             | Notes                            |
| ----------------- | ---------------- | -------------------------------- |
| **OpenAI GPT-4**  | $0.01-0.03       | Script generation (\~500 tokens) |
| **ElevenLabs**    | $0.01-0.02       | \~200 characters voiceover       |
| **Google Veo 3**  | $0.10-0.30       | 8-second 720p video              |
| **Cloudflare R2** | $0.00-0.01       | Storage + bandwidth              |
| **Total**         | **\~$0.12-0.36** | Per video                        |

### Monthly Estimates:

| Videos/Month | Estimated Cost |
| ------------ | -------------- |
| 50 videos    | $6-18          |
| 100 videos   | $12-36         |
| 500 videos   | $60-180        |

**Free Tiers:**

- **ElevenLabs:** 10,000 characters/month free
- **Cloudflare R2:** 10GB storage free
- **OpenAI:** $5 free credit (new accounts)

---

## 🔧 Troubleshooting

### Common Issues:

### 1\. “Veo 3 video generation failed”

**Cause:** API quota exceeded or invalid prompt

**Solution:**

```
# Check API quota
curl -H "x-goog-api-key: YOUR_KEY" \\
  <https://generativelanguage.googleapis.com/v1beta/models>

# Verify prompt length (max 1024 tokens)
# Simplify complex prompts

```

### 2\. “Voiceover generation timeout”

**Cause:** ElevenLabs API slow or quota exceeded

**Solution:**

```
# Check ElevenLabs quota
curl -H "xi-api-key: YOUR_KEY" \\
  <https://api.elevenlabs.io/v1/user>

# Reduce script length
# Increase timeout in node settings

```

### 3\. “Email not received”

**Cause:** Gmail OAuth expired or spam folder

**Solution:**

```
# Re-authenticate Gmail:
1. Go to Credentials in n8n
2. Delete old Gmail credential
3. Create new one
4. Re-authorize

# Check spam/junk folders
# Verify email address is correct

```

### 4\. “Video download fails”

**Cause:** Veo 3 URL expired (2-day limit)

**Solution:**

```
# Videos expire after 48 hours
# Download immediately after generation
# Consider increasing storage retention

```

### 5\. “Audio-video merge error”

**Cause:** FFmpeg not installed or incorrect path

**Solution:**

```
# Install FFmpeg
sudo apt-get install ffmpeg

# Verify installation
ffmpeg -version

# Update code node with correct FFmpeg path

```

---

## ⚙️ Advanced Configuration

### Custom Voice Mapping

Edit the `voiceover-generation` node to map custom voices:

```
// Voice ID mapping
const voiceMap = {
  "Professional Male": "21m00Tcm4TlvDq8ikWAM",
  "Professional Female": "EXAVITQu4vr4xnSDxMaL",
  "Young Energetic Male": "pNInz6obpgDQGcFmaJgB",
  "Young Energetic Female": "jBpfuIE2acCO8z3wKNLl",
  "Custom Voice 1": "YOUR_VOICE_ID_HERE"
};

const selectedVoice = voiceMap[$json.voice_type] || voiceMap["Professional Male"];

```

### Extend Video Duration

Veo 3 supports up to 8 seconds per generation. For longer videos:

1. Generate multiple 8-second clips
2. Use Veo 3’s extension feature
3. Stitch clips using FFmpeg

### Add Watermark/Logo

Update `merge-audio-video` node:

```
# FFmpeg command with watermark
ffmpeg -i video.mp4 -i logo.png -i audio.mp3 \\
  -filter_complex "[0:v][1:v]overlay=W-w-10:H-h-10" \\
  -c:a aac -map 2:a output.mp4

```

### Batch Processing

Enable batch mode to process multiple videos:

1. Replace form trigger with Google Sheets trigger
2. Read rows of video ideas
3. Loop through each row
4. Generate videos in parallel (max 3-5 concurrent)

---

# FULL JSON Workflow

```
{
  "name": "🎬 YouTube Shorts Automation with Veo 3",
  "nodes": [
    {
      "parameters": {
        "formTitle": "🎬 YouTube Shorts Video Generator",
        "formDescription": "Create professional YouTube Shorts videos with AI-powered script, voiceover, and Veo 3 video generation. Enter your video concept and let AI handle the rest!",
        "formFields": {
          "values": [
            {
              "fieldLabel": "Video Topic/Idea",
              "fieldType": "textarea",
              "placeholder": "e.g., 'Top 5 productivity hacks for remote workers' or 'How to make the perfect espresso at home'",
              "requiredField": true
            },
            {
              "fieldLabel": "Target Audience",
              "fieldType": "dropdown",
              "fieldOptions": {
                "values": [
                  {
                    "option": "Gen Z (18-24)"
                  },
                  {
                    "option": "Millennials (25-40)"
                  },
                  {
                    "option": "Gen X (41-56)"
                  },
                  {
                    "option": "Professionals"
                  },
                  {
                    "option": "Entrepreneurs"
                  },
                  {
                    "option": "Students"
                  },
                  {
                    "option": "Parents"
                  },
                  {
                    "option": "General Audience"
                  }
                ]
              },
              "requiredField": true
            },
            {
              "fieldLabel": "Video Style",
              "fieldType": "dropdown",
              "fieldOptions": {
                "values": [
                  {
                    "option": "Auto-detect (AI decides)"
                  },
                  {
                    "option": "Energetic & Fast-paced"
                  },
                  {
                    "option": "Professional & Clean"
                  },
                  {
                    "option": "Fun & Casual"
                  },
                  {
                    "option": "Educational & Informative"
                  },
                  {
                    "option": "Inspirational & Motivational"
                  },
                  {
                    "option": "Dramatic & Cinematic"
                  }
                ]
              }
            },
            {
              "fieldLabel": "Video Duration",
              "fieldType": "dropdown",
              "fieldOptions": {
                "values": [
                  {
                    "option": "8 seconds"
                  },
                  {
                    "option": "30 seconds"
                  },
                  {
                    "option": "45 seconds"
                  },
                  {
                    "option": "60 seconds"
                  }
                ]
              },
              "requiredField": true
            },
            {
              "fieldLabel": "Voiceover Voice Type",
              "fieldType": "dropdown",
              "fieldOptions": {
                "values": [
                  {
                    "option": "Professional Male"
                  },
                  {
                    "option": "Professional Female"
                  },
                  {
                    "option": "Young Energetic Male"
                  },
                  {
                    "option": "Young Energetic Female"
                  },
                  {
                    "option": "Warm & Friendly"
                  },
                  {
                    "option": "Deep & Authoritative"
                  }
                ]
              }
            },
            {
              "fieldLabel": "Email for Delivery",
              "fieldType": "email",
              "placeholder": "your@email.com",
              "requiredField": true
            }
          ]
        },
        "responseMode": "lastNode",
        "options": {}
      },
      "id": "form-trigger-node",
      "name": "🎯 Video Idea Input Form",
      "type": "n8n-nodes-base.formTrigger",
      "typeVersion": 2.3,
      "position": [
        -7152,
        928
      ]
    },
    {
      "parameters": {
        "jsCode": "// Parse the OpenAI response and extract script data\nconst response = items[0].json;\n\n// Handle different response formats (Standard Node vs API Raw)\nconst aiResponse = response.message?.content || response.choices?.[0]?.message?.content || response.content;\n\nif (!aiResponse) {\n  throw new Error(`Could not find content in OpenAI response. Received: ${JSON.stringify(response)}`);\n}\n\nlet scriptData;\ntry {\n  // Try to parse JSON from the response\n  const jsonMatch = aiResponse.match(/```(?:json)?\\s*([\\s\\S]*?)\\s*```/);\n  if (jsonMatch) {\n    scriptData = JSON.parse(jsonMatch[1]);\n  } else {\n    scriptData = JSON.parse(aiResponse);\n  }\n} catch (e) {\n  console.error('Failed to parse script data:', e);\n  // Fallback structure\n  scriptData = {\n    script: {\n      hook: 'Amazing discovery ahead!',\n      main_content: 'This is the most important thing you need to know.',\n      cta: 'Follow for more tips!',\n      full_script: 'Amazing discovery ahead! This is the most important thing you need to know. Follow for more tips!'\n    },\n    timing: {\n      hook_duration: 3,\n      main_duration: 24,\n      cta_duration: 3,\n      total_estimated: 30\n    },\n    visual_direction: {\n      style: 'realistic',\n      energy_level: 'high',\n      color_palette: 'vibrant',\n      camera_movement: 'dynamic'\n    },\n    veo3_scene_prompt: 'Dynamic scene with engaging visuals',\n    seo_keywords: ['viral', 'trending', 'must-watch'],\n    title_suggestion: 'You Won\\'t Believe This!',\n    description_suggestion: 'Amazing content you need to see!'\n  };\n}\n\n// Merge with original form data\nconst formData = $('🎯 Video Idea Input Form').item.json;\n\nreturn [{\n  json: {\n    ...formData,\n    ...scriptData,\n    processing_id: `yt-shorts-${Date.now()}`,\n    created_at: new Date().toISOString()\n  }\n}];"
      },
      "id": "parse-script-node",
      "name": "Parse Script Data",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -6704,
        928
      ]
    },
    {
      "parameters": {
        "jsCode": "// Store the audio file data and pass through all context\nconst audioData = items[0].binary;\nconst contextData = $('Parse Script Data').item.json;\n\n// Get audio duration (approximate from file size)\nconst audioBuffer = audioData.data;\nconst estimatedDuration = Math.min(Math.ceil(audioBuffer.byteLength / 44100 / 2), 60);\n\nreturn [{\n  json: {\n    ...contextData,\n    audio_file: {\n      data: audioBuffer.toString('base64'),\n      mimeType: 'audio/mpeg',\n      fileName: `voiceover_${contextData.processing_id}.mp3`,\n      estimated_duration: estimatedDuration\n    },\n    audio_ready: true,\n    audio_duration_seconds: estimatedDuration\n  },\n  binary: audioData\n}];"
      },
      "id": "store-audio-node",
      "name": "Store Audio File",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -6256,
        928
      ]
    },
    {
      "parameters": {
        "jsCode": "const response = items[0].json;\n\n// ✅ Handle ALL n8n OpenAI response formats\nconst enhancedPrompt =\n  response.output_text ||\n  response.message?.content ||\n  response.choices?.[0]?.message?.content ||\n  response.content ||\n  '';\n\nif (!enhancedPrompt || typeof enhancedPrompt !== 'string') {\n  throw new Error(\n    `Enhanced Veo prompt missing. Received: ${JSON.stringify(response)}`\n  );\n}\n\nconst contextData = $('Store Audio File').item.json;\n\nreturn [\n  {\n    json: {\n      ...contextData,\n      veo3_enhanced_prompt: enhancedPrompt.trim(),\n      veo3_ready: true,\n    },\n  },\n];"
      },
      "id": "extract-prompt-node",
      "name": "Extract Enhanced Prompt",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -5808,
        928
      ]
    },
    {
      "parameters": {
        "jsCode": "// Video comes directly from Veo node\nconst videoBinary = items[0].binary;\n\n// Pull audio + metadata from Store Audio File (still exists)\nconst contextData = $('Store Audio File').item.json;\nconst audioBinary = $('Store Audio File').item.binary;\n\n// Simulated merged metadata\nconst mergedVideo = {\n  filename: `youtube_short_${contextData.processing_id}.mp4`,\n  mimeType: 'video/mp4',\n  duration: contextData.audio_duration_seconds,\n  resolution: '720p',\n  aspect_ratio: '9:16',\n  has_audio: true,\n};\n\nreturn [\n  {\n    json: {\n      ...contextData,\n      merged_video: mergedVideo,\n      merge_status: 'completed',\n      final_video_ready: true,\n    },\n    binary: {\n      video: videoBinary.data,\n      audio: audioBinary.data,\n    },\n  },\n];"
      },
      "id": "merge-audio-video-node",
      "name": "🎞️ Merge Audio + Video",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -5152,
        928
      ]
    },
    {
      "parameters": {
        "jsCode": "const contextData = items[0].json;\n\n// Resolve filename safely\nconst filename =\n  contextData.merged_video?.filename ||\n  `youtube_short_${contextData.processing_id}.mp4`;\n\n// ⚠️ REPLACE WITH YOUR CLOUDFLARE R2 PUBLIC URL\nconst baseUrl = 'https://YOUR-R2-PUBLIC-URL.r2.dev';\n\n// Build URL\nconst shareableUrl = `${baseUrl}/${filename}`;\n\n// Expiry (7 days)\nconst expiryDate = new Date();\nexpiryDate.setDate(expiryDate.getDate() + 7);\n\nreturn [\n  {\n    json: {\n      ...contextData,\n      shareable_url: shareableUrl,\n      download_url: shareableUrl,\n      url_expires_at: expiryDate.toISOString(),\n      share_ready: true,\n    },\n  },\n];"
      },
      "id": "generate-link-node",
      "name": "🔗 Generate Shareable Link",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -4256,
        928
      ]
    },
    {
      "parameters": {
        "jsCode": "// Generate beautiful HTML email with video details\nconst data = items[0].json;\n\n// ---- SAFETY NORMALIZATION ----\nconst visualDirection = data.visual_direction || {\n  style: 'Auto',\n  energy_level: 'Auto',\n};\n\nconst script = data.script || {\n  hook: '—',\n  main_content: '—',\n  cta: '—',\n};\n\nconst seoKeywords = Array.isArray(data.seo_keywords)\n  ? data.seo_keywords\n  : [];\n\nconst html = `\n<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"UTF-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n  <style>\n    body {\n      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n      line-height: 1.6;\n      color: #333;\n      max-width: 600px;\n      margin: 0 auto;\n      padding: 20px;\n      background-color: #f5f5f5;\n    }\n    .container {\n      background-color: white;\n      border-radius: 12px;\n      padding: 40px;\n      box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n    }\n    .header {\n      text-align: center;\n      border-bottom: 4px solid #FF0000;\n      padding-bottom: 20px;\n      margin-bottom: 30px;\n    }\n    h1 {\n      color: #FF0000;\n      margin: 0;\n      font-size: 32px;\n    }\n    .emoji {\n      font-size: 48px;\n      margin-bottom: 10px;\n    }\n    .video-preview {\n      background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n      border-radius: 8px;\n      padding: 30px;\n      text-align: center;\n      margin: 30px 0;\n      color: white;\n    }\n    .download-btn {\n      display: inline-block;\n      background: #FF0000;\n      color: white;\n      padding: 16px 32px;\n      text-decoration: none;\n      border-radius: 8px;\n      font-weight: bold;\n      font-size: 18px;\n      margin: 20px 0;\n      transition: background 0.3s ease;\n    }\n    .download-btn:hover {\n      background: #CC0000;\n    }\n    .details {\n      background: #f8f9fa;\n      border-radius: 8px;\n      padding: 20px;\n      margin: 20px 0;\n    }\n    .detail-row {\n      display: flex;\n      justify-content: space-between;\n      padding: 10px 0;\n      border-bottom: 1px solid #e9ecef;\n    }\n    .detail-row:last-child {\n      border-bottom: none;\n    }\n    .label {\n      font-weight: 600;\n      color: #495057;\n    }\n    .value {\n      color: #212529;\n    }\n    .script-box {\n      background: #fff3cd;\n      border-left: 4px solid #ffc107;\n      padding: 15px;\n      margin: 20px 0;\n      border-radius: 4px;\n    }\n    .tips {\n      background: #d1ecf1;\n      border-left: 4px solid #0c5460;\n      padding: 15px;\n      margin: 20px 0;\n      border-radius: 4px;\n    }\n    .footer {\n      text-align: center;\n      margin-top: 30px;\n      padding-top: 20px;\n      border-top: 1px solid #dee2e6;\n      font-size: 12px;\n      color: #6c757d;\n    }\n    .keywords {\n      display: flex;\n      flex-wrap: wrap;\n      gap: 8px;\n      margin: 10px 0;\n    }\n    .keyword-tag {\n      background: #e7f3ff;\n      color: #0066cc;\n      padding: 4px 12px;\n      border-radius: 12px;\n      font-size: 12px;\n      font-weight: 500;\n    }\n  </style>\n</head>\n<body>\n  <div class=\"container\">\n    <div class=\"header\">\n      <div class=\"emoji\">🎬</div>\n      <h1>Your YouTube Short is Ready!</h1>\n      <p style=\"margin: 10px 0 0 0; color: #6c757d;\">Generated with AI-powered Veo 3 technology</p>\n    </div>\n\n    <div class=\"video-preview\">\n      <h2 style=\"margin-top: 0;\">✨ ${data.title_suggestion}</h2>\n      <p style=\"font-size: 14px; opacity: 0.9;\">Duration: ${data.audio_duration_seconds}s | Resolution: 720p | Format: 9:16 (Vertical)</p>\n    </div>\n\n    <div style=\"text-align: center;\">\n      <a href=\"${data.download_url}\" class=\"download-btn\">📥 Download Your Video</a>\n      <p style=\"font-size: 12px; color: #6c757d;\">Link expires: ${new Date(data.url_expires_at).toLocaleDateString()}</p>\n    </div>\n\n    <div class=\"details\">\n      <h3 style=\"margin-top: 0; color: #212529;\">📊 Video Details</h3>\n      <div class=\"detail-row\">\n        <span class=\"label\">Processing ID:</span>\n        <span class=\"value\">${data.processing_id}</span>\n      </div>\n      <div class=\"detail-row\">\n        <span class=\"label\">Target Audience:</span>\n        <span class=\"value\">${data.target_audience}</span>\n      </div>\n      <div class=\"detail-row\">\n        <span class=\"label\">Video Style:</span>\n        <span class=\"value\">${visualDirection.style}</span>\n      </div>\n      <div class=\"detail-row\">\n        <span class=\"label\">Energy Level:</span>\n        <span class=\"value\">${visualDirection.energy_level}</span>\n      </div>\n      <div class=\"detail-row\">\n        <span class=\"label\">Generated:</span>\n        <span class=\"value\">${new Date(data.completion_time).toLocaleString()}</span>\n      </div>\n    </div>\n\n    <div class=\"script-box\">\n      <h3 style=\"margin-top: 0;\">📝 Video Script</h3>\n      <p><strong>Hook:</strong> ${script.hook}</p>\n      <p><strong>Main Content:</strong> ${script.main_content}</p>\n      <p><strong>Call-to-Action:</strong> ${script.cta}</p>\n    </div>\n\n    <div class=\"details\">\n      <h3 style=\"margin-top: 0;\">🎯 SEO Keywords</h3>\n      <div class=\"keywords\">\n        ${seoKeywords.map(kw => `<span class=\"keyword-tag\">#${kw}</span>`).join('')}\n      </div>\n    </div>\n\n    <div class=\"details\">\n      <h3 style=\"margin-top: 0;\">📱 Suggested YouTube Details</h3>\n      <p><strong>Title:</strong> ${data.title_suggestion}</p>\n      <p><strong>Description:</strong></p>\n      <p style=\"white-space: pre-wrap;\">${data.description_suggestion}</p>\n    </div>\n\n    <div class=\"tips\">\n      <h3 style=\"margin-top: 0;\">💡 Publishing Tips</h3>\n      <ul style=\"margin: 10px 0; padding-left: 20px;\">\n        <li>Upload during peak hours (6-9 PM your timezone)</li>\n        <li>Use all suggested SEO keywords in your description</li>\n        <li>Create an eye-catching thumbnail</li>\n        <li>Pin a comment asking viewers to subscribe</li>\n        <li>Share on Instagram Reels and TikTok for cross-platform reach</li>\n        <li>Respond to comments in the first hour to boost engagement</li>\n      </ul>\n    </div>\n\n    <div class=\"footer\">\n      <p><strong>🤖 Powered by AI</strong></p>\n      <p>Script: OpenAI GPT-4 | Video: Google Veo 3.1 | Voiceover: ElevenLabs</p>\n      <p style=\"margin-top: 15px;\">Questions? Reply to this email for support.</p>\n    </div>\n  </div>\n</body>\n</html>\n`;\n\nreturn [{\n  json: {\n    ...data,\n    email_html: html,\n    email_subject: `🎬 Your YouTube Short is Ready: \"${data.title_suggestion}\"`,\n    email_ready: true\n  }\n}];"
      },
      "id": "format-email-node",
      "name": "📧 Format Email Report",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -4032,
        928
      ]
    },
    {
      "parameters": {
        "sendTo": "={{ $('🎯 Video Idea Input Form').item.json['Email for Delivery'] }}",
        "subject": "={{ $json.email_subject }}",
        "message": "={{ $json.email_html }}",
        "options": {}
      },
      "id": "send-email-node",
      "name": "📧 Send Email Notification",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        -3808,
        928
      ],
      "credentials": {
        "gmailOAuth2": {
          "id": "YOUR_GMAIL_CREDENTIAL_ID",
          "name": "Gmail account"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// Log successful completion\nconst data = items[0].json;\n\nconsole.log('✅ YouTube Short generation completed successfully!');\nconsole.log('Processing ID:', data.processing_id);\nconsole.log('Video URL:', data.download_url);\nconsole.log('Duration:', data.audio_duration_seconds + 's');\nconsole.log('Sent to:', data.email);\n\nreturn [{\n  json: {\n    status: 'success',\n    processing_id: data.processing_id,\n    video_url: data.download_url,\n    email_sent_to: data.email,\n    completion_time: new Date().toISOString(),\n    total_processing_time: Math.round((new Date(data.completion_time) - new Date(data.created_at)) / 1000) + 's'\n  }\n}];"
      },
      "id": "log-success-node",
      "name": "✅ Log Success",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -3584,
        928
      ]
    },
    {
      "parameters": {
        "resource": "chat",
        "model": "gpt-4o-mini",
        "prompt": {
          "messages": [
            {
              "role": "system",
              "content": "You are an expert at writing prompts for Google's Veo 3 video generation model. Create detailed, cinematic prompts that specify subject, action, camera movement, composition, lighting, mood, and style. Reference the Veo 3 best practices: be descriptive, specify camera angles, include lighting details, and describe motion clearly."
            },
            {
              "role": "user",
              "content": "Create an optimized Veo 3.1 prompt for this YouTube Short:\n\n**Original Prompt:** {{ $json.veo3_scene_prompt }}\n**Script Content:** {{ $json.script.full_script }}\n**Visual Style:** {{ $json.visual_direction.style }}\n**Energy Level:** {{ $json.visual_direction.energy_level }}\n\nCreate a steady-paced but clear {{ $('🎯 Video Idea Input Form').item.json['Video Duration'] }} YouTube Short.\nVisual pacing should naturally follow the spoken narration.\n\n**Target Audience:** {{ $json['Target Audience'] }}\n\nCreate a detailed Veo 3.1 prompt that:\n1. Match the pacing and scene transitions to the spoken script content,\nensuring visuals naturally align with the narration flow.\n2. Uses appropriate visual style ({{ $json.visual_direction.style }})\n3. Specifies camera movement and composition\n4. Includes lighting and mood details\n5. Works in 9:16 vertical format (YouTube Shorts)\n6. Is optimized for the target audience\n\nReturn ONLY the optimized prompt text, no JSON, no extra commentary. Make it detailed and cinematic.\n\nIMPORTANT TIMING REQUIREMENT:\nThis video MUST run for approximately {{ $('🎯 Video Idea Input Form').item.json['Video Duration'] }}.\nDo NOT compress or summarize the narration.\nDo NOT shorten scenes to fit a shorter runtime.\nEach sentence should be given sufficient on-screen time.\nVisual pacing rules:\n- Each sentence should have its own visual beat\n- Maintain steady pacing throughout\n- Do not montage multiple ideas into one shot\n- Scene transitions should align with narration pauses\nEnd the video only after the narration fully completes."
            }
          ]
        },
        "options": {
          "maxTokens": 500,
          "temperature": 0.4
        },
        "requestOptions": {}
      },
      "type": "n8n-nodes-base.openAi",
      "typeVersion": 1,
      "position": [
        -6032,
        928
      ],
      "id": "enhance-prompt-node",
      "name": "🎨 Enhance Veo 3 Prompt",
      "credentials": {
        "openAiApi": {
          "id": "YOUR_OPENAI_CREDENTIAL_ID",
          "name": "OpenAi account"
        }
      }
    },
    {
      "parameters": {
        "resource": "video",
        "modelId": {
          "__rl": true,
          "value": "models/veo-3.1-generate-preview",
          "mode": "list",
          "cachedResultName": "models/veo-3.1-generate-preview"
        },
        "prompt": "={{ $json.veo3_enhanced_prompt }}",
        "options": {
          "durationSeconds": 8,
          "aspectRatio": "9:16",
          "personGeneration": "allow_all"
        }
      },
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "typeVersion": 1,
      "position": [
        -5376,
        928
      ],
      "id": "veo-generation-node",
      "name": "🎬 Veo 3.1 Video Generation",
      "credentials": {
        "googlePalmApi": {
          "id": "YOUR_GOOGLE_GEMINI_CREDENTIAL_ID",
          "name": "Google Gemini(PaLM) Api account"
        }
      }
    },
    {
      "parameters": {
        "resource": "chat",
        "model": "gpt-4o",
        "prompt": {
          "messages": [
            {
              "role": "system",
              "content": "You are an expert YouTube Shorts scriptwriter specializing in viral, engaging short-form content. Create scripts that hook viewers in the first 3 seconds, maintain engagement throughout, and end with a strong call-to-action. Scripts should be optimized for voiceover timing and visual pacing."
            },
            {
              "role": "user",
              "content": "Create a YouTube Shorts script for this concept:\n\n**Topic:** {{ $json['Video Topic/Idea'] }}\n**Target Audience:** {{ $json['Target Audience'] }}\n**Duration:** {{ $json['Video Duration'] }}\n**Style:** {{ $json.video_style || 'Auto-detect based on topic' }}\n\nGenerate a script with:\n1. HOOK (0-3 seconds): Attention-grabbing opening\n2. Aim for approximately 120–140 spoken words.\nMAIN CONTENT: Key points with precise timing\n3. CALL-TO-ACTION: Strong ending\n\nAlso provide:\n- Scene descriptions for video generation\n- Recommended pacing and energy level\n- Visual style recommendations (realistic, animated, cinematic, etc.)\n- Keywords for SEO\n\nFormat as JSON:\n```json\n{\n  \"script\": {\n    \"hook\": \"Opening line that grabs attention\",\n    \"main_content\": \"Main script content with natural pauses\",\n    \"cta\": \"Call to action line\",\n    \"full_script\": \"Complete script for voiceover\"\n  },\n  \"timing\": {\n    \"hook_duration\": 3,\n    \"main_duration\": 24,\n    \"cta_duration\": 3,\n    \"total_estimated\": 30\n  },\n  \"visual_direction\": {\n    \"style\": \"cinematic|realistic|animated|mixed\",\n    \"energy_level\": \"high|medium|calm\",\n    \"color_palette\": \"vibrant|muted|dramatic|natural\",\n    \"camera_movement\": \"dynamic|steady|slow-motion\"\n  },\n  \"veo3_scene_prompt\": \"Detailed prompt for Veo 3 video generation that describes the visual scene, camera angles, lighting, mood, and action\",\n  \"seo_keywords\": [\"keyword1\", \"keyword2\", \"keyword3\"],\n  \"title_suggestion\": \"Catchy video title\",\n  \"description_suggestion\": \"Video description for YouTube\"\n}\n```"
            }
          ]
        },
        "options": {
          "maxTokens": 2000,
          "temperature": 0.7
        },
        "requestOptions": {}
      },
      "type": "n8n-nodes-base.openAi",
      "typeVersion": 1,
      "position": [
        -6928,
        928
      ],
      "id": "script-generation-node",
      "name": "📝 AI Script Generation",
      "credentials": {
        "openAiApi": {
          "id": "YOUR_OPENAI_CREDENTIAL_ID",
          "name": "OpenAi account"
        }
      }
    },
    {
      "parameters": {
        "resource": "speech",
        "voice": {
          "__rl": true,
          "value": "CwhRBWXzGAHq8TQ4Fs17",
          "mode": "list",
          "cachedResultName": "Roger - Laid-Back, Casual, Resonant"
        },
        "text": "={{ $json.script.full_script }}",
        "additionalOptions": {
          "voiceSettings": "{\n            \"stability\": 0.5,\n            \"similarity_boost\": 0.75,\n            \"style\": 0.5,\n            \"use_speaker_boost\": true\n          }"
        },
        "requestOptions": {}
      },
      "type": "@elevenlabs/n8n-nodes-elevenlabs.elevenLabs",
      "typeVersion": 1,
      "position": [
        -6480,
        928
      ],
      "id": "voiceover-generation-node",
      "name": "🎤 ElevenLabs Voiceover",
      "credentials": {
        "elevenLabsApi": {
          "id": "YOUR_ELEVENLABS_CREDENTIAL_ID",
          "name": "ElevenLabs account"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// Freeze merged context so it survives upload\nreturn [\n  {\n    json: items[0].json,\n    binary: items[0].binary,\n  },\n];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -4928,
        928
      ],
      "id": "prepare-upload-node",
      "name": "Prepare Upload Context"
    },
    {
      "parameters": {
        "operation": "upload",
        "bucketName": "youtube-shorts",
        "fileName": "={{ $json.merged_video.filename }}",
        "binaryPropertyName": "video",
        "additionalFields": {}
      },
      "type": "n8n-nodes-base.s3",
      "typeVersion": 1,
      "position": [
        -4704,
        1024
      ],
      "id": "upload-file-node",
      "name": "Upload a file",
      "credentials": {
        "s3": {
          "id": "YOUR_S3_CREDENTIAL_ID",
          "name": "S3 account"
        }
      }
    },
    {
      "parameters": {
        "mode": "combine",
        "combineBy": "combineByPosition",
        "options": {}
      },
      "type": "n8n-nodes-base.merge",
      "typeVersion": 3.2,
      "position": [
        -4480,
        928
      ],
      "id": "merge-node",
      "name": "Merge"
    },
    {
      "parameters": {
        "jsCode": "return [{\n  json: {\n    ...items[0].json,\n    images: []\n  }\n}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -5600,
        928
      ],
      "id": "cleanup-node",
      "name": "Code in JavaScript"
    }
  ],
  "pinData": {},
  "connections": {
    "🎯 Video Idea Input Form": {
      "main": [
        [
          {
            "node": "📝 AI Script Generation",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Script Data": {
      "main": [
        [
          {
            "node": "🎤 ElevenLabs Voiceover",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Store Audio File": {
      "main": [
        [
          {
            "node": "🎨 Enhance Veo 3 Prompt",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "🎨 Enhance Veo 3 Prompt": {
      "main": [
        [
          {
            "node": "Extract Enhanced Prompt",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Enhanced Prompt": {
      "main": [
        [
          {
            "node": "Code in JavaScript",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "🎬 Veo 3.1 Video Generation": {
      "main": [
        [
          {
            "node": "🎞️ Merge Audio + Video",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "🎞️ Merge Audio + Video": {
      "main": [
        [
          {
            "node": "Prepare Upload Context",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "🔗 Generate Shareable Link": {
      "main": [
        [
          {
            "node": "📧 Format Email Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "📧 Send Email Notification": {
      "main": [
        [
          {
            "node": "✅ Log Success",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "📧 Format Email Report": {
      "main": [
        [
          {
            "node": "📧 Send Email Notification",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "📝 AI Script Generation": {
      "main": [
        [
          {
            "node": "Parse Script Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "🎤 ElevenLabs Voiceover": {
      "main": [
        [
          {
            "node": "Store Audio File",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Upload Context": {
      "main": [
        [
          {
            "node": "Upload a file",
            "type": "main",
            "index": 0
          },
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upload a file": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Merge": {
      "main": [
        [
          {
            "node": "🔗 Generate Shareable Link",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code in JavaScript": {
      "main": [
        [
          {
            "node": "🎬 Veo 3.1 Video Generation",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "meta": {
    "templateCredsSetupCompleted": false
  },
  "tags": [
    {
      "name": "YouTube Automation"
    },
    {
      "name": "AI Content Creation"
    },
    {
      "name": "Veo 3 Video Generation"
    }
  ]
}
```

---

## 🎓 FAQ

**Q: Can I use this for commercial purposes?**

A: Yes, but check each API’s terms of service. OpenAI and ElevenLabs allow commercial use. Ensure you have rights to any content you generate.

**Q: How long does video generation take?**

A: Typically 2-3 minutes total:

- Script generation: 10-20 seconds
- Voiceover: 5-10 seconds
- Veo 3 video: 60-120 seconds
- Processing: 10-20 seconds

**Q: Can I customize the video style?**

A: Yes! Edit the `veo3-prompt-enhancement` node to adjust:

- Camera angles
- Lighting
- Color grading
- Visual effects

**Q: What happens if video generation fails?**

A: The workflow includes error handling:

- Retries up to 3 times
- Logs detailed error messages
- Sends notification email
- Stores partial results for debugging

**Q: Can I integrate with YouTube API for direct upload?**

A: Absolutely! Add a YouTube upload node after video generation. See [n8n YouTube documentation](https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.youtube/?utm%5Fsource=theaidrivenmarketer.beehiiv.com&utm%5Fmedium=referral&utm%5Fcampaign=youtube-shorts-automation-with-veo-3).

**Q: How do I reduce API costs?**

A: Several strategies:

- Use GPT-3.5 instead of GPT-4 for scripts
- Cache common prompts
- Implement rate limiting
- Use free tier limits first
- Process in batches during off-peak hours

**Q: Can I use different video models?**

A: Yes! The workflow can be adapted for:

- Runway Gen-2/3
- Stability AI Video
- Pika Labs
- Other video generation APIs

Just replace the Veo 3 nodes with the appropriate API calls.

---

## 📞 Support

### Getting Help:

1. **Check Logs:**
2. **Community Support:**
  - [n8n Community Forum](https://community.n8n.io/?utm%5Fsource=theaidrivenmarketer.beehiiv.com&utm%5Fmedium=referral&utm%5Fcampaign=youtube-shorts-automation-with-veo-3)
  - [n8n Discord](https://discord.gg/n8n?utm%5Fsource=theaidrivenmarketer.beehiiv.com&utm%5Fmedium=referral&utm%5Fcampaign=youtube-shorts-automation-with-veo-3)

---

## 📄 License

This workflow is provided as-is for educational and commercial use. Individual API services have their own terms of service.

---

## 🙏 Credits

**Built with:**

- [n8n](https://n8n.io/?utm%5Fsource=theaidrivenmarketer.beehiiv.com&utm%5Fmedium=referral&utm%5Fcampaign=youtube-shorts-automation-with-veo-3) \- Workflow automation
- [Google Veo 3](https://deepmind.google/technologies/veo/?utm%5Fsource=theaidrivenmarketer.beehiiv.com&utm%5Fmedium=referral&utm%5Fcampaign=youtube-shorts-automation-with-veo-3) \- Video generation
- [OpenAI](https://openai.com/?utm%5Fsource=theaidrivenmarketer.beehiiv.com&utm%5Fmedium=referral&utm%5Fcampaign=youtube-shorts-automation-with-veo-3) \- Script generation
- [ElevenLabs](https://elevenlabs.io/?utm%5Fsource=theaidrivenmarketer.beehiiv.com&utm%5Fmedium=referral&utm%5Fcampaign=youtube-shorts-automation-with-veo-3) \- Voice synthesis
- [Cloudflare R2](https://cloudflare.com/r2?utm%5Fsource=theaidrivenmarketer.beehiiv.com&utm%5Fmedium=referral&utm%5Fcampaign=youtube-shorts-automation-with-veo-3) \- Video storage

---

**Made with ❤️ for content creators worldwide** 🎬