{
  "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
          }
        ]
      ]
    }
  }
}