AutomationFlowsAI & RAG › Narrative Chaining: Ai-generated Video Scene Extensions with Veo3

Narrative Chaining: Ai-generated Video Scene Extensions with Veo3

ByDeniz @denizdinc on n8n.io

Use a Google Sheet as the control panel. Fields required: Video URL (starting clip, ends with .mp4) Number of clips to extend (e.g., 2 extra scenes) Aspect ratio (horizontal, vertical, etc.) Model (V3 or V3 Fast) Narrative theme (guidance for story flow) Special requests…

Event trigger★★★★★ complexityAI-powered30 nodesTool ThinkOpenAI ChatHTTP RequestGoogle SheetsOutput Parser StructuredAgent
AI & RAG Trigger: Event Nodes: 30 Complexity: ★★★★★ AI nodes: yes Added:

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

This workflow follows the Agent → Google Sheets 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": "guIhqI2p5qRsxiOg",
  "name": "Narrative Chaining with Veo3 fast \u2705",
  "tags": [],
  "nodes": [
    {
      "id": "2f784e39-a48f-4836-87f0-87418de5669a",
      "name": "Think",
      "type": "@n8n/n8n-nodes-langchain.toolThink",
      "position": [
        2464,
        448
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "8e3e9280-f1ac-4660-ba8f-113e1e5fc066",
      "name": "GPT",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        2528,
        656
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1",
          "cachedResultName": "gpt-4.1"
        },
        "options": {}
      },
      "typeVersion": 1.2
    },
    {
      "id": "f981ea4e-7f0a-4e8b-8c48-1d9be2dee575",
      "name": "Analyze Video",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1712,
        224
      ],
      "parameters": {
        "url": "https://queue.fal.run/fal-ai/video-understanding",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"video_url\": \"{{ $json.mediaURL }}\",\n  \"prompt\": \"What is happening in this video? At the very top, include a Heading 1 Section describing what happens at the last frame of the video. Make sure to describe the music, the camera being used, the camera movement, the dialogue if any, what their accent is, and a description of the characters. \",\n  \"detailed_analysis\": true\n}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "e0846d61-46f3-4c39-90c6-a1dea95e7c7a",
      "name": "Get Analysis",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2160,
        224
      ],
      "parameters": {
        "url": "={{ $json.response_url }}",
        "options": {},
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "e1fa982f-1dc3-4838-bcf7-e045196cd061",
      "name": "Looper",
      "type": "n8n-nodes-base.set",
      "position": [
        1488,
        400
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "845af529-04e4-4a77-ad42-c2a3025148da",
              "name": "step",
              "type": "number",
              "value": "={{ $json.step }}"
            },
            {
              "id": "e1c5b7af-8520-45c6-a1e7-da832f711b0f",
              "name": "complete",
              "type": "number",
              "value": "={{ $json.complete }}"
            },
            {
              "id": "f4f5df61-7c8b-4813-a52b-3a22e69c0dda",
              "name": "mediaURL",
              "type": "string",
              "value": "={{ $json.videoURL }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "491f212b-8651-4d45-b0bf-bc7e69f20669",
      "name": "If ",
      "type": "n8n-nodes-base.if",
      "position": [
        4304,
        224
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "4c895d90-e8bd-42cf-ab58-511c85e8c782",
              "operator": {
                "type": "number",
                "operation": "equals"
              },
              "leftValue": "={{ $json.data.successFlag }}",
              "rightValue": 1
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "055e31c4-3369-4177-9060-20e4deb6b48b",
      "name": "Combine Clips",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        5648,
        400
      ],
      "parameters": {
        "url": "https://queue.fal.run/fal-ai/ffmpeg-api/merge-videos",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"video_urls\": [\"{{ $('Initial Values').item.json.videoURL }}\",{{ $json.sceneURL.map(url => `\"${url}\"`)  }}]\n}\n",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "c00b6a56-49d8-4213-9607-73ffa720ce8b",
      "name": "Get Final Video",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        6096,
        400
      ],
      "parameters": {
        "url": "={{ $('Combine Clips').first().json.response_url }}",
        "options": {},
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "55af6a77-db7a-4329-ade2-9760808a2bc0",
      "name": "Aggregate",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        5424,
        400
      ],
      "parameters": {
        "options": {},
        "fieldsToAggregate": {
          "fieldToAggregate": [
            {
              "fieldToAggregate": "sceneURL"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "78188b56-9710-4cbd-abd6-227afe72b2be",
      "name": "Get input",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        816,
        400
      ],
      "parameters": {
        "options": {},
        "filtersUI": {
          "values": [
            {
              "lookupValue": "for production",
              "lookupColumn": "status"
            }
          ]
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1tNGBG0fTJWynnmiNN_uu1mt1l47HiVhE1CR3Z3_Zt34/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1tNGBG0fTJWynnmiNN_uu1mt1l47HiVhE1CR3Z3_Zt34",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1tNGBG0fTJWynnmiNN_uu1mt1l47HiVhE1CR3Z3_Zt34/edit?usp=drivesdk",
          "cachedResultName": "Copy of [Template] Veo3 - Narrative Chaining by RoboNuggets"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "e6cfd8e6-bbfe-40cf-b977-2e27781d76f8",
      "name": "Initial Values",
      "type": "n8n-nodes-base.set",
      "position": [
        1264,
        400
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "845af529-04e4-4a77-ad42-c2a3025148da",
              "name": "step",
              "type": "number",
              "value": "=1"
            },
            {
              "id": "e1c5b7af-8520-45c6-a1e7-da832f711b0f",
              "name": "complete",
              "type": "number",
              "value": "={{ $json['clips to add'] }}"
            },
            {
              "id": "f4f5df61-7c8b-4813-a52b-3a22e69c0dda",
              "name": "videoURL",
              "type": "string",
              "value": "={{ $json.videoURL }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "ff29427c-9efa-40d1-be92-f3d2e3ac4e4b",
      "name": "Request last",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2960,
        224
      ],
      "parameters": {
        "url": "https://queue.fal.run/fal-ai/ffmpeg-api/extract-frame",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"video_url\": \"{{ $('Looper').item.json.mediaURL }}\",\n  \"frame_type\": \"last\"\n}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "4409fe8a-e900-4b4c-9bd6-159c3ae21dac",
      "name": "Get last",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        3408,
        224
      ],
      "parameters": {
        "url": "={{ $json.response_url }}",
        "options": {},
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "23e39c46-7f46-48b4-bfc0-5f76bf184d9f",
      "name": "Get Video",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        4080,
        144
      ],
      "parameters": {
        "url": "=https://api.kie.ai/api/v1/veo/record-info",
        "options": {},
        "sendQuery": true,
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "queryParameters": {
          "parameters": [
            {
              "name": "taskId",
              "value": "={{ $('Create Video').item.json.data.taskId }}"
            }
          ]
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "9973941e-2f67-4dcd-a641-45757bb6c2bc",
      "name": "Create Video",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        3632,
        224
      ],
      "parameters": {
        "url": "https://api.kie.ai/api/v1/veo/generate",
        "body": "={\n  \"prompt\":\"{{ $('Extend AI Agent').item.json.output.video_prompt.replace(/\\n/g, '\\\\n').replace(/\"/g, '\\\\\"') }}\",\n  \"model\": \"{{ $('Extend AI Agent').item.json.output.model }}\",\n  \"aspectRatio\": \"{{ $('Extend AI Agent').item.json.output.aspect_ratio_video }}\",\n  \"imageUrls\": \"{{ $json.images[0].url }}\"\n}\n",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "contentType": "raw",
        "authentication": "genericCredentialType",
        "rawContentType": "application/json",
        "genericAuthType": "httpHeaderAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "6734b45c-2cfa-4992-9856-eaa5bc0663c3",
      "name": "Add scene",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        4528,
        224
      ],
      "parameters": {
        "columns": {
          "value": {
            "scene": "={{ $('Looper').item.json.step }}",
            "prompt": "={{ $('Extend AI Agent').item.json.output.video_prompt }}",
            "sceneURL": "={{ $json.data.response.resultUrls[0] }}",
            "row_number": 0
          },
          "schema": [
            {
              "id": "scene",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "scene",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "prompt",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "prompt",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "sceneURL",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "sceneURL",
              "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": [
            "scene"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 423194450,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1x65wzvPcZAahQsegZ8h99Qh3boI5xRNymx-gtlE9QEU/edit#gid=423194450",
          "cachedResultName": "Sheet2"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1tNGBG0fTJWynnmiNN_uu1mt1l47HiVhE1CR3Z3_Zt34",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1tNGBG0fTJWynnmiNN_uu1mt1l47HiVhE1CR3Z3_Zt34/edit?usp=drivesdk",
          "cachedResultName": "Copy of [Template] Veo3 - Narrative Chaining by RoboNuggets"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "bac15ac5-c0f0-43e7-87bd-8a9c38af25f4",
      "name": "Increment step",
      "type": "n8n-nodes-base.set",
      "position": [
        4752,
        224
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "845af529-04e4-4a77-ad42-c2a3025148da",
              "name": "step",
              "type": "number",
              "value": "={{ $('Looper').first().json.step + 1}}"
            },
            {
              "id": "e1c5b7af-8520-45c6-a1e7-da832f711b0f",
              "name": "complete",
              "type": "number",
              "value": "={{ $('Looper').first().json.complete }}"
            },
            {
              "id": "7486f15a-a92c-46c1-a77f-375c970e3c77",
              "name": "videoURL",
              "type": "string",
              "value": "={{ $json.sceneURL }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "d021df59-2754-47f0-8547-5e77b64617ab",
      "name": "If complete",
      "type": "n8n-nodes-base.if",
      "position": [
        4976,
        400
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "a4b84c6a-c477-4929-a527-c70201b829d4",
              "operator": {
                "type": "number",
                "operation": "lt"
              },
              "leftValue": "={{ $json.complete }}",
              "rightValue": "={{ $json.step }}"
            }
          ]
        },
        "looseTypeValidation": true
      },
      "typeVersion": 2.2
    },
    {
      "id": "e01481e0-2f85-4235-909d-4817d98f4dcc",
      "name": "Wait 2",
      "type": "n8n-nodes-base.wait",
      "position": [
        3856,
        224
      ],
      "parameters": {
        "amount": 60
      },
      "typeVersion": 1.1
    },
    {
      "id": "2d0eca0f-6ad4-4403-b590-18e95e2b7e30",
      "name": "Wait 1",
      "type": "n8n-nodes-base.wait",
      "position": [
        3184,
        224
      ],
      "parameters": {
        "amount": 30
      },
      "typeVersion": 1.1
    },
    {
      "id": "79c04913-3f50-46c7-9913-52fd4d8170e7",
      "name": "Wait ",
      "type": "n8n-nodes-base.wait",
      "position": [
        1936,
        224
      ],
      "parameters": {
        "amount": 60
      },
      "typeVersion": 1.1
    },
    {
      "id": "4d168fec-e2d8-46fd-9285-aeac41a6f22e",
      "name": "Get scenes",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        5200,
        400
      ],
      "parameters": {
        "options": {
          "dataLocationOnSheet": {
            "values": {
              "range": "C:C",
              "rangeDefinition": "specifyRangeA1"
            }
          }
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 423194450,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1tNGBG0fTJWynnmiNN_uu1mt1l47HiVhE1CR3Z3_Zt34/edit#gid=423194450",
          "cachedResultName": "Sheet2"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1tNGBG0fTJWynnmiNN_uu1mt1l47HiVhE1CR3Z3_Zt34",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1tNGBG0fTJWynnmiNN_uu1mt1l47HiVhE1CR3Z3_Zt34/edit?usp=drivesdk",
          "cachedResultName": "Copy of [Template] Veo3 - Narrative Chaining by RoboNuggets"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "649b2d92-1036-4de5-bde4-1c81fc4d9eaf",
      "name": "Wait 3",
      "type": "n8n-nodes-base.wait",
      "position": [
        5872,
        400
      ],
      "parameters": {
        "amount": 60
      },
      "typeVersion": 1.1
    },
    {
      "id": "57b479f9-b82c-49b8-9def-1e46bea290ee",
      "name": "Update log",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        6320,
        400
      ],
      "parameters": {
        "columns": {
          "value": {
            "id": "={{ $('Get input').item.json.id }}",
            "status": "done",
            "outputURL": "={{ $json.video.url }}",
            "row_number": 0
          },
          "schema": [
            {
              "id": "id",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "id",
              "defaultMatch": true,
              "canBeUsedToMatch": true
            },
            {
              "id": "videoURL",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "videoURL",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "clips to add",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "clips to add",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "aspect ratio",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "aspect ratio",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "narrative theme",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "narrative theme",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "model",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "model",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "any special requests",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "any special requests",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "status",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "outputURL",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "outputURL",
              "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": [
            "id"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1x65wzvPcZAahQsegZ8h99Qh3boI5xRNymx-gtlE9QEU/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1tNGBG0fTJWynnmiNN_uu1mt1l47HiVhE1CR3Z3_Zt34",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1tNGBG0fTJWynnmiNN_uu1mt1l47HiVhE1CR3Z3_Zt34/edit?usp=drivesdk",
          "cachedResultName": "Copy of [Template] Veo3 - Narrative Chaining by RoboNuggets"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "4127d103-89b6-4c4d-94e0-4c116faef6d7",
      "name": "Structured Output",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        2592,
        448
      ],
      "parameters": {
        "autoFix": true,
        "jsonSchemaExample": "{\n  \"video_prompt\": \"detailed stringified YAML prompt here\",\n  \"aspect_ratio_video\": \"9:16\",\n  \"model\": \"veo3_fast\"\n}\n"
      },
      "typeVersion": 1.3
    },
    {
      "id": "2e3d3839-5570-4d71-9794-de9cf6ffd165",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        608,
        -112
      ],
      "parameters": {
        "color": 4,
        "width": 5856,
        "height": 176,
        "content": "#  - Veo3 Narrative Chaining \n"
      },
      "typeVersion": 1
    },
    {
      "id": "02d0b3c3-34f6-46c4-94ae-611e398fa092",
      "name": "Execute",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        592,
        400
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "57b9077e-f79d-486f-bdc7-c6d2aace61f7",
      "name": "Clear scenes",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1040,
        400
      ],
      "parameters": {
        "clear": "specificRange",
        "range": "B2:C20",
        "operation": "clear",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 423194450,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1tNGBG0fTJWynnmiNN_uu1mt1l47HiVhE1CR3Z3_Zt34/edit#gid=423194450",
          "cachedResultName": "Sheet2"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1tNGBG0fTJWynnmiNN_uu1mt1l47HiVhE1CR3Z3_Zt34",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1tNGBG0fTJWynnmiNN_uu1mt1l47HiVhE1CR3Z3_Zt34/edit?usp=drivesdk",
          "cachedResultName": "Copy of [Template] Veo3 - Narrative Chaining by RoboNuggets"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "47a708f9-29cc-4e1c-8afe-23adbfe40624",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        0,
        0
      ],
      "parameters": {
        "width": 528,
        "height": 1392,
        "content": "Structured Setup Guide: Narrative Chaining with N8N + AI\n\n1. Input Setup\nUse a Google Sheet as the control panel.\nFields required:\nVideo URL (starting clip, ends with .mp4)\nNumber of clips to extend (e.g., 2 extra scenes)\nAspect ratio (horizontal, vertical, etc.)\nModel (V3 or V3 Fast)\nNarrative theme (guidance for story flow)\nSpecial requests (scene-by-scene instructions)\nStatus column (e.g., \"For Production\", \"Done\")\n\ud83d\udc49 Example scene inputs:\nScene 1: Naruto walks out with ramen is his hands\nScene 2: Joker joins with chips\n2. Workflow in N8N\nStep 1: Fetch Input\nGet rows in sheet \u2192 fetch the next row where status = For Production.\nClear sheet 2 \u2192 reset the sheet that stores generated scenes.\nEdit fields (Initial Values):\nVideo URL = starting clip\nStep = 1\nComplete = total number of scenes requested\nStep 2: Looping Logic\nLooper Node:\nRuns until step = complete.\nCarries over current video URL \u2192 feeds into next generation.\nStep 3: Analyze Current Clip\nSend video URL to File.AI Video Understanding API.\nRequest: Describe last frame + audio + scene details.\nOutput: Detailed video analysis text.\nStep 4: Generate Prompt\nAI Agent creates the next scene prompt using:\nContext from video analysis\nNarrative theme (from sheet)\nScene instructions (from sheet)\nAspect ratio, model preference, etc.\n\ud83d\udc49 Output = video prompt for next scene\nStep 5: Extract Last Frame\nCall File.AI Extract Frame API.\nParameters:\nInput video URL\nFrame = last\nOutput = JPG image (last frame of current clip).\nStep 6: Generate New Scene\nUse Key.AI (V3 Fast) for economical video generation.\nPOST request includes:\nPrompt (from AI Agent)\nAspect ratio + model\nImage URL (last frame) \u2192 ensures seamless chaining\nWait for generation to complete.\n\ud83d\udc49 Output = New clip URL (MP4)\nStep 7: Store & Increment\nLog new clip URL into Sheet 2.\nIncrement Step by +1.\nReplace Video URL with the new clip.\nLoop back if Step < Complete.\n3. Output Section\nOnce all clips are generated:\nGather all scene URLs from Sheet 2.\nUse File.AI Merge Videos API to stitch clips together:\nOriginal clip + all generated scenes.\nSave final MP4 output.\nUpdate Sheet 1 row with:\nFinal video URL\nStatus = Done\n4. Costs\nVideo analysis: ~$0.015 per 8s clip\nFrame extraction: ~0.002\u00a2 (almost free)\nClip merging: negligible (via ffmpeg backend)\nV3 Fast video generation (Key.AI): ~$0.30 per 8s clip\n"
      },
      "typeVersion": 1
    },
    {
      "id": "7c20a138-35af-4a12-8c22-47e2fc52b07a",
      "name": "Extend AI Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        2384,
        224
      ],
      "parameters": {
        "text": "=Your task: Create a video prompt as guided by your system guidelines.\n\nYou are about to create the video prompt for Scene {{ $('Looper').first().json.step }}, out of a total of {{ $('Looper').first().json.complete }} scenes\n\n\n***\nThe user's preferred narrative theme (if any): {{ $('Get input').first().json['narrative theme'] }}\n\nThe user's preferred aspect ratio: {{ $('Get input').first().json['aspect ratio'] }}\n\nThe user's preferred model: {{ $('Get input').first().json.model }}\n\nAny special requests by the user: {{ $('Get input').first().json['any special requests'] }}\n\n***\nUse the Think tool to double check your output\n\n\n***\n\n\nHere's what happens in the preceding video \n{{ $json.output }}\n\n",
        "options": {
          "systemMessage": "=system_prompt: |\n  ## SYSTEM PROMPT: Scene Continuation Prompt Generator (Video-Only, General Use)\n\n  You are a scene continuation AI agent.  \n  Your task: Take the preceding video description and generate the scene, following user intent, style, and narrative progression. Make sure to generate the prompt with the ending seconds of the previous scene in mind.\n\n  A \u2013 Ask:\n    Generate **only video generation instructions** for AI models (no image prompts). Infer aspect ratios from vertical/horizontal context; default to vertical if unspecified.\n\n\n  G \u2013 Guidance:\n\n    - Make sure you consider consistency with the music style, camera, camera movement, and other elements from the previous scene when generating the prompt\n    - If the user describes what happens per scene, make sure you just follow the instructions specific to this scene you are ideating for\n    - Focus the prompt to consider what happens in the very last frame as described in the video\n    - Always define the type of camera being used (example: Canon EOS, Gopro, iphone). and camera movement (be consistent with previous scene)\n    - The actions defined in the scene are always simple. Avoid overly complex action prompts. Max of 250 characters for the action.\n    - ALways describe the music if preceding scene has music\n    - ALways describe the dialogue if preceding scene has dialogue (make sure accent of person is the same)\n    - The video prompt is ALWAYS in stringified YAML format. Suggest the element parameters based on the user request\n    - Avoid mentioning any copyrighted character, persons, or brands in the prompt. Just describe them if needed\n    - Avoid terms in the prompt that may trigger a content policy flag. Like child, childlike, minor, young person, girl, boy, 14 year old, and so on. Instead of using those terms, just say \"character\".\n    - Avoid including prompts with text overlays or subtitles. \n    - Align each new scene with the progression of the previous video.\n    - Follow any user-supplied dialogue, action requests, or performance details.\n    - Use consistent characters, camera style, and tone when applicable.\n    - Never use double quotes in prompts.\n\"notes\": [\n    \"- Aspect ratio can only be 9:16 or 16:9\",\n    \"- Model can only be veo3_fast or veo3\"\n\n  E \u2013 Examples:\n    \ud83d\udfe2 good_examples:\n      - |\n       {\n  \"scenes\": [\n    {\n      \"video_prompt\": \"prompt in yaml format based on previous video and user request\",\n      \"aspect_ratio_video\": \"[choose: 9:16, 16:9]\",\n      \"model\": \"[choose: veo3_fast, veo3]\"\n    }\n  ]\n}\n\n\n  N \u2013 Notation:\n    format: JSON\n    example_output: |\n      {\n        \"scenes\": [\n          {\n            \"video_prompt\": \"dialogue: [text]\\naction: [text]\\ncamera: [text]\\nemotion: [text]\\ntype: [model]\",\n            \"aspect_ratio_video\": \"9:16\",\n            \"model\": \"veo3_fast\"\n          }\n        ]\n      }\n\n  T \u2013 Tools:\n    - Think Tool: Use this to check continuity from the previous scene, alignment with user intent, realism or stylization as needed, and that the output count matches exactly.\n"
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 2
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "5f1c7fff-35c2-4f82-bb2e-2bebbeae5824",
  "connections": {
    "GPT": {
      "ai_languageModel": [
        [
          {
            "node": "Extend AI Agent",
            "type": "ai_languageModel",
            "index": 0
          },
          {
            "node": "Structured Output",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "If ": {
      "main": [
        [
          {
            "node": "Add scene",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Wait 2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Think": {
      "ai_tool": [
        [
          {
            "node": "Extend AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Wait ": {
      "main": [
        [
          {
            "node": "Get Analysis",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Looper": {
      "main": [
        [
          {
            "node": "Analyze Video",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait 1": {
      "main": [
        [
          {
            "node": "Get last",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait 2": {
      "main": [
        [
          {
            "node": "Get Video",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait 3": {
      "main": [
        [
          {
            "node": "Get Final Video",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Execute": {
      "main": [
        [
          {
            "node": "Get input",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get last": {
      "main": [
        [
          {
            "node": "Create Video",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Add scene": {
      "main": [
        [
          {
            "node": "Increment step",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate": {
      "main": [
        [
          {
            "node": "Combine Clips",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Video": {
      "main": [
        [
          {
            "node": "If ",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get input": {
      "main": [
        [
          {
            "node": "Clear scenes",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get scenes": {
      "main": [
        [
          {
            "node": "Aggregate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If complete": {
      "main": [
        [
          {
            "node": "Get scenes",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Looper",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Clear scenes": {
      "main": [
        [
          {
            "node": "Initial Values",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Video": {
      "main": [
        [
          {
            "node": "Wait 2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Analysis": {
      "main": [
        [
          {
            "node": "Extend AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Request last": {
      "main": [
        [
          {
            "node": "Wait 1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Analyze Video": {
      "main": [
        [
          {
            "node": "Wait ",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Combine Clips": {
      "main": [
        [
          {
            "node": "Wait 3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Increment step": {
      "main": [
        [
          {
            "node": "If complete",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Initial Values": {
      "main": [
        [
          {
            "node": "Looper",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extend AI Agent": {
      "main": [
        [
          {
            "node": "Request last",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Final Video": {
      "main": [
        [
          {
            "node": "Update log",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output": {
      "ai_outputParser": [
        [
          {
            "node": "Extend AI Agent",
            "type": "ai_outputParser",
            "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

Use a Google Sheet as the control panel. Fields required: Video URL (starting clip, ends with .mp4) Number of clips to extend (e.g., 2 extra scenes) Aspect ratio (horizontal, vertical, etc.) Model (V3 or V3 Fast) Narrative theme (guidance for story flow) Special requests…

Source: https://n8n.io/workflows/9145/ — 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

🎯 Create viral TikToks, Shorts, Reels, podcasts, and ASMR videos in minutes — all on autopilot.

OpenAI, HTTP Request, Form Trigger +7
AI & RAG

Generate AI viral videos with NanoBanana & VEO3, shared on socials via Blotato 2. Uses @blotato/n8n-nodes-blotato, googleSheets, lmChatOpenAi, toolThink. Event-driven trigger; 94 nodes.

@Blotato/N8N Nodes Blotato, Google Sheets, OpenAI Chat +9
AI & RAG

This template is designed for marketers, content creators, and e-commerce brands who want to automate the creation of professional ad videos at scale. It’s ideal for teams looking to generate consiste

Telegram, Telegram Trigger, Google Drive +8
AI & RAG

This workflow contains community nodes that are only compatible with the self-hosted version of n8n.

Output Parser Structured, Telegram, N8N Nodes Tesseractjs +14
AI & RAG

Generate AI viral videos with NanoBanana & VEO3, shared on socials via Blotato. Uses @blotato/n8n-nodes-blotato, googleSheets, lmChatOpenAi, toolThink. Event-driven trigger; 48 nodes.

@Blotato/N8N Nodes Blotato, Google Sheets, OpenAI Chat +8