This workflow corresponds to n8n.io template #12168 — we link there as the canonical source.
This workflow follows the Chainllm → Google Drive 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 →
{
"meta": {
"templateCredsSetupCompleted": true
},
"nodes": [
{
"id": "43e0eeb0-ae4a-4fcd-92be-b9d39a424594",
"name": "Every 2 Hours1",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
272,
-176
],
"parameters": {
"rule": {
"interval": [
{
"field": "hours",
"hoursInterval": 2
}
]
}
},
"typeVersion": 1.1
},
{
"id": "4b4a6de0-642c-4b6a-8e97-c0e40ea62e00",
"name": "Google Gemini Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"position": [
432,
-352
],
"parameters": {
"options": {}
},
"credentials": {
"googlePalmApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "04f034fb-37c7-4ef3-83f1-bc39c9814fd5",
"name": "Append or update row in sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
896,
-176
],
"parameters": {
"columns": {
"value": {
"id": "={{ $json.id }}",
"idea": "={{ $json.idea }}",
"caption": "={{ $json.caption }}",
"production": "={{ $json.production }}",
"final_output": "={{ $json.final_output }}",
"environment_pro": "={{ $json.environment_pro }}"
},
"schema": [
{
"id": "id",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "id",
"defaultMatch": true,
"canBeUsedToMatch": true
},
{
"id": "idea",
"type": "string",
"display": true,
"required": false,
"displayName": "idea",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "caption",
"type": "string",
"display": true,
"required": false,
"displayName": "caption",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "production",
"type": "string",
"display": true,
"required": false,
"displayName": "production",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "environment_pro",
"type": "string",
"display": true,
"required": false,
"displayName": "environment_pro",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "final_output",
"type": "string",
"display": true,
"required": false,
"displayName": "final_output",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"id"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "appendOrUpdate",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1yiKLl4AnBOODSBJsF0n-AcU1v15JdBPPvcjj-n1i5fg/edit#gid=0",
"cachedResultName": "Sheet1"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1yiKLl4AnBOODSBJsF0n-AcU1v15JdBPPvcjj-n1i5fg",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1yiKLl4AnBOODSBJsF0n-AcU1v15JdBPPvcjj-n1i5fg/edit?usp=drivesdk",
"cachedResultName": "Video Prod Sheet - VEO3"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.7
},
{
"id": "6a5145ff-a81b-4df4-9203-ca75dfa66a57",
"name": "Basic LLM Chain",
"type": "@n8n/n8n-nodes-langchain.chainLlm",
"position": [
432,
-176
],
"parameters": {
"text": "=Generate a complete video production concept for this idea: prompt_here\n\nYou MUST respond with ONLY valid JSON in this exact format:\n{\n \"id\": \"6-character alphanumeric code\",\n \"idea\": \"2-3 sentence detailed video concept description\",\n \"caption\": \"engaging social media caption under 150 characters\",\n \"production\": \"equipment needed, crew size, estimated time\",\n \"environment_pro\": \"location, props, set requirements\",\n \"final_output\": \"format, duration, platform specifications\"\n}\n\nExample:\n{\n \"id\": \"Y3T1V8\",\n \"idea\": \"A friendly Yeti sits in a snowy mountain cave holding a selfie stick...\",\n \"caption\": \"POV: You're a Yeti trying to go viral \u2744\ufe0f\ud83d\udcf1\",\n \"production\": \"1 camera operator, GoPro + extension pole, 2-3 hours\",\n \"environment_pro\": \"Snowy set with cave backdrop, selfie stick, fur costume\",\n \"final_output\": \"1080p MP4, 60-90 sec, TikTok/Instagram Reels 9:16\"\n}\n\nGenerate actual content, not the schema definition.",
"batching": {},
"promptType": "define"
},
"typeVersion": 1.7
},
{
"id": "4eb96131-e8ad-41ec-86db-11e207349fff",
"name": "Code in JavaScript",
"type": "n8n-nodes-base.code",
"position": [
720,
-176
],
"parameters": {
"jsCode": "// Get the text output from the LLM\nconst text = $input.first().json.text;\n\n// Remove markdown code blocks (```json and ```)\nconst cleanedText = text.replace(/```json\\n?/g, '').replace(/```\\n?/g, '').trim();\n\n// Parse the JSON\nconst parsedData = JSON.parse(cleanedText);\n\n// Return the parsed object\nreturn [{\n json: parsedData\n}];"
},
"typeVersion": 2
},
{
"id": "d93a1c94-5c35-4003-a1a9-24a099e862ec",
"name": "Code in JavaScript1",
"type": "n8n-nodes-base.code",
"position": [
1376,
-176
],
"parameters": {
"jsCode": "// Extract and clean the Veo 3 prompt text from LLM output\nconst text = $input.first().json.text;\n\n// Remove any template variables that weren't resolved\n// The prompt should be plain text, not contain {{ }} variables\nconst cleanedPrompt = text\n .trim()\n .replace(/\\{\\{[^}]+\\}\\}/g, '') // Remove any unresolved template variables\n .replace(/\\s+/g, ' ') // Replace multiple spaces with single space\n .trim();\n\n// Get data from previous steps in the workflow\n// This assumes the data flows through from the Google Sheets node\nconst allData = $input.all();\nconst previousData = allData[0]?.json || {};\n\n// Extract aspect ratio and duration from final_output if available\nlet aspectRatio = '9:16'; // default\nlet duration = '60s'; // default\n\nif (previousData.final_output) {\n aspectRatio = previousData.final_output.includes('9:16') ? '9:16' : '16:9';\n \n // Try to extract duration\n const durationMatch = previousData.final_output.match(/(\\d+)-(\\d+)\\s*seconds?/i);\n if (durationMatch) {\n const avgDuration = Math.floor((parseInt(durationMatch[1]) + parseInt(durationMatch[2])) / 2);\n duration = `${avgDuration}s`;\n }\n}\n\n// Return properly formatted data for Veo 3 API\nreturn [{\n json: {\n id: previousData.id || 'VEO_' + Date.now(),\n veo3_prompt: cleanedPrompt,\n aspect_ratio: aspectRatio,\n duration: duration,\n caption: previousData.caption || '',\n timestamp: new Date().toISOString()\n }\n}];"
},
"typeVersion": 2
},
{
"id": "01505442-9c3a-470f-a524-8c5c15713f2f",
"name": "Setting",
"type": "n8n-nodes-base.set",
"position": [
1632,
-176
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "5cedc3de-6221-4d7e-a6c8-82f4cb9cf0e9",
"name": "PROJECT_ID",
"type": "string",
"value": "project-cd6b8b94-5c8c-49f8-9cf"
},
{
"id": "90019751-e2d5-4764-9bf9-e13916dcc528",
"name": "MODEL_VERSION",
"type": "string",
"value": "veo-3.0-generate-preview"
},
{
"id": "67ab205c-82b3-4263-99c4-c906a0ca6ae9",
"name": "LOCATION",
"type": "string",
"value": "us-central1"
},
{
"id": "413415fb-60c5-4d0d-ac45-1e6178a55227",
"name": "TEXT_PROMPT",
"type": "string",
"value": "={{ $json.veo3_prompt }}"
},
{
"id": "bf0910e1-b757-4852-9341-a7792161f89b",
"name": "ACCESS_TOKEN",
"type": "string",
"value": "Your_Access_Token"
},
{
"id": "17954335-b96b-4813-9c4a-20817d675448",
"name": "API_ENDPOINT",
"type": "string",
"value": "us-central1-aiplatform.googleapis.com"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "4338fb60-3c4a-4e11-8f57-aba096fe98bd",
"name": "Convert to File",
"type": "n8n-nodes-base.convertToFile",
"position": [
1104,
272
],
"parameters": {
"options": {},
"operation": "toBinary",
"sourceProperty": "response.videos[0].bytesBase64Encoded"
},
"typeVersion": 1.1
},
{
"id": "64dce305-789f-4b05-b1e5-2b404048c660",
"name": "Vertex AI-fetch",
"type": "n8n-nodes-base.httpRequest",
"position": [
672,
288
],
"parameters": {
"url": "=https://{{ $('Setting').item.json.API_ENDPOINT }}/v1/projects/{{ $('Setting').item.json.PROJECT_ID }}/locations/{{ $('Setting').item.json.LOCATION }}/publishers/google/models/{{ $('Setting').item.json.MODEL_VERSION }}:fetchPredictOperation\n",
"method": "POST",
"options": {},
"jsonBody": "={\n \"operationName\": \"{{ $json.name }}\"\n}\n",
"sendBody": true,
"sendHeaders": true,
"specifyBody": "json",
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "Authorization",
"value": "=Bearer {{ $('Setting').item.json.ACCESS_TOKEN }}"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "74ddab4e-2bb3-4304-8b43-a1746a95b240",
"name": "Wait",
"type": "n8n-nodes-base.wait",
"position": [
480,
288
],
"parameters": {
"unit": "minutes",
"amount": 2
},
"typeVersion": 1.1
},
{
"id": "e090a167-7a66-406e-ad50-3f7e0da78574",
"name": "Upload file",
"type": "n8n-nodes-base.googleDrive",
"position": [
1296,
272
],
"parameters": {
"name": "={{ $('Code in JavaScript').item.json.caption.replace(/\\s+/g, '_') + '_' + $now.toMillis() }}",
"driveId": {
"__rl": true,
"mode": "list",
"value": "My Drive",
"cachedResultUrl": "https://drive.google.com/drive/my-drive",
"cachedResultName": "My Drive"
},
"options": {},
"folderId": {
"__rl": true,
"mode": "list",
"value": "1ymC_Lf5Zi7wf3EsMIEV687PMclAnDlkV",
"cachedResultUrl": "https://drive.google.com/drive/folders/1ymC_Lf5Zi7wf3EsMIEV687PMclAnDlkV",
"cachedResultName": "Archive"
}
},
"credentials": {
"googleDriveOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 3
},
{
"id": "9036aaee-0fe6-4877-bebb-ebc475df4aa6",
"name": "Log Final Video in Sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
1488,
272
],
"parameters": {
"columns": {
"value": {
"idea": "={{ $('Append or update row in sheet').item.json.idea }}",
"production": "done",
"row_number": 0,
"final_output": "={{ $('Upload file').item.json.webViewLink }}"
},
"schema": [
{
"id": "id",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "id",
"defaultMatch": true,
"canBeUsedToMatch": true
},
{
"id": "idea",
"type": "string",
"display": true,
"required": false,
"displayName": "idea",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "caption",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "caption",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "production",
"type": "string",
"display": true,
"required": false,
"displayName": "production",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "environment_pro",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "environment_pro",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "final_output",
"type": "string",
"display": true,
"required": false,
"displayName": "final_output",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "row_number",
"type": "number",
"display": true,
"removed": false,
"readOnly": true,
"required": false,
"displayName": "row_number",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"idea"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "update",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1yiKLl4AnBOODSBJsF0n-AcU1v15JdBPPvcjj-n1i5fg/edit#gid=0",
"cachedResultName": "Sheet1"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1yiKLl4AnBOODSBJsF0n-AcU1v15JdBPPvcjj-n1i5fg",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1yiKLl4AnBOODSBJsF0n-AcU1v15JdBPPvcjj-n1i5fg/edit?usp=drivesdk",
"cachedResultName": "Video Prod Sheet - VEO3"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.5
},
{
"id": "ee87a34c-5764-42c2-9137-6b59d9d83bc5",
"name": "Vertex AI-VEO",
"type": "n8n-nodes-base.httpRequest",
"position": [
256,
288
],
"parameters": {
"url": "=https://{{ $json.API_ENDPOINT }}/v1/projects/{{ $json.PROJECT_ID }}/locations/{{ $json.LOCATION }}/publishers/google/models/{{ $json.MODEL_VERSION }}:predictLongRunning",
"method": "POST",
"options": {},
"jsonBody": "={\n \"endpoint\": \"projects/n8n-project-440404/locations/us-central1/publishers/google/models/veo-3.0-generate-preview\",\n \"instances\": [\n {\n \"prompt\": {{ JSON.stringify($json.TEXT_PROMPT) }}\n }\n ],\n \"parameters\": {\n \"aspectRatio\": \"9:16\",\n \"sampleCount\": 1,\n \"durationSeconds\": \"8\",\n \"personGeneration\": \"allow_all\",\n \"addWatermark\": true,\n \"includeRaiReason\": true,\n \"generateAudio\": true\n }\n}\n",
"sendBody": true,
"sendHeaders": true,
"specifyBody": "json",
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "Authorization",
"value": "=Bearer {{ $json.ACCESS_TOKEN }}"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "fc571a07-9988-42c3-b98c-9c74c022bef6",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
192,
-448
],
"parameters": {
"color": 7,
"width": 836,
"height": 464,
"content": "## 1. Generate ideas for the prompt"
},
"typeVersion": 1
},
{
"id": "a9a42c29-5d70-421c-ba94-44d433413da2",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
1056,
-448
],
"parameters": {
"color": 7,
"width": 840,
"height": 464,
"content": "## 2. Generate Prompt for the video\n"
},
"typeVersion": 1
},
{
"id": "dbf69e01-3104-4795-af96-161f70f69825",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
192,
48
],
"parameters": {
"color": 7,
"width": 1704,
"height": 464,
"content": "## 3. Generate video, convert to mp4, store and log\n"
},
"typeVersion": 1
},
{
"id": "419d4197-14be-4168-8c43-99bc4f2185aa",
"name": "Basic LLM Chain - Prompt",
"type": "@n8n/n8n-nodes-langchain.chainLlm",
"position": [
1088,
-176
],
"parameters": {
"text": "=You are a Veo 3 video prompt engineer. \nGive me a Veo3 prompt for this idea:\n{{ $json.idea }}\n\nThis is the environment:\n{{ $json.environment_pro }}\n\n",
"batching": {},
"promptType": "define"
},
"typeVersion": 1.7
},
{
"id": "66710f9b-f0e7-4f85-9f9a-6380b0f97713",
"name": "Is Video Complete?1",
"type": "n8n-nodes-base.if",
"position": [
864,
288
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 1,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "5b86e527-716f-4ed2-a1ca-c1c1b5336396",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
},
"leftValue": "={{ $json.done }}",
"rightValue": "true"
}
]
}
},
"typeVersion": 2
},
{
"id": "d03ecfd6-a00f-4fdb-8586-6d1abfffeb65",
"name": "Wait 1 Min & Retry1",
"type": "n8n-nodes-base.wait",
"position": [
864,
80
],
"parameters": {
"amount": 60
},
"typeVersion": 1.1
},
{
"id": "c1215511-7b07-4242-bfe3-b0a2a69ab2ea",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
1504,
-352
],
"parameters": {
"color": 5,
"width": 352,
"height": 352,
"content": "## Change Access Token every hour or auto refreshes token using a Google cloud service account"
},
"typeVersion": 1
},
{
"id": "efe8301d-3971-4c4a-ba97-deee9b057261",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
-656,
-448
],
"parameters": {
"width": 800,
"height": 880,
"content": "## AI-Powered Video Generation Pipeline with Google Drive Storage\n\n## How it works\n- **Schedule Trigger** node to start the workflow\n- **Basic LLM chain** node works with Google Gemini AI (Can be replaced by Claude AI or OpenAI) to generate ideas using a prompt\n- **Code** nodes are used to pass the prompt in a structured output\n- **Google Sheet** nodes to log in the results\n- **HTTP request** node is used to call **vertex AI ACCESS TOKEN**\n- Setting is to edit ACCESS TOKEN (Note: **ACCESS TOKEN** Changes hourly)\n- **Wait** node to delay\n- Convert to file is used to convert base64 to MP4\n- **Google Drive** node is used to store video in the Google Drive folder\n- **If** node to check if video is completed, otherwise wait 1 more minute and run again\n\n## Setup\n1. Get the Google Sheet template below\n2. Set Prompts in Basic LLM chain nodes\n3. Setup [**Google Cloud**](https://console.cloud.google.com/vertex-ai/studio/) and enable Vertex AI and get **ACCESS TOKEN** - use \"gcloud auth print-access-token\" in Google Cloud terminal\n4. Enable [Google Drive](https://console.cloud.google.com/) in Google Cloud and setup credential\n5. Get [Gemini API](https://aistudio.google.com/) and setup credential\n\n## [Get Google Sheet template](https://docs.google.com/spreadsheets/d/1575_YE8kQk92Xj2DTpx4feCYDXu4hZh8CVl57Un2l2k/edit?usp=sharing)"
},
"typeVersion": 1
}
],
"connections": {
"Wait": {
"main": [
[
{
"node": "Vertex AI-fetch",
"type": "main",
"index": 0
}
]
]
},
"Setting": {
"main": [
[
{
"node": "Vertex AI-VEO",
"type": "main",
"index": 0
}
]
]
},
"Upload file": {
"main": [
[
{
"node": "Log Final Video in Sheet",
"type": "main",
"index": 0
}
]
]
},
"Vertex AI-VEO": {
"main": [
[
{
"node": "Wait",
"type": "main",
"index": 0
}
]
]
},
"Every 2 Hours1": {
"main": [
[
{
"node": "Basic LLM Chain",
"type": "main",
"index": 0
}
]
]
},
"Basic LLM Chain": {
"main": [
[
{
"node": "Code in JavaScript",
"type": "main",
"index": 0
}
]
]
},
"Convert to File": {
"main": [
[
{
"node": "Upload file",
"type": "main",
"index": 0
}
]
]
},
"Vertex AI-fetch": {
"main": [
[
{
"node": "Is Video Complete?1",
"type": "main",
"index": 0
}
]
]
},
"Code in JavaScript": {
"main": [
[
{
"node": "Append or update row in sheet",
"type": "main",
"index": 0
}
]
]
},
"Code in JavaScript1": {
"main": [
[
{
"node": "Setting",
"type": "main",
"index": 0
}
]
]
},
"Is Video Complete?1": {
"main": [
[
{
"node": "Convert to File",
"type": "main",
"index": 0
}
],
[
{
"node": "Wait 1 Min & Retry1",
"type": "main",
"index": 0
}
]
]
},
"Wait 1 Min & Retry1": {
"main": [
[
{
"node": "Vertex AI-fetch",
"type": "main",
"index": 0
}
]
]
},
"Basic LLM Chain - Prompt": {
"main": [
[
{
"node": "Code in JavaScript1",
"type": "main",
"index": 0
}
]
]
},
"Google Gemini Chat Model": {
"ai_languageModel": [
[
{
"node": "Basic LLM Chain",
"type": "ai_languageModel",
"index": 0
},
{
"node": "Basic LLM Chain - Prompt",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Append or update row in sheet": {
"main": [
[
{
"node": "Basic LLM Chain - Prompt",
"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.
googleDriveOAuth2ApigooglePalmApigoogleSheetsOAuth2Api
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Automate video creation: AI generates ideas, Vertex AI renders videos, and auto-uploads to Google Drive with complete tracking.
Source: https://n8n.io/workflows/12168/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
Categories Content Creation AI Automation Publishing Social Media
ANIS_HUB 1. Uses gmail, googleDrive, googleSheets, httpRequest. Webhook trigger; 89 nodes.
Resume Screening & Behavioral Interviews with Gemini, Elevenlabs, & Notion ATS copy. Uses outputParserStructured, chainLlm, googleDrive, stickyNote. Webhook trigger; 67 nodes.
Candidate Engagement | Resume Screening | AI Voice Interviews | Applicant Insights
The Multi-Model Agency Content Engine is a high-performance editorial system designed for agencies. It solves the "blank page" problem by alternating between real-world social proof and strategic expe