AutomationFlowsAI & RAG › Create AI Videos From Prompts with Openai Script, Tts & Pexels B-roll Assembly

Create AI Videos From Prompts with Openai Script, Tts & Pexels B-roll Assembly

ByOneclick AI Squad @oneclick-ai on n8n.io

Automatically creates complete videos from a text prompt—script, voiceover, stock footage, and subtitles all assembled and ready.

Webhook trigger★★★★☆ complexityAI-powered18 nodesOpenAIHTTP RequestExecute CommandGoogle Drive
AI & RAG Trigger: Webhook Nodes: 18 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow corresponds to n8n.io template #10502 — we link there as the canonical source.

This workflow follows the Executecommand → HTTP Request recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "id": "NpOU5BmtmxwWbSzM",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Prompt-Based AI Video Creation with Auto Script, Voiceover & B-Roll Assembly",
  "tags": [],
  "nodes": [
    {
      "id": "cab91705-8229-4fa0-adc8-3fae3e7941d0",
      "name": "Generate Video Script",
      "type": "n8n-nodes-base.openAi",
      "position": [
        704,
        144
      ],
      "parameters": {
        "model": "=gpt-3.5-turbo-instruct",
        "options": {},
        "requestOptions": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "cabbc4d2-3240-4698-90a2-6b5588820a21",
      "name": "Parse Script into Scenes",
      "type": "n8n-nodes-base.code",
      "position": [
        928,
        144
      ],
      "parameters": {
        "jsCode": "const script = $input.first().json.choices[0].message.content;\n\n// Parse script into scenes\nconst scenes = [];\nconst lines = script.split('\\n').filter(line => line.trim());\n\nlet currentScene = {\n  number: 1,\n  voiceover: '',\n  visuals: '',\n  duration: 5\n};\n\nfor (const line of lines) {\n  if (line.match(/^Scene \\d+:/i) || line.match(/^\\[Scene \\d+\\]/i)) {\n    if (currentScene.voiceover) {\n      scenes.push({...currentScene});\n      currentScene = {\n        number: scenes.length + 1,\n        voiceover: '',\n        visuals: '',\n        duration: 5\n      };\n    }\n  } else if (line.match(/^Voiceover:/i) || line.match(/^VO:/i)) {\n    currentScene.voiceover += line.replace(/^(Voiceover:|VO:)/i, '').trim() + ' ';\n  } else if (line.match(/^Visual:/i) || line.match(/^Visuals:/i)) {\n    currentScene.visuals = line.replace(/^(Visual:|Visuals:)/i, '').trim();\n  } else if (currentScene.voiceover === '') {\n    currentScene.voiceover += line.trim() + ' ';\n  }\n}\n\nif (currentScene.voiceover) {\n  scenes.push(currentScene);\n}\n\n// If no structured scenes found, create single scene\nif (scenes.length === 0) {\n  scenes.push({\n    number: 1,\n    voiceover: script,\n    visuals: $input.first().json.prompt || 'relevant stock footage',\n    duration: 10\n  });\n}\n\nreturn scenes.map(scene => ({\n  json: {\n    sceneNumber: scene.number,\n    voiceoverText: scene.voiceover.trim(),\n    visualDescription: scene.visuals || 'stock footage',\n    estimatedDuration: scene.duration,\n    fullScript: script\n  }\n}));"
      },
      "typeVersion": 2
    },
    {
      "id": "42c325b8-a14b-4d37-924a-df40a60b829f",
      "name": "Generate Voiceover (TTS)",
      "type": "n8n-nodes-base.openAi",
      "position": [
        1600,
        48
      ],
      "parameters": {
        "model": "=tts-1-hd",
        "options": {},
        "requestOptions": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "0848f454-0590-4bb6-b3f6-d9adaea778e4",
      "name": "Search Stock Footage (Pexels)",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1152,
        240
      ],
      "parameters": {
        "url": "https://api.pexels.com/videos/search",
        "options": {},
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "query",
              "value": "={{ $json.visualDescription }}"
            },
            {
              "name": "per_page",
              "value": "3"
            },
            {
              "name": "size",
              "value": "medium"
            }
          ]
        }
      },
      "typeVersion": 4.1
    },
    {
      "id": "453117f8-5a08-4693-90db-ed076639dbce",
      "name": "Extract Video URLs",
      "type": "n8n-nodes-base.code",
      "position": [
        1376,
        240
      ],
      "parameters": {
        "jsCode": "const items = $input.all();\nconst result = [];\n\nfor (let i = 0; i < items.length; i++) {\n  const item = items[i].json;\n  \n  // Get the first available video file\n  let videoUrl = '';\n  if (item.videos && item.videos.length > 0) {\n    const video = item.videos[0];\n    if (video.video_files && video.video_files.length > 0) {\n      // Find HD quality video\n      const hdVideo = video.video_files.find(vf => vf.quality === 'hd') || video.video_files[0];\n      videoUrl = hdVideo.link;\n    }\n  }\n  \n  result.push({\n    json: {\n      sceneNumber: item.sceneNumber,\n      videoUrl: videoUrl,\n      videoId: item.videos?.[0]?.id || i,\n      duration: item.videos?.[0]?.duration || 5\n    }\n  });\n}\n\nreturn result;"
      },
      "typeVersion": 2
    },
    {
      "id": "52d7df36-7169-4a22-83f8-88c927c3d9b2",
      "name": "Download B-Roll Footage",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1600,
        240
      ],
      "parameters": {
        "url": "={{ $json.videoUrl }}",
        "options": {
          "response": {
            "response": {
              "responseFormat": "file"
            }
          }
        }
      },
      "typeVersion": 4.1
    },
    {
      "id": "b0c2f48b-1f5e-46bc-8c16-5d44a9cb047a",
      "name": "Merge Audio & Video",
      "type": "n8n-nodes-base.merge",
      "position": [
        1824,
        144
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "mergeByFields": {
          "values": [
            {
              "field1": "sceneNumber",
              "field2": "sceneNumber"
            }
          ]
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "51b579ee-a26a-4a5c-8924-0d87d2bb6014",
      "name": "Generate Subtitles (SRT)",
      "type": "n8n-nodes-base.code",
      "position": [
        2048,
        144
      ],
      "parameters": {
        "jsCode": "// Generate SRT subtitle format\nconst items = $input.all();\nlet srtContent = '';\nlet startTime = 0;\n\nfor (let i = 0; i < items.length; i++) {\n  const scene = items[i].json;\n  const text = scene.voiceoverText || '';\n  \n  // Estimate duration based on text length (average speaking rate: 150 words/min)\n  const words = text.split(' ').length;\n  const duration = Math.max(3, Math.ceil((words / 150) * 60));\n  \n  const endTime = startTime + duration;\n  \n  // Format timestamps for SRT\n  const formatTime = (seconds) => {\n    const hrs = Math.floor(seconds / 3600);\n    const mins = Math.floor((seconds % 3600) / 60);\n    const secs = Math.floor(seconds % 60);\n    const ms = Math.floor((seconds % 1) * 1000);\n    return `${String(hrs).padStart(2, '0')}:${String(mins).padStart(2, '0')}:${String(secs).padStart(2, '0')},${String(ms).padStart(3, '0')}`;\n  };\n  \n  srtContent += `${i + 1}\\n`;\n  srtContent += `${formatTime(startTime)} --> ${formatTime(endTime)}\\n`;\n  srtContent += `${text}\\n\\n`;\n  \n  startTime = endTime;\n}\n\nreturn [{\n  json: {\n    srtContent: srtContent,\n    totalDuration: startTime\n  },\n  binary: {\n    subtitles: {\n      data: Buffer.from(srtContent).toString('base64'),\n      mimeType: 'text/plain',\n      fileName: 'subtitles.srt'\n    }\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "7e8e2e9b-8a69-4350-b656-5d2f88b85853",
      "name": "Assemble Final Video",
      "type": "n8n-nodes-base.executeCommand",
      "position": [
        2272,
        144
      ],
      "parameters": {
        "command": "# This is a placeholder for FFmpeg video assembly\n# In production, you would use FFmpeg or a video editing API\n\n# Example FFmpeg command structure:\n# ffmpeg -i voiceover.mp3 -i video1.mp4 -i video2.mp4 \\\n#   -filter_complex \"[0:a]volume=1.0[a];[1:v][2:v]concat=n=2:v=1:a=0[v]\" \\\n#   -map \"[v]\" -map \"[a]\" -c:v libx264 -c:a aac output.mp4\n\necho \"Video assembly requires FFmpeg installation\"\necho \"Total scenes: $(ls *.mp4 2>/dev/null | wc -l)\"\necho \"Voiceover files: $(ls *.mp3 2>/dev/null | wc -l)\"\necho \"Subtitle file: $(ls *.srt 2>/dev/null)\""
      },
      "typeVersion": 1
    },
    {
      "id": "be8985a5-f16f-4fec-8053-844d13fe0faa",
      "name": "Save to Google Drive",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        2496,
        144
      ],
      "parameters": {
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive"
        },
        "options": {},
        "folderId": {
          "__rl": true,
          "mode": "list",
          "value": "root",
          "cachedResultName": "/ (Root folder)"
        }
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "f1b73ddf-266e-431e-85ac-910c925a0c09",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        16,
        -464
      ],
      "parameters": {
        "width": 389,
        "height": 444,
        "content": "## How it works\n\nThis workflow transforms a simple text prompt into a complete video with voiceover, stock footage, and subtitles. It uses OpenAI to generate a structured script, converts text to speech, searches Pexels for matching B-roll footage, and assembles everything into video components ready for final editing.\n\n## Setup steps\n\n1. **Add API credentials**: Connect your OpenAI account and Pexels API key (free at pexels.com/api)\n2. **Configure Google Drive**: Set up Google Drive OAuth for video storage\n3. **Test the webhook**: Send a POST request with your video topic\n4. **Install FFmpeg**: Required for final video assembly (or use alternative video editing tool)\n\n**Note**: The final assembly step requires FFmpeg or a video editing service. All components (audio, video clips, subtitles) are prepared and can be manually edited if needed."
      },
      "typeVersion": 1
    },
    {
      "id": "25b768b1-2e65-4bcc-968a-1fcef942946a",
      "name": "Set Video Parameters",
      "type": "n8n-nodes-base.set",
      "position": [
        256,
        144
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "a1b2c3d4",
              "name": "prompt",
              "type": "string",
              "value": "Create a 60-second video about the benefits of morning exercise"
            },
            {
              "id": "b2c3d4e5",
              "name": "videoStyle",
              "type": "string",
              "value": "motivational"
            },
            {
              "id": "c3d4e5f6",
              "name": "targetDuration",
              "type": "number",
              "value": "60"
            }
          ]
        }
      },
      "typeVersion": 3.3
    },
    {
      "id": "5cbebc12-a5d1-4a5f-820f-e14e1fb27db3",
      "name": "Prepare Script Prompt",
      "type": "n8n-nodes-base.set",
      "position": [
        480,
        144
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "d4e5f6g7",
              "name": "systemPrompt",
              "type": "string",
              "value": "You are a professional video script writer. Create a detailed video script with the following format:\n\nScene 1:\nVoiceover: [What the narrator says]\nVisual: [Description of what should be shown]\n\nScene 2:\nVoiceover: [What the narrator says]\nVisual: [Description of what should be shown]\n\nCreate 4-6 scenes for a {{ $('Set Video Parameters').item.json.targetDuration }}-second video about: {{ $('Set Video Parameters').item.json.prompt }}\n\nStyle: {{ $('Set Video Parameters').item.json.videoStyle }}\n\nMake the script engaging, concise, and suitable for stock footage visuals."
            }
          ]
        }
      },
      "typeVersion": 3.3
    },
    {
      "id": "dca76e16-6d41-4baf-b3e2-677f498eeaae",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        32,
        144
      ],
      "parameters": {
        "path": "2d562675-fada-4183-aca9-a95813e81819",
        "options": {}
      },
      "typeVersion": 2.1
    },
    {
      "id": "4d2a9351-7718-4efa-a2d3-eada3e8aa353",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -16,
        16
      ],
      "parameters": {
        "color": 4,
        "width": 528,
        "height": 240,
        "content": "## Input & Configuration\n\nReceives video prompt via webhook and sets parameters like duration, style, and prepares the AI script generation prompt."
      },
      "typeVersion": 1
    },
    {
      "id": "74175936-d229-4cb5-95fa-7fefd1a341e5",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        656,
        16
      ],
      "parameters": {
        "color": 3,
        "width": 304,
        "height": 240,
        "content": "## Script Generation\n\nUses OpenAI to create a structured video script with scenes, voiceover text, and visual descriptions."
      },
      "typeVersion": 1
    },
    {
      "id": "f0be8b88-4549-4d86-a96f-72d618d7e700",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1104,
        -80
      ],
      "parameters": {
        "color": 5,
        "width": 528,
        "height": 336,
        "content": "## Content Generation\n\nGenerates AI voiceover from script and searches Pexels for matching stock footage based on scene descriptions."
      },
      "typeVersion": 1
    },
    {
      "id": "a2e42ac7-82b8-4e59-aa9e-eff1f790aa81",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1776,
        16
      ],
      "parameters": {
        "color": 2,
        "width": 720,
        "height": 240,
        "content": "## Assembly & Export\n\nCombines audio and video clips, generates SRT subtitles, assembles final video, and uploads to Google Drive."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "f19a5bdd-8a23-4eb8-8040-b8b6096c6a94",
  "connections": {
    "Webhook": {
      "main": [
        [
          {
            "node": "Set Video Parameters",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Video URLs": {
      "main": [
        [
          {
            "node": "Download B-Roll Footage",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Audio & Video": {
      "main": [
        [
          {
            "node": "Generate Subtitles (SRT)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Assemble Final Video": {
      "main": [
        [
          {
            "node": "Save to Google Drive",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Video Parameters": {
      "main": [
        [
          {
            "node": "Prepare Script Prompt",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Video Script": {
      "main": [
        [
          {
            "node": "Parse Script into Scenes",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Script Prompt": {
      "main": [
        [
          {
            "node": "Generate Video Script",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download B-Roll Footage": {
      "main": [
        [
          {
            "node": "Merge Audio & Video",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Generate Subtitles (SRT)": {
      "main": [
        [
          {
            "node": "Assemble Final Video",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Voiceover (TTS)": {
      "main": [
        [
          {
            "node": "Merge Audio & Video",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Script into Scenes": {
      "main": [
        [
          {
            "node": "Generate Voiceover (TTS)",
            "type": "main",
            "index": 0
          },
          {
            "node": "Search Stock Footage (Pexels)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Search Stock Footage (Pexels)": {
      "main": [
        [
          {
            "node": "Extract Video URLs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Automatically creates complete videos from a text prompt—script, voiceover, stock footage, and subtitles all assembled and ready.

Source: https://n8n.io/workflows/10502/ — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

Transforms provider documentation (URLs) into an auditable, enforceable multicloud security control baseline. It: Fetches and sanitizes HTML Uses AI to extract security requirements* (strict 3-line TX

HTTP Request, OpenAI, Google Drive
AI & RAG

Listens for completed Fireflies transcripts, qualifies whether a proposal is needed using OpenAI, drafts structured proposal content, populates a Google Doc template, converts to PDF, and sends it to

HTTP Request, OpenAI, Google Drive +3
AI & RAG

This system meticulously guides each lead through a fully automated journey, from initial contact to a personalized follow-up and CRM integration.

OpenAI, @Elevenlabs/N8N Nodes Elevenlabs, Google Drive +4
AI & RAG

A smart, fully automated coding pipeline built inside n8n that leverages Cursor AI to write, refactor, review, and optimize code projects — triggered by a webhook, schedule, or manual prompt. Every ou

HTTP Request, Google Drive, Google Sheets +2
AI & RAG

Build a fully automated music generation workflow in n8n using Suno to create and store AI-generated songs.

HTTP Request, Google Drive, Google Sheets +2