
YouTube Video Summary to Discord with GPT-4o, Slack Approval, and Google Sheets
Description
Categories
🤖 AI & Machine Learning📢 Marketing
Nodes Used
n8n-nodes-base.coden8n-nodes-base.slackn8n-nodes-base.discordn8n-nodes-base.stickyNoten8n-nodes-base.stickyNoten8n-nodes-base.stickyNoten8n-nodes-base.stickyNoten8n-nodes-base.stickyNoten8n-nodes-base.stickyNoten8n-nodes-base.stickyNote
PriceFree
Views0
Last Updated11/28/2025
workflow.json
{
"meta": {
"instanceId": "5aaf4236c70e34e423fbdb2c7b754d19253a933bb1476d548f75848a01e473cf",
"templateCredsSetupCompleted": true
},
"nodes": [
{
"id": "8a2b5bef-97b5-4fb9-933c-3bdf48c72bea",
"name": "YouTube RSS Trigger",
"type": "n8n-nodes-base.rssFeedReadTrigger",
"position": [
-1240,
460
],
"parameters": {
"feedUrl": "https://www.youtube.com/feeds/videos.xml?channel_id=UCf3dc-Y3k5vBTCVpPCAfG6g",
"pollTimes": {
"item": [
{}
]
}
},
"typeVersion": 1
},
{
"id": "bf9d4831-e6ea-4bb4-a4e8-e4f7708a049c",
"name": "Extract Channel ID",
"type": "n8n-nodes-base.code",
"position": [
-1020,
460
],
"parameters": {
"jsCode": "// 'items' is already defined in n8n and contains incoming data\n\nreturn items.map(item => {\n const link = item.json.link; // e.g., \"https://www.youtube.com/watch?v=Y0DYmRnfHlc\"\n const videoId = link.split(\"v=\")[1].split(\"&\")[0];\n return {\n json: {\n videoId,\n },\n };\n});\n"
},
"typeVersion": 2
},
{
"id": "34208ab9-a3ba-4226-942a-33024118b8bc",
"name": "Fetch Video Details",
"type": "n8n-nodes-base.httpRequest",
"position": [
-640,
460
],
"parameters": {
"url": "https://www.googleapis.com/youtube/v3/videos",
"options": {},
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "part",
"value": "snippet"
},
{
"name": "id",
"value": "={{ $json.videoId }}"
},
{
"name": "key",
"value": "YOUR-API_KEY"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "8d210fe5-1278-409f-8176-3a313c1adc5d",
"name": "Summarize Agent",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
-220,
460
],
"parameters": {
"text": "=Title: {{ $json.items[0].snippet.title }}\nDescription: {{ $json.items[0].snippet.description }}",
"options": {
"systemMessage": "You are a YouTube video summarizer. If the description is not available just tell that it is not available. Summarize the following video description"
},
"promptType": "define"
},
"typeVersion": 1.9
},
{
"id": "472ebda0-35fb-4aa8-8bb8-96fcf7e3eca1",
"name": "OpenAI GPT Summary Model",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
-260,
680
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4o-mini"
},
"options": {}
},
"typeVersion": 1.2
},
{
"id": "efff4f36-e382-4d68-80a0-8bd649d009f2",
"name": "Store results to Google Sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
260,
460
],
"parameters": {
"columns": {
"value": {
"Title": "={{ $('Fetch Video Details').item.json.items[0].snippet.title }}",
"Summary": "={{ $json.output }}",
"Video URL": "={{ $('YouTube RSS Trigger').item.json.link }}",
"Video Published Date": "={{ $('YouTube RSS Trigger').item.json.isoDate }}"
},
"schema": [
{
"id": "Title",
"type": "string",
"display": true,
"required": false,
"displayName": "Title",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Video URL",
"type": "string",
"display": true,
"required": false,
"displayName": "Video URL",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Summary",
"type": "string",
"display": true,
"required": false,
"displayName": "Summary",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Video Published Date",
"type": "string",
"display": true,
"required": false,
"displayName": "Video Published Date",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1ImEKVtyBlxVvXzWKQw4wGbp4IzT_L2EUVqVj5txqY8A/edit#gid=0",
"cachedResultName": "Sheet1"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1ImEKVtyBlxVvXzWKQw4wGbp4IzT_L2EUVqVj5txqY8A",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1ImEKVtyBlxVvXzWKQw4wGbp4IzT_L2EUVqVj5txqY8A/edit?usp=drivesdk",
"cachedResultName": "Youtube video summarizer"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"id": "DwjQkQSmdk0Zj6Wj",
"name": "Google Sheets account 2"
}
},
"typeVersion": 4.5
},
{
"id": "4c5dcb17-7510-479a-8276-0ac86e3312c6",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1300,
-20
],
"parameters": {
"color": 3,
"width": 440,
"height": 680,
"content": "### 🔹 Section 1: **Trigger & Metadata Extraction**\n\n#### 1. `Trigger: New YouTube Video via RSS`\n\n* **Type**: RSS Trigger\n* **Purpose**: Listens for new videos published on a YouTube channel using its RSS feed.\n* **Output**: Latest video feed item including URL, title, and publication date.\n\n#### 2. `Function: Extract Channel ID from RSS`\n\n* **Type**: Function Node\n* **Purpose**: Parses the video URL from the RSS feed and extracts the YouTube Channel ID or Video ID.\n* **Why**: Required to fetch full video metadata using YouTube Data API in the next step.\n\n---\n\n"
},
"typeVersion": 1
},
{
"id": "c00b667c-3272-4e18-bb2f-1ee5b5a4a0aa",
"name": "Sticky Note9",
"type": "n8n-nodes-base.stickyNote",
"position": [
-3140,
-160
],
"parameters": {
"color": 4,
"width": 1300,
"height": 320,
"content": "=======================================\n WORKFLOW ASSISTANCE\n=======================================\nFor any questions or support, please contact:\n [email protected]\n\nExplore more tips and tutorials here:\n - YouTube: https://www.youtube.com/@YaronBeen/videos\n - LinkedIn: https://www.linkedin.com/in/yaronbeen/\n=======================================\n"
},
"typeVersion": 1
},
{
"id": "923883a0-2f05-46f8-bbb2-d6ea80e4be69",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
-3140,
180
],
"parameters": {
"color": 4,
"width": 1289,
"height": 2378,
"content": "# 📺 YouTube Video Summary Workflow – Documentation\n\n## 🧩 Overview\n\nThis n8n workflow automates the process of:\n\n* Monitoring a YouTube channel for new videos via RSS\n* Extracting video metadata\n* Summarizing the video description using GPT\n* Logging the summary in a Google Sheet\n* Requesting human approval via Slack\n* Posting the approved summary to a Discord channel\n\n---\n\n## 🔗 Workflow Breakdown\n\n### 🔹 Group 1: **Trigger & Metadata Extraction**\n\n#### 1. `Trigger: New YouTube Video via RSS`\n\n* **Type**: RSS Trigger\n* **Purpose**: Listens for new videos published on a YouTube channel using its RSS feed.\n* **Output**: Latest video feed item including URL, title, and publication date.\n\n#### 2. `Function: Extract Channel ID from RSS`\n\n* **Type**: Function Node\n* **Purpose**: Parses the video URL from the RSS feed and extracts the YouTube Channel ID or Video ID.\n* **Why**: Required to fetch full video metadata using YouTube Data API in the next step.\n\n---\n\n### 🔹 Group 2: **Video Metadata Retrieval**\n\n#### 3. `HTTP Request: Fetch Video Metadata from YouTube API`\n\n* **Type**: HTTP Request Node\n* **Purpose**: Fetches detailed video data like description, title, and published date using the YouTube Data API.\n* **Key Output Fields**:\n\n * `videoTitle`\n * `videoDescription`\n * `videoPublishedAt`\n * `videoURL`\n\n---\n\n### 🔹 Group 3: **AI Summary Generation**\n\n#### 4. `Agent: Summarize Video Description (GPT)`\n\n* **Type**: OpenAI GPT Agent Node\n* **Purpose**: Uses OpenAI GPT model to generate a concise summary from the video description.\n* **Model Used**: OpenAI GPT (e.g., gpt-4 or gpt-3.5)\n* **Inputs**: Raw video description\n* **Outputs**: Clean, readable summary\n\n---\n\n### 🔹 Group 4: **Storage & Human Approval**\n\n#### 5. `Google Sheets: Append Summary Record`\n\n* **Type**: Google Sheets Node\n* **Purpose**: Logs each video’s summary to a Google Sheet.\n* **Fields Stored**:\n\n * `Title`\n * `Video URL`\n * `Summary`\n * `Video Published Date`\n\n#### 6. `Slack: Send Summary for Approval`\n\n* **Type**: Slack (sendAndWait) Node\n* **Purpose**: Sends the summary to a Slack channel for human review.\n* **Interactivity**: Waits for a response (approve or reject) from the user.\n\n---\n\n### 🔹 Group 5: **Final Publishing**\n\n#### 7. `Discord: Post Approved Summary`\n\n* **Type**: Discord Message Node\n* **Purpose**: Publishes the final approved summary to a specific Discord channel.\n* **Condition**: Only posts if approved via Slack interaction.\n\n---\n\n## ✅ Benefits\n\n* **Automation**: Saves time by reducing manual video summarization.\n* **Human-in-the-loop**: Ensures quality control via Slack approval.\n* **Cross-platform updates**: Automatically updates both internal (Google Sheets) and external (Discord) channels.\n\n---\n\n\n"
},
"typeVersion": 1
},
{
"id": "4ced7d41-bbed-4825-8fcd-b2c8c280a431",
"name": "Send Summary for Approval",
"type": "n8n-nodes-base.slack",
"position": [
440,
460
],
"webhookId": "24d232e5-aaa6-49e4-b070-479d86ed0aee",
"parameters": {
"select": "channel",
"message": "=The summary of a video titled \"{{ $json.Title }}\" is given below:\n\n{{ $json.Summary }}",
"options": {
"appendAttribution": false
},
"channelId": {
"__rl": true,
"mode": "list",
"value": "C08TTV0CC3E",
"cachedResultName": "all-nathing"
},
"operation": "sendAndWait"
},
"typeVersion": 2.3
},
{
"id": "b625cc87-62a3-4d1c-89a9-aedd348c5be0",
"name": "Post Approved Summary",
"type": "n8n-nodes-base.discord",
"position": [
760,
460
],
"webhookId": "f687b811-e348-4f76-8a8e-0abb35dab2fc",
"parameters": {
"content": "=New Video Summary\nTitle: {{ $('Store results to Google Sheet').item.json.Title }}\nSummary: {{ $('Store results to Google Sheet').item.json.Summary }}\n",
"guildId": {
"__rl": true,
"mode": "list",
"value": ""
},
"options": {},
"resource": "message",
"channelId": {
"__rl": true,
"mode": "list",
"value": ""
}
},
"typeVersion": 2
},
{
"id": "04f9dc44-0d22-4d4a-9ade-58b8596ed3f5",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
-780,
80
],
"parameters": {
"color": 2,
"width": 380,
"height": 580,
"content": "### 🔹 Section 2: **Video Metadata Retrieval**\n\n#### 3. `HTTP Request: Fetch Video Metadata from YouTube API`\n\n* **Type**: HTTP Request Node\n* **Purpose**: Fetches detailed video data like description, title, and published date using the YouTube Data API.\n* **Key Output Fields**:\n\n * `videoTitle`\n * `videoDescription`\n * `videoPublishedAt`\n * `videoURL`\n\n---\n\n"
},
"typeVersion": 1
},
{
"id": "89452ce8-1bfb-48b6-9572-ef28f959f4f4",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
-320,
120
],
"parameters": {
"color": 4,
"width": 400,
"height": 700,
"content": "### 🔹 Section 3: **AI Summary Generation**\n\n#### 4. `Agent: Summarize Video Description (GPT)`\n\n* **Type**: OpenAI GPT Agent Node\n* **Purpose**: Uses OpenAI GPT model to generate a concise summary from the video description.\n* **Model Used**: OpenAI GPT (e.g., gpt-4 or gpt-3.5)\n* **Inputs**: Raw video description\n* **Outputs**: Clean, readable summary\n\n---\n\n\n"
},
"typeVersion": 1
},
{
"id": "b357e45b-94a5-40b5-8e09-461d2176d0e2",
"name": "Sticky Note7",
"type": "n8n-nodes-base.stickyNote",
"position": [
180,
-140
],
"parameters": {
"color": 5,
"width": 400,
"height": 820,
"content": "### 🔹 Section 4: **Storage & Human Approval**\n\n#### 5. `Google Sheets: Append Summary Record`\n\n* **Type**: Google Sheets Node\n* **Purpose**: Logs each video’s summary to a Google Sheet.\n* **Fields Stored**:\n\n * `Title`\n * `Video URL`\n * `Summary`\n * `Video Published Date`\n\n#### 6. `Slack: Send Summary for Approval`\n\n* **Type**: Slack (sendAndWait) Node\n* **Purpose**: Sends the summary to a Slack channel for human review.\n* **Interactivity**: Waits for a response (approve or reject) from the user.\n\n---\n\n"
},
"typeVersion": 1
},
{
"id": "4fbedef1-b1ea-460b-9842-ce0ae0d8d4d2",
"name": "Sticky Note8",
"type": "n8n-nodes-base.stickyNote",
"position": [
660,
180
],
"parameters": {
"color": 6,
"width": 320,
"height": 480,
"content": "### 🔹 Section 5: **Final Publishing**\n\n#### 7. `Discord: Post Approved Summary`\n\n* **Type**: Discord Message Node\n* **Purpose**: Publishes the final approved summary to a specific Discord channel.\n* **Condition**: Only posts if approved via Slack interaction.\n\n---\n\n\n"
},
"typeVersion": 1
}
],
"pinData": {},
"connections": {
"Summarize Agent": {
"main": [
[
{
"node": "Store results to Google Sheet",
"type": "main",
"index": 0
}
]
]
},
"Extract Channel ID": {
"main": [
[
{
"node": "Fetch Video Details",
"type": "main",
"index": 0
}
]
]
},
"Fetch Video Details": {
"main": [
[
{
"node": "Summarize Agent",
"type": "main",
"index": 0
}
]
]
},
"YouTube RSS Trigger": {
"main": [
[
{
"node": "Extract Channel ID",
"type": "main",
"index": 0
}
]
]
},
"OpenAI GPT Summary Model": {
"ai_languageModel": [
[
{
"node": "Summarize Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Send Summary for Approval": {
"main": [
[
{
"node": "Post Approved Summary",
"type": "main",
"index": 0
}
]
]
},
"Store results to Google Sheet": {
"main": [
[
{
"node": "Send Summary for Approval",
"type": "main",
"index": 0
}
]
]
}
}
}