AutomationFlowsAI & RAG › YouTube Video to Short Clips with AI & Airtable

YouTube Video to Short Clips with AI & Airtable

Original n8n title: Generate Short-form Clips From Youtube Videos with Gpt-4o, Grok & Airtable

ByJordan @jordan-ai-16 on n8n.io

This n8n template demonstrates how to automate YouTube content repurposing using AI. Upload a video to Google Drive and automatically generate transcriptions, A/B testable titles, AI thumbnails, short-form clips with captions, and YouTube descriptions with chapter timestamps.

Event trigger★★★★★ complexityAI-powered43 nodesAirtableGoogle Drive TriggerOpenAIHTTP RequestOpenRouter ChatChain LlmGoogle DriveYouTube
AI & RAG Trigger: Event Nodes: 43 Complexity: ★★★★★ AI nodes: yes Added:

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

This workflow follows the Airtable → Chainllm 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": "qQFa5Haojd7MRgNw",
  "name": "Repurpose YouTube videos to short-form clips with AI",
  "tags": [],
  "nodes": [
    {
      "id": "24509caf-c92d-4d79-98e9-ef73fcdb3dba",
      "name": "Create a record",
      "type": "n8n-nodes-base.airtable",
      "position": [
        1328,
        128
      ],
      "parameters": {
        "base": {
          "__rl": true,
          "mode": "list",
          "value": "appFGF4qoyqn50KOz",
          "cachedResultUrl": "https://airtable.com/appFGF4qoyqn50KOz",
          "cachedResultName": "Content Factory"
        },
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "tblUTxWrEJD5pUsV2",
          "cachedResultUrl": "https://airtable.com/appFGF4qoyqn50KOz/tblUTxWrEJD5pUsV2",
          "cachedResultName": "Table 1"
        },
        "columns": {
          "value": {
            "Video file name": "={{ $json.name }}",
            "Longform edited video": "={{ $json.webViewLink }}"
          },
          "schema": [
            {
              "id": "Video file name",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "Video file name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Longform edited video",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "Longform edited video",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Video summary",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "Video summary",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Reference image 1",
              "type": "array",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "Reference image 1",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Reference image 2",
              "type": "array",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "Reference image 2",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Reference image 3",
              "type": "array",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "Reference image 3",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Title 1",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "Title 1",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Title 2",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "Title 2",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Title 3",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "Title 3",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Thumbnail 1 prompt",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "Thumbnail 1 prompt",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Thumbnail 2 prompt",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "Thumbnail 2 prompt",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Thumbnail 3 prompt",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "Thumbnail 3 prompt",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Clips",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "Clips",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Calculation",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": true,
              "required": false,
              "displayName": "Calculation",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "create"
      },
      "credentials": {
        "airtableTokenApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "c8d179de-9ced-434a-9ba8-7049a0325f97",
      "name": "When video is added to drive folder",
      "type": "n8n-nodes-base.googleDriveTrigger",
      "position": [
        1136,
        128
      ],
      "parameters": {
        "event": "fileCreated",
        "options": {},
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        },
        "triggerOn": "specificFolder",
        "folderToWatch": {
          "__rl": true,
          "mode": "list",
          "value": "1Uv782L3VuaRi_T7vtTpLy3mieKiVYB2Q",
          "cachedResultUrl": "https://drive.google.com/drive/folders/1Uv782L3VuaRi_T7vtTpLy3mieKiVYB2Q",
          "cachedResultName": "Edited videos (pre upload)"
        }
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "96c9238b-fb77-4061-bf10-fe21fe18fde9",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        1600,
        128
      ],
      "parameters": {
        "path": "a03394e6-91e5-40a5-9104-98c025e14f69",
        "options": {}
      },
      "typeVersion": 2.1
    },
    {
      "id": "27f3d8ce-76cc-4dc4-bd44-caa283274c7f",
      "name": "Generate 3 titles",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        1968,
        128
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini",
          "cachedResultName": "GPT-4O-MINI"
        },
        "options": {
          "textFormat": {
            "textOptions": {
              "type": "json_schema",
              "schema": "{\n  \"type\": \"object\",\n  \"properties\": {\n    \"title_1\": {\n      \"type\": \"string\"\n    },\n    \"title_2\": {\n      \"type\": \"string\"\n    },\n    \"title_3\": {\n      \"type\": \"string\"\n    }\n  },\n  \"required\": [\"title_1\", \"title_2\", \"title_3\"],\n  \"additionalProperties\": false\n}"
            }
          }
        },
        "responses": {
          "values": [
            {
              "role": "system",
              "content": "=You are an expert YouTube title strategist specializing in (YOUR CONTENT NICHE HERE HAVE CLAUDE TAILOR THIS TO YOUR NICHE) Your job is to generate 3 high-performing title options based on proven 2025 YouTube title best practices and data-backed strategies.\n\n# CONTEXT\n- Niche: AI automation, n8n workflows, no-code automation, business process automation\n- Target Audience: Mix of (1) agency builders learning to sell AI automation, and (2) business owners needing automation solutions\n- Goal: Drive clicks (high CTR), rank in search, and funnel viewers to free Skool community\n\n# TITLE REQUIREMENTS\n\n## Length & Structure\n- 40-60 characters total (optimal for CTR and mobile display)\n- Front-load the most important keyword in the first 3-5 words\n- Avoid truncation - keep critical info visible before the \"...\"\n\n## Keyword Integration\n- Primary keyword MUST appear in the first half of the title\n- Use natural, human-readable phrasing (no keyword stuffing)\n- Include secondary/LSI keywords when relevant (e.g., \"workflow,\" \"automation,\" \"AI,\" \"n8n\")\n\n## Proven Title Formulas (Use These)\n1. **How-To Formula**: \"How to [Achieve Outcome] with [Tool/Method]\"\n   - Example: \"How to Automate Lead Gen with n8n (Step-by-Step)\"\n\n2. **Number-Based Formula**: \"[Number] Ways to [Benefit] Using [Tool]\"\n   - Example: \"5 n8n Workflows That Save 10 Hours/Week\"\n   - Note: Odd numbers (3, 5, 7) perform better than even\n\n3. **Outcome + Time Formula**: \"How I [Result] in [Timeframe] with [Method]\"\n   - Example: \"How I Built 20 Automations in 1 Week (n8n)\"\n\n4. **Problem/Solution Formula**: \"[Problem] \u274c \u2192 [Solution] \u2705\"\n   - Example: \"Manual Data Entry \u274c \u2192 AI Automation \u2705\"\n\n5. **Curiosity + Benefit Formula**: \"[Intriguing Hook] + [Clear Value]\"\n   - Example: \"This n8n Workflow Changed Everything (Free Template)\"\n\n6. **Bracket Enhancement**: Use [brackets] for context, updates, or bonuses\n   - Example: \"Build AI Chatbots in n8n [2025 Update + Free Template]\"\n\n## Power Words & Emotional Triggers\n**Include 1-2 of these in each title:**\n\n**Curiosity:** Secret, Hidden, Surprising, Breakthrough, Discovery\n**Authority:** Proven, Expert, Ultimate, Complete, Professional\n**Urgency:** Now, Fast, Quick, Instantly, Today, 2025\n**Value:** Free, Easy, Simple, Step-by-Step, Blueprint\n**Achievement:** Build, Create, Master, Automate, Scale\n**Specificity:** Exact, Specific, Real, Actual, True\n\n## Critical Rules\n\u2705 DO:\n- Start with the keyword your target audience is searching for\n- Use specific numbers and outcomes (\"Save 10 Hours\" not \"Save Time\")\n- Create curiosity while setting clear expectations\n- Match title to video content (no clickbait)\n- Include year (2025) for recency when relevant\n- Use parentheses or brackets for bonus context\n- Make the benefit crystal clear\n\n\u274c DON'T:\n- Use all caps or excessive emojis\n- Create misleading clickbait (kills watch time)\n- Bury the keyword at the end\n- Be vague (\"Cool Automation\" vs \"AI Lead Gen Automation\")\n- Exceed 60 characters\n- Use industry jargon that confuses beginners\n\n## Title Testing Strategy\nGenerate 3 variations that test different angles:\n- **Title 1**: SEO-focused (keyword-heavy, search-optimized)\n- **Title 2**: Curiosity-driven (emotional hook, benefit-focused)\n- **Title 3**: Hybrid (balances SEO + curiosity)\n\n# INPUT\nYou will receive a detailed video summary. Analyze it to:\n1. Identify the core problem being solved\n2. Extract the main tool/method being taught\n3. Determine the key outcome/benefit\n4. Note any specific numbers, timeframes, or results\n\n# OUTPUT FORMAT\nReturn ONLY the 3 titles in this exact format:\n\nTitle 1 (SEO-Focused): [title here]\nTitle 2 (Curiosity-Driven): [title here]\nTitle 3 (Hybrid): [title here]\n\n# EXAMPLES FOR n8n/AI AUTOMATION NICHE\n\nVideo Summary: \"Tutorial showing how to build an n8n workflow that automatically transcribes YouTube videos, generates summaries, creates 3 title options, and generates thumbnails using AI.\"\n\nOutput:\nTitle 1 (SEO-Focused): n8n AI Workflow: Auto-Generate YouTube Titles & Thumbnails\nTitle 2 (Curiosity-Driven): This AI Workflow Creates My YouTube Content (Save 5 Hours)\nTitle 3 (Hybrid): How to Automate YouTube Titles with n8n [Free Template]\n\n---\n\nVideo Summary: \"Building a complete RAG system in n8n that allows businesses to query their documents using AI, includes setup, testing, and deployment.\"\n\nOutput:\nTitle 1 (SEO-Focused): Build a RAG System in n8n (Complete AI Document Query Setup)\nTitle 2 (Curiosity-Driven): Turn Your PDFs Into an AI Assistant (n8n Workflow)\nTitle 3 (Hybrid): How I Built a $5K RAG System with n8n [Step-by-Step]"
            },
            {
              "content": "=# VIDEO SUMMARY\n\n{{ $json['Video summary'] }}\n\nGenerate 3 optimized YouTube title options for this AI automation/n8n tutorial video following the title framework provided in your system instructions."
            }
          ]
        },
        "builtInTools": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "fe601d09-7b4d-4119-a246-502dfb56bd1f",
      "name": "Add titles to record",
      "type": "n8n-nodes-base.airtable",
      "position": [
        2256,
        128
      ],
      "parameters": {
        "base": {
          "__rl": true,
          "mode": "list",
          "value": "appFGF4qoyqn50KOz",
          "cachedResultUrl": "https://airtable.com/appFGF4qoyqn50KOz",
          "cachedResultName": "Content Factory"
        },
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "tblUTxWrEJD5pUsV2",
          "cachedResultUrl": "https://airtable.com/appFGF4qoyqn50KOz/tblUTxWrEJD5pUsV2",
          "cachedResultName": "Table 1"
        },
        "columns": {
          "value": {
            "Title 1": "={{ $json.output[0].content[0].text.title_1 }}",
            "Title 2": "={{ $json.output[0].content[0].text.title_2 }}",
            "Title 3": "={{ $json.output[0].content[0].text.title_3 }}",
            "Calculation": "={{ $('Get a record').item.json.Calculation }}"
          },
          "schema": [
            {
              "id": "id",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": true,
              "required": false,
              "displayName": "id",
              "defaultMatch": true
            },
            {
              "id": "Video file name",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "Video file name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Longform edited video",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "Longform edited video",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Video summary",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "Video summary",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Reference image 1",
              "type": "array",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "Reference image 1",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Reference image 2",
              "type": "array",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "Reference image 2",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Reference image 3",
              "type": "array",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "Reference image 3",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Title 1",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "Title 1",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Title 2",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "Title 2",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Title 3",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "Title 3",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Thumbnail 1 prompt",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "Thumbnail 1 prompt",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Thumbnail 2 prompt",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "Thumbnail 2 prompt",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Thumbnail 3 prompt",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "Thumbnail 3 prompt",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Clips",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "Clips",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Calculation",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": true,
              "required": false,
              "displayName": "Calculation",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "Calculation"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update"
      },
      "credentials": {
        "airtableTokenApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "74a8d801-2d67-4ab0-a8c8-d9718c63f144",
      "name": "Webhook2",
      "type": "n8n-nodes-base.webhook",
      "position": [
        1104,
        448
      ],
      "parameters": {
        "path": "8bcc5357-97bc-4816-982d-fee8a591f66f",
        "options": {}
      },
      "typeVersion": 2.1
    },
    {
      "id": "db66fa8a-f872-42cb-8ded-6761b1317214",
      "name": "Get a record2",
      "type": "n8n-nodes-base.airtable",
      "position": [
        1280,
        448
      ],
      "parameters": {
        "id": "={{ $json.query.recordId }}",
        "base": {
          "__rl": true,
          "mode": "list",
          "value": "appFGF4qoyqn50KOz",
          "cachedResultUrl": "https://airtable.com/appFGF4qoyqn50KOz",
          "cachedResultName": "Content Factory"
        },
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "tblUTxWrEJD5pUsV2",
          "cachedResultUrl": "https://airtable.com/appFGF4qoyqn50KOz/tblUTxWrEJD5pUsV2",
          "cachedResultName": "Table 1"
        },
        "options": {}
      },
      "credentials": {
        "airtableTokenApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "ffcb2eb2-242c-4e44-85d2-51a8da1d66a2",
      "name": "Get image1",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1264,
        608
      ],
      "parameters": {
        "url": "https://api.kie.ai/api/v1/jobs/recordInfo",
        "options": {},
        "sendQuery": true,
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "queryParameters": {
          "parameters": [
            {
              "name": "taskId",
              "value": "={{ $json.data.taskId }}"
            }
          ]
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "eaa251c2-ff2c-46fa-a167-655a4af50e22",
      "name": "Extract from File5",
      "type": "n8n-nodes-base.extractFromFile",
      "position": [
        1856,
        592
      ],
      "parameters": {
        "options": {},
        "operation": "binaryToPropery"
      },
      "typeVersion": 1.1
    },
    {
      "id": "27f66737-cfea-47cd-b923-ee18e5767a5e",
      "name": "Wait10",
      "type": "n8n-nodes-base.wait",
      "position": [
        1664,
        752
      ],
      "parameters": {},
      "typeVersion": 1.1
    },
    {
      "id": "19369361-63fd-4d1e-965f-230b8bc9630e",
      "name": "Switch4",
      "type": "n8n-nodes-base.switch",
      "position": [
        1488,
        608
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "31ada6d9-ba49-44fe-9897-4349a16154e0",
                    "operator": {
                      "type": "string",
                      "operation": "notEmpty",
                      "singleValue": true
                    },
                    "leftValue": "={{ $json.data.resultJson }}",
                    "rightValue": 200
                  }
                ]
              }
            },
            {
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "a14c7d84-31f9-4358-8815-746f806b58b7",
                    "operator": {
                      "type": "string",
                      "operation": "empty",
                      "singleValue": true
                    },
                    "leftValue": "={{ $json.data.resultJson }}",
                    "rightValue": 501
                  }
                ]
              }
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3.3
    },
    {
      "id": "589d76e7-2e56-4167-bb26-14cd56d64cd7",
      "name": "Download image",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1680,
        592
      ],
      "parameters": {
        "url": "={{ JSON.parse($json.data.resultJson).resultUrls[0] }}",
        "options": {}
      },
      "typeVersion": 4.3
    },
    {
      "id": "6d37ca11-09fa-453c-bc88-59d9e3c74812",
      "name": "Code in JavaScript",
      "type": "n8n-nodes-base.code",
      "position": [
        1952,
        448
      ],
      "parameters": {
        "jsCode": "// Get all items from previous node\nconst items = $input.all();\n\n// Get the prompt\nlet prompt = items[0].json.thumbnailPrompt;\n\n// Check if prompt exists\nif (!prompt) {\n  throw new Error('thumbnailPrompt is empty or undefined');\n}\n\n// Remove leading and trailing quotes if present\nif (prompt.startsWith('\"') && prompt.endsWith('\"')) {\n  prompt = prompt.slice(1, -1);\n}\n\n// Clean up the prompt\nprompt = prompt\n  .replace(/\\n/g, ' ')\n  .replace(/\\r/g, ' ')\n  .replace(/\\s+/g, ' ')\n  .replace(/\\\\\"/g, '\"')\n  .trim();\n\n// Get image URLs from Airtable\nconst airtableData = $('Get a record2').first().json;\n\n// Try both possible field names\nconst image1 = airtableData[\"Reference image 1\"]?.[0]?.url || airtableData[\"Thumbnail reference 1\"]?.[0]?.url;\nconst image2 = airtableData[\"Reference image 2\"]?.[0]?.url || airtableData[\"Thumbnail reference 2\"]?.[0]?.url;\n\n// Debug: Log what we found\nconsole.log('Airtable fields:', Object.keys(airtableData));\nconsole.log('Image1:', image1);\nconsole.log('Image2:', image2);\n\n// Check if images were found\nif (!image1 || !image2) {\n  throw new Error(`Missing images. Image1: ${!!image1}, Image2: ${!!image2}. Available fields: ${Object.keys(airtableData).join(', ')}`);\n}\n\n// Build the JSON body with only 2 images\nconst bodyRaw = JSON.stringify({\n  model: \"nano-banana-pro\",\n  callBackUrl: $execution.resumeUrl,\n  input: {\n    prompt: prompt,\n    image_input: [image1, image2],\n    aspect_ratio: \"16:9\",\n    resolution: \"1K\",\n    output_format: \"png\"\n  }\n});\n\n// Return the stringified JSON\nreturn [{\n  json: {\n    bodyRaw: bodyRaw\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "f9da1276-52fa-4232-be1f-71aa8a47d8f9",
      "name": "Thumbnail prompt optimizer",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        1440,
        448
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-5-mini",
          "cachedResultName": "GPT-5-MINI"
        },
        "options": {},
        "responses": {
          "values": [
            {
              "role": "system",
              "content": "=You are an expert at optimizing image generation prompts for Nano Banana Pro to create high-performing YouTube thumbnails.\n\n# YOUR TASK\n\nThe user provides a rough thumbnail idea. You optimize it into a single-paragraph Nano Banana Pro prompt that:\n1. Keeps their core concept\n2. Adds missing YouTube thumbnail essentials (text, lighting, effects, colors)\n3. Makes it visually appealing and high-converting\n4. Uses 2 reference images (Image 1 and Image 2)\n\n# YOUTUBE THUMBNAIL ESSENTIALS TO ADD\n\n**Text Overlay (add if missing):**\n- 1-3 words maximum\n- Bold Impact or sans-serif font\n- High contrast (white with colored glow, or bright yellow/orange)\n- Top center or top-left placement\n- Example words: \"AI Tool\", \"Watch This\", \"Free Method\", \"Secret Trick\"\n\n**Visual Effects:**\n- Glows on key elements (cyan, orange, neon green)\n- Rim lighting on people\n- Drop shadows for depth\n- High contrast colors\n- Blur background, sharp foreground\n\n**Colors:**\n- Vibrant, saturated colors (electric blue, neon green, orange, yellow)\n- Deep backgrounds (purple, navy, black gradients)\n- Avoid red/black/white (blends with YouTube)\n\n**Composition:**\n- Clear foreground/background separation\n- Mobile-optimized (70% watch on phones)\n- Face visible if person included\n- Rule of thirds\n\n# REFERENCE IMAGES\n\nUser will provide 2 images:\n- **Image 1**: Usually the person/creator\n- **Image 2**: Usually workflow/screenshot/content\n\n# CRITICAL RULES\n\n\u2705 DO:\n- Output ONLY the prompt (one paragraph)\n- Preserve user's core idea\n- Add text overlay if missing\n- Add lighting, glows, effects\n- Specify 16:9, high resolution, mobile-optimized\n- Use natural, flowing language\n\n\u274c DON'T:\n- Add preamble or analysis\n- Change their creative vision\n- Use section headers or labels\n- Reference \"Image 3\" (only 2 images available)\n- Explain your reasoning\n\n# EXAMPLES\n\n**Input:** \"workflow as background, me on the left\"\n\n**Output:** \"Create a 16:9 high-resolution YouTube thumbnail using the two provided reference images. Use Image 2 (workflow screenshot) as the full-width background, applying a strong Gaussian blur and deep purple to navy gradient overlay (#2D1B69 to #071029, 40% opacity) to create depth while keeping workflow elements recognizable. Extract and position Image 1 (person) as a clean cutout on the left third of frame with background removed, add dramatic cyan-tinted rim lighting on the edges and a soft drop shadow beneath for separation. Apply vibrant cyan glows (#00D9FF) to key workflow nodes and orange accents (#FF6B35) to connection lines in the blurred background. Place bold text 'AI WORKFLOW' in extra-large white Impact font at top center with bright orange outer glow (20px blur) and thin black stroke for maximum mobile readability. Ensure high contrast, sharp details on person, cinematic color grading, and professional YouTube thumbnail aesthetic optimized for small screens.\"\n\n**Input:** \"AI creating videos, phone showing result\"\n\n**Output:** \"Create a vibrant 16:9 YouTube thumbnail composition using the two reference images. Center Image 2 (phone/screen showing AI-generated video) as the dominant element angled toward viewer, with high saturation and contrast on the displayed content. Extract Image 1 (person) with background removed and place as a circular or angled cutout in the left or bottom corner at 30% size with neon green border (#00FF00) and drop shadow. Add electric blue background (#0080FF) with neon green and bright yellow accent elements suggesting AI processing or data flow. Apply screen glare effect on phone, cyan and magenta light rays emanating from screen, and dramatic lighting. Place bold text 'FREE AI' at top-left in extra-large bright yellow font (#FFFF00) with neon green glow for maximum visibility. Ensure eye-catching colors, high contrast, sharp phone details, cinematic lighting, and mobile-optimized composition with modern tech YouTube aesthetic.\"\n\n# OUTPUT FORMAT\n\nReturn ONLY the optimized prompt. No analysis, no preamble, no explanation. Just the prompt as one flowing paragraph ready to send to Nano Banana Pro."
            },
            {
              "content": "=Convert this YouTube thumbnail concept into an optimized Nano Banana Pro image generation prompt:\n{{ $json[\"Thumbnail prompt\"] }}"
            }
          ]
        },
        "builtInTools": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "0c951080-8528-461a-a29b-a5432b56611c",
      "name": "clean up prompt",
      "type": "n8n-nodes-base.set",
      "position": [
        1760,
        448
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "280ce518-be14-4bba-afa1-64e8e042a8f3",
              "name": "thumbnailPrompt",
              "type": "string",
              "value": "={{ JSON.stringify($json.output[0].content[0].text.replace(/\\n/g, ' ').replace(/\\r/g, ' ').replace(/\\s+/g, ' ').trim()) }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "21b60b2b-d25a-44c4-ba8b-e335bd43d1c7",
      "name": "Create thumbnail",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2112,
        448
      ],
      "parameters": {
        "url": "https://api.kie.ai/api/v1/jobs/createTask",
        "method": "POST",
        "options": {},
        "jsonBody": "={{ $json.bodyRaw }}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "e96cc769-2161-4007-bea8-17b31431a1cc",
      "name": "Add thumbnail to airtable",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2032,
        592
      ],
      "parameters": {
        "url": "=https://content.airtable.com/v0/YOUR_BASE_ID/{{ $('Get a record2').item.json.id }}/Thumbnail/uploadAttachment",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"contentType\": \"image/png\",\n  \"file\": \"{{ $json.data }}\",\n  \"filename\": \"generated_image.png\"\n}\n",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "airtableTokenApi"
      },
      "credentials": {
        "airtableApi": {
          "name": "<your credential>"
        },
        "airtableTokenApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "9714391f-af38-40ca-bf43-0a73bf7aca2a",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1056,
        0
      ],
      "parameters": {
        "width": 480,
        "height": 304,
        "content": "## When edited video is added to google drive folder create the record with our video in airtable"
      },
      "typeVersion": 1
    },
    {
      "id": "f3c1d119-4824-41f8-ba73-e394e959115a",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1536,
        0
      ],
      "parameters": {
        "color": 2,
        "width": 1072,
        "height": 304,
        "content": "## When Video summary is added this system is triggered to then generate 3 optimized titles to A/B test based on the video summary"
      },
      "typeVersion": 1
    },
    {
      "id": "0bdd2e76-0ace-4228-b034-26ba9dfb8c37",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1056,
        304
      ],
      "parameters": {
        "color": 3,
        "width": 1552,
        "height": 656,
        "content": "## This system is manually triggered once you want to generate the thumbnail based on the idea you typed in the airtable \"thumbnail idea\" field. This system then sends that idea into our image prompt optimizer that then sends the image prompt to kie.ai to access nano banana pro"
      },
      "typeVersion": 1
    },
    {
      "id": "5c7940bb-ffdc-41e2-9b40-0a256feb431f",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        0,
        0
      ],
      "parameters": {
        "color": 7,
        "width": 1072,
        "height": 2304,
        "content": "# \ud83c\udfac AI REPURPOSING SYSTEM (READ THIS FIRST)\n\n# Created by: [Jordan Austin](https://www.skool.com/ai-growth-lab-4394/about?ref=5065ab28874b4325b44ef3ead8105722)\n\n# \ud83d\udca1 System Overview\n## This is a **fully automated YouTube content processing pipeline**. Upload a video to Google Drive and it automatically transcribes, generates 3 A/B-testable titles, creates an AI thumbnail with your reference style, identifies 3-8 elite clips with captions, and writes a YouTube description with chapters. Processing time: ~10-15 minutes per video.\n\n# Automated Steps:\n## * **Transcription:** Uses via Apify to transcribe with H:MM:SS.mmm timestamps.\n## * **Title Generation:** Creates 3 title variations for A/B testing using GPT-4o-mini.\n## * **Thumbnail Creation:** Generates photorealistic thumbnail with 2 reference images via Kie.ai Nano Banana Pro.\n## * **Clip Identification:** Uses Grok 4.1 Fast to find 3-8 elite clips (45+ seconds) with action-oriented captions and timestamps.\n## * **Description Generation:** Creates YouTube description with chapter timestamps.\n## * **Database Storage:** Saves all outputs to Airtable for easy access and workflow management.\n\n# \u2699\ufe0f Critical Setup & Configuration\n## * **Estimated Setup Time:** ~15-20 minutes.\n## * **Webhook Setup:** After activating workflow, copy Webhook URLs from Webhook1 and Webhook2 nodes and place into your Airtable button formulas and the 2 airtable automations\n## * **Make sure you look through the prompts where it says (HVE CLAUDE TAILOR THIS TO YOUR NICHE) and paste the prompt into claude telling it to not change the prompt but just to tailor it to what you make content about\n## * **Towards the end of the video I show you an error that we ran into and how to fix them. Instead of uploading the video to private we upload it as unlisted so that way we can access the video.\n## * **Another thing we added was a video id field into airtable which is required to paste in before you check the box saying the video was uploaded to youtube which then triggers the clip generator and description genrator\n\n# \u26a0\ufe0f Mandatory Steps (Do This First!)\n## 1. **Duplicate Airtable Base:** Copy the base structure into your account (buttons and fields are pre-configured).\n   ## * [AIRTABLE BASE](https://airtable.com/appGXKQcCn8bf8wyq/shrIf6F9GfnYZNp79)\n## 2. **Update Webhook URLs:** After activating the workflow in n8n:\n   ## * Copy Production URL from **Webhook2** node \u2192 Paste into \"Generate thumbnail\" button formula\n   ## * Update `YOUR_WEBHOOK_URL` in both Airtable automations \n## 3. **Credential Setup:** Connect your accounts for **every service** listed below via the Credentials panel.\n## 4. **Create drive folder** You need to create a drive folder that you can put your edited video into so the system can trigger\n## 5. **Anywhere that says YOUR_API in a node you need to paste in your API key (check the apify node)\n## 6. **In the add thumbnail to airtable node you need to add in your airtable base ID where it says YOUR_BASE_ID \n\n# \ud83d\udd11 Required Services (APIs & Credentials)\n## * [AIRTABLE](https://docs.n8n.io/integrations/builtin/credentials/airtable/?utm_source=n8n_app&utm_medium=credential_settings&utm_campaign=create_new_credentials_modal) - For database storage and workflow triggers.\n## * [GOOGLE DRIVE](https://docs.n8n.io/integrations/builtin/credentials/google/?utm_source=n8n_app&utm_medium=credential_settings&utm_campaign=create_new_credentials_modal) - For video upload monitoring.\n## * [APIFY](https://docs.apify.com/platform/integrations/api) - For video transcription via AssemblyAI actor.\n## * [OPENAI](https://docs.n8n.io/integrations/builtin/credentials/openai/?utm_source=n8n_app&utm_medium=credential_settings&utm_campaign=create_new_credentials_modal) - For title/description generation (GPT-4o-mini).\n## * [OPENROUTER](https://docs.n8n.io/integrations/builtin/credentials/openrouter/?utm_source=n8n_app&utm_medium=credential_settings&utm_campaign=create_new_credentials_modal) - For clip identification (Grok 4.1 Fast).\n## * Kie.ai\n## * [GOOGLE API SETUP VIDEO](https://youtube.com/shorts/FBRQNmCN0F8?feature=share)"
      },
      "typeVersion": 1
    },
    {
      "id": "5be766c2-2ffe-4179-976d-b9e529fd93cd",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2624,
        -160
      ],
      "parameters": {
        "color": 6,
        "width": 1936,
        "height": 1104,
        "content": "@[Youtube](EEBaCA3XvUs)"
      },
      "typeVersion": 1
    },
    {
      "id": "00d5b7e4-b911-4f62-88b0-0c4cf4da6a8c",
      "name": "Get a record",
      "type": "n8n-nodes-base.airtable",
      "position": [
        1792,
        128
      ],
      "parameters": {
        "id": "={{ $json.query.recordId }}",
        "base": {
          "__rl": true,
          "mode": "list",
          "value": "appFGF4qoyqn50KOz",
          "cachedResultUrl": "https://airtable.com/appFGF4qoyqn50KOz",
          "cachedResultName": "Content Factory"
        },
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "tblUTxWrEJD5pUsV2",
          "cachedResultUrl": "https://airtable.com/appFGF4qoyqn50KOz/tblUTxWrEJD5pUsV2",
          "cachedResultName": "Table 1"
        },
        "options": {}
      },
      "credentials": {
        "airtableTokenApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "6c504471-38fc-496f-bd1f-2d4d31f7f48a",
      "name": "Wait 2 mins",
      "type": "n8n-nodes-base.wait",
      "position": [
        1104,
        608
      ],
      "parameters": {
        "unit": "minutes",
        "amount": 2
      },
      "typeVersion": 1.1
    },
    {
      "id": "5668f6df-1609-4d89-8210-6d37c8c73879",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1344,
        1984
      ],
      "parameters": {
        "width": 1056,
        "height": 1392,
        "content": "# \u26a0\ufe0f YouTube Captions Polling Loop (Not in Video)\n\n## Why This Wasn't in the Original Video\nWhen I recorded the tutorial, I was testing with videos that already had captions available. I didn't realize YouTube takes 10-60 minutes AFTER upload to generate auto-captions.\n\n## **The Problem:** If you click \"Generate clips\" immediately after upload, there's no transcript available yet.\n\n## **The Solution:** When you click \"Generate clips,\" these 3 nodes automatically poll YouTube's API every 5 minutes until captions are ready, then the workflow continues to clip identification automatically.\n\n---\n\n## What These Nodes Do\n\n### **Node 1: Check YouTube Captions API**\n- Calls `captions.list` endpoint to check if auto-generated captions exist\n- Returns empty array if not ready, or caption data if ready\n\n### **Node 2: IF - Captions Ready?**\n- Checks if `items.length > 0`\n- **TRUE** \u2192 Captions ready, continue to clip identification\n- **FALSE** \u2192 Not ready, loop back to wait node\n\n### **Node 3: Wait 5 Minutes**\n- Pauses workflow for 5 minutes before checking again\n- Prevents API rate limiting\n\n---\n\n## How It Works\n\n## 1. Click \"Generate clips\" button in Airtable\n## 2. Workflow checks YouTube: Are captions ready?\n  ### - **YES** \u2192 Proceed to clip identification (rest of workflow)\n  ### - **NO** \u2192 Wait 5 minutes, check again\n## 3. Automatically continues when captions are available\n\n## **No manual checking required - the workflow handles everything automatically.**\n\n---\n\n## **Added:** December 9, 2025  \n## **Why:** Discovered caption processing delay when testing with freshly uploaded video"
      },
      "typeVersion": 1
    },
    {
      "id": "b3f31b8f-4398-4d8d-9f49-2c86ee7045f4",
      "name": "Wait 5 mins",
      "type": "n8n-nodes-base.wait",
      "position": [
        1952,
        1712
      ],
      "parameters": {
        "unit": "minutes"
      },
      "typeVersion": 1.1
    },
    {
      "id": "3f6e0d99-9626-4672-acba-46f9c710535e",
      "name": "Check to see if transcript is ready",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1600,
        1680
      ],
      "parameters": {
        "url": "https://www.googleapis.com/youtube/v3/captions",
        "options": {},
        "sendQuery": true,
        "sendHeaders": true,
        "authentication": "predefinedCredentialType",
        "queryParameters": {
          "parameters": [
            {
              "name": "videoId",
              "value": "={{ $json.id }}"
            },
            {
              "name": "part",
              "value": "=snippet"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "Accept",
              "value": "application/json"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "nodeCredentialType": "youTubeOAuth2Api"
      },
      "credentials": {
        "youTubeOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "3ebe53cb-429d-49cd-9743-06a98c9c8a41",
      "name": "Is transcript ready?",
      "type": "n8n-nodes-base.switch",
      "position": [
        1792,
        1680
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "97ef1f9c-2247-4517-9f18-568d5986a182",
                    "operator": {
                      "type": "boolean",
                      "operation": "true",
                      "singleValue": true
                    },
                    "leftValue": "={{ $json.items.length > 0 }}",
                    "rightValue": ""
                  }
                ]
              }
            },
            {
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "7e5309db-9776-43d0-8cac-0e053d5deb35",
                    "operator": {
                      "type": "boolean",
                      "operation": "false",
                      "singleValue": true
                    },
                    "leftValue": "={{ $json.items.length > 0 }}",
                    "rightValue": ""
                  }
                ]
              }
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3.3
    },
    {
      "id": "c4a06c00-5ea9-4a6a-a103-32fd503c0275",
      "name": "Webhook3",
      "type": "n8n-nodes-base.webhook",
      "position": [
        1088,
        1296
      ],
      "parameters": {
        "path": "5df46517-cec1-4563-93f3-dc51948f3551",
        "options": {}
      },
      "typeVersion": 2.1
    },
    {
      "id": "d1ff3fab-12c8-4705-8755-1705afe71477",
      "name": "Get a record4",
      "type": "n8n-nodes-base.airtable",
      "position": [
        1232,
        1296
      ],
      "parameters": {
        "id": "={{ $json.query.recordId }}",
        "base": {
          "__rl": true,
          "mode": "list",
          "value": "appFGF4qoyqn50KOz",
          "cachedResultUrl": "https://airtable.com/appFGF4qoyqn50KOz",
          "cachedResultName": "Content Factory"
        },
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "tblUTxWrEJD5pUsV2",
          "cachedResultUrl": "https://airtable.com/appFGF4qoyqn50KOz/tblUTxWrEJD5pUsV2",
          "cachedResultName": "Table 1"
        },
        "options": {}
      },
      "credentials": {
        "airtableTokenApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "63e5a59d-fe0a-4c9c-a99c-1cf2019c3ab3",
      "name": " Get transcript from video1",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2000,
        1280
      ],
      "parameters": {
        "url": "https://api.apify.com/v2/acts/pintostudio~youtube-transcript-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN_HERE",
        "method": "POST",
        "options": {
          "redirect": {
            "redirect": {}
          }
        },
        "jsonBody": "={\n    \"videoUrl\": \"https://www.youtube.com/watch?v={{ $('Get a video1').item.json.id }}\"\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "Accept",
              "value": "application/json"
            },
            {
              "name": "Authorization",
              "value": "Bearer YOUR_TOKEN_HERE"
            }
          ]
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "730508c3-d6a9-486b-bb5a-06b401729bfa",
      "name": "Formatt transcript1",
      "type": "n8n-nodes-base.code",
      "position": [
        2208,
        1280
      ],
      "parameters": {
        "jsCode": "// Get the transcript array from Apify\nconst transcriptData = $json.data;\n\n// Check if it's an array\nif (!Array.isArray(transcriptData)) {\n  throw new Error(\"Transcript data is not an array\");\n}\n\n// Convert seconds to HH:MM:SS.mmm format\nfunction formatTimestamp(seconds) {\n  const totalSeconds = parseFloat(seconds);\n  const hrs = Math.floor(totalSeconds / 3600);\n  const mins = Math.floor((totalSeconds % 3600) / 60);\n  const secs = Math.floor(totalSeconds % 60);\n  const ms = Math.floor((totalSeconds % 1) * 1000);\n  \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// Build clean, readable transcript\nlet cleanTranscript = \"\";\n\nfor (let i = 0; i < transcriptData.length; i++) {\n  const item = transcriptData[i];\n  if (item.text && item.text.trim()) {\n    cleanTranscript += formatTimestamp(item.start) + \" - \" + item.text.trim() + \"\\n\\n\";\n  }\n}\n\n// Return formatted transcript\nreturn {\n  json: {\n    Transcript: cleanTranscript.trim()\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "d520640d-adb4-438b-b5e4-c55d526e6506",
      "name": " Description agent1",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        2464,
        1392
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-5-mini",
          "cachedResultName": "GPT-5-MINI"
        },
        "options": {},
        "responses": {
          "values": [
            {
              "role": "system",
              "content": "=You are a YouTube description generator. Your job is to take a template and fill in the chapter timestamps based on the video transcript.\n\n# YOUR TASK\n\nFill in the YouTube description template with properly formatted chapter timestamps. Keep ALL other text in the template EXACTLY as provided.\n\n# TIMESTAMP REQUIREMENTS\n\n## Format Rules\n- Use MM:SS format for videos under 1 hour (example: 05:34)\n- Use HH:MM:SS format for videos over 1 hour (example: 1:05:34)\n- MUST start with 00:00 (YouTube requirement)\n- NO milliseconds (00:00:00.000 is WRONG)\n- Format must be EXACT: MM:SS or HH:MM:SS with leading zeros\n\n## Chapter Title Requirements\n- Keep titles clear and descriptive (5-10 words max)\n- Use title case (capitalize first letter of major words)\n- Be specific about what happens in that section\n- Make it scannable and valuable to viewers\n\nGOOD CHAPTER TITLES:\n\u2705 \"Introduction: What We're Building Today\"\n\u2705 \"Setting Up the n8n Webhook Trigger\"\n\u2705 \"Configuring the HTTP Request Node\"\n\u2705 \"Testing the Complete Workflow\"\n\u2705 \"Outro & Free Template Download\"\n\nBAD CHAPTER TITLES:\n\u274c \"Intro\" (too vague)\n\u274c \"Node breakdown starts here\" (not descriptive)\n\u274c \"Next part\" (doesn't tell viewer anything)\n\n## Chapter Placement Strategy\n- First chapter MUST be at 00:00\n- Create chapters at natural section breaks (every 2-5 minutes ideal)\n- Aim for 5-15 chapters total depending on video length\n- Don't create chapters for segments under 30 seconds\n- Align chapters with when new topics/steps begin\n\n# OUTPUT RULES\n\n- Return ONLY the completed description template\n- Do NOT add any preamble like \"Here's the description:\" or explanations\n- Do NOT add markdown formatting (no code blocks)\n- Keep ALL original text from the template unchanged\n- ONLY replace the [TIMESTAMPS SECTION] placeholder with generated timestamps\n- The output should be ready to copy/paste directly into YouTube"
            },
            {
              "content": "=Fill in this YouTube description template with chapter timestamps based on the transcript.\n\n**Template:**\n\n[VIDEO TITLE RESTATED WITH KEYWORDS]\nLearn how to [MAIN BENEFIT] using [TOOLS MENTIONED]. In this tutorial, I'll show you [KEY TAKEAWAY 1], [KEY TAKEAWAY 2], and [KEY TAKEAWAY 3].\n\n\ud83d\udc65 Join My Free Skool Community: https://www.skool.com/ai-growth-lab-4394/about?ref=5065ab28874b4325b44ef3ead8105722\n\nGet the full n8n template, Airtable base, and exclusive AI automation resources.\n\n\ud83e\udd16 Need Custom AI Solutions? Work with me: https://zangflow.com\n\n---\n\n\u23f1\ufe0f TIMESTAMPS\n00:00 - Introduction: What We're Building\n[AUTO-GENERATED TIMESTAMPS WITH DESCRIPTIVE TITLES]\n\n---\n\n\ud83d\udc47 TOOLS & RESOURCES\n\n\ud83d\ude80 Cold Email Engine (Instantly.ai): https://instantly.ai/?via=jordan-austin\n\ud83e\udd16 n8n Automation Platform: https://n8n.partnerlinks.io/77ys2bwb9k9c\n\n---\n\n\ud83d\udca1 Don't forget to like, subscribe, and turn on notifications for weekly AI automation tutorials, n8n workflows, and no-code AI agent builds!\n\n\n**Video Title:** {{ $('Get a record4').item.json['Title 1'] }}\n\n**Video Summary:** {{ $('Get a record4').item.json['Video summary'] }}\n\n**Full Transcript with Timestamps:**\n{{ $json[\"Transcript\"] }}\n\nReturn ONLY the completed description template ready to paste into YouTube. No preamble, no explanation, no markdown formatting.\n\nDO NOT CHANGE ANY OF THE LINKS "
            }
          ]
        },
        "builtInTools": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "1babfed9-c0de-42a3-8a73-e7bb9cb942c3",
      "name": "OpenRouter Chat Model1",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
      "position": [
        2304,
        1136
      ],
      "parameters": {
        "model": "x-ai/grok-4.1-fast",
        "options": {}
      },
      "credentials": {
        "openRouterApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "cafddad4-37af-481f-8c96-284c12c55ce3",
      "name": "Key value pair clips",
      "type": "n8n-nodes-base.code",
      "position": [
        2704,
        1184
      ],
      "parameters": {
        "jsCode": "// Get the AI response\nconst items = $input.all();\n\n// Handle different possible structures\nlet rawOutput;\nif (items[0].json.output) {\n  // Anthropic/Claude structure\n  rawOutput = items[0].json.output[0].content[0].text;\n} else if (items[0].json.text) {\n  // Direct text field\n  rawOutput = items[0].json.text;\n} else if (items[0].json.choices) {\n  // OpenAI structure\n  rawOutput = items[0].json.choices[0].message.content;\n} else {\n  // Fallback - try to stringify and parse\n  rawOutput = JSON.stringify(items[0].json);\n}\n\n// Remove markdown code fences if present\nrawOutput = rawOutput\n  .replace(/```json\\s*/g, '')  // Remove ```json\n  .replace(/```\\s*/g, '')       // Remove closing ```\n  .trim();\n\n// Parse the JSON string\nconst clips = JSON.parse(rawOutput);\n\n// Return each clip as a separate item for Airtable\nreturn clips.map(clip => ({\n  json: clip\n}));"
      },
      "typeVersion": 2
    },
    {
      "id": "edb586a1-2d56-46e0-be62-20d4e3cfd9c9",
      "name": "cleanly formatt clips",
      "type": "n8n-nodes-base.code",
      "position": [
        2880,
        1184
      ],
      "parameters": {
        "jsCode": "// Get the input\nconst items = $input.all();\n\n// The input is already an array of clips\nconst clips = items.map(item => item.json);\n\n// Format each clip as readable text\nconst formattedClips = clips.map(clip => {\n  return `CLIP ${clip.clip_number}\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\ud83d\udccd Start: ${clip.start_timestamp}\n\ud83d\udccd End: ${clip.end_timestamp}\n\ud83d\udccd CTA Start: ${clip.cta_start_timestamp}\n\ud83d\udccd CTA End: ${clip.cta_end_timestamp}\n\n\ud83d\udcfa Title: ${clip.youtube_title}\n\n\ud83d\udcdd Caption:\n${clip.caption}\n`;\n}).join('\\n\\n');\n\n// Create summary\nconst summary = `\ud83c\udfac TOTAL CLIPS IDENTIFIED: ${clips.length}\n\n${formattedClips}`;\n\n// Return just what you need\nreturn [{\n  json: {\n    clips_formatted: summary\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "bcd6de1c-caa4-415c-8f99-f79bee7d5915",
      "name": "Update record",
      "type": "n8n-nodes-base.airtable",
      "position": [
        3024,
        1184
      ],
      "parameters": {
        "base": {
          "__rl": true,
          "mode": "list",
          "value": "appFGF4qoyqn50KOz",
          "cachedResultUrl": "https://airtable.com/appFGF4qoyqn50KOz",
          "cachedResultName": "Content Factory"
        },
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "tblUTxWrEJD5pUsV2",
          "cachedResultUrl": "https://airtable.com/appFGF4qoyqn50KOz/tblUTxWrEJD5pUsV2",
          "cachedResultName": "Table 1"
        },
        "columns": {
          "value": {
            "Clips": "={{ $json.clips_formatted }}",
            "Select": "Complete",
            "Calculation": "={{ $('Get a record4').first().json.Calculation }}"
          },
          "schema": [
            {
              "id": "id",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": true,
              "required": false,
              "displayName": "id",
              "defaultMatch": true
            },
            {
              "id": "Video file name",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "Video file name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Select",
              "type": "options",
              "display": true,
              "options": [
                {
                  "name": "In progress",
                  "value": "In progress"
                },
                {
                  "name": "Complete",
                  "value": "Complete"
                }
              ],
              "removed": false,
              "readOnly": false,
              "required": false,
     

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

This n8n template demonstrates how to automate YouTube content repurposing using AI. Upload a video to Google Drive and automatically generate transcriptions, A/B testable titles, AI thumbnails, short-form clips with captions, and YouTube descriptions with chapter timestamps.

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

This workflow automates the creation, rendering, approval, and posting of TikTok-style POV (Point of View) videos to Instagram, with cross-posting to Facebook and YouTube. It eliminates manual video p

OpenAI Chat, Output Parser Item List, HTTP Request +10
AI & RAG

(from just and image to complete Shopify product page.)

Airtable, HTTP Request, Google Drive +6
AI & RAG

This workflow turns a Google Drive folder into a fully automated YouTube publishing pipeline. Whenever a new video file is added to the folder, the workflow generates all YouTube metadata using AI, up

Google Drive, Google Drive Trigger, OpenAI +5
AI & RAG

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

Google Drive Trigger, Google Drive, OpenAI Chat +4
AI & RAG

YT New Video Upload. Uses googleDrive, googleDriveTrigger, openAi, lmChatGoogleGemini. Event-driven trigger; 14 nodes.

Google Drive, Google Drive Trigger, OpenAI +4