AutomationFlowsAI & RAG › YouTube Video Clip Extraction Workflow

YouTube Video Clip Extraction Workflow

Original n8n title: 视频剪藏工作流 Demo

视频剪藏工作流 Demo. Uses youTube, httpRequest, readWriteFile, agent. Event-driven trigger; 23 nodes.

Event trigger★★★★☆ complexityAI-powered23 nodesYouTubeHTTP RequestRead Write FileAgentLm Chat Deep SeekOutput Parser StructuredNotion
AI & RAG Trigger: Event Nodes: 23 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow follows the Agent → HTTP Request 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
{
  "name": "\u89c6\u9891\u526a\u85cf\u5de5\u4f5c\u6d41 Demo",
  "nodes": [
    {
      "parameters": {},
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        -800,
        -160
      ],
      "id": "01d13c16-a9d1-4124-9ef0-b3e95cdeda99",
      "name": "When clicking \u2018Execute workflow\u2019"
    },
    {
      "parameters": {
        "resource": "playlistItem",
        "operation": "getAll",
        "playlistId": "PLORDp40s58gMHecjJRjHQ4J3K23iMrGfd",
        "returnAll": true,
        "options": {}
      },
      "type": "n8n-nodes-base.youTube",
      "typeVersion": 1,
      "position": [
        -592,
        -160
      ],
      "id": "fab9b67d-707a-44a5-bcd9-d5f3b5325945",
      "name": "Get many playlist items",
      "credentials": {
        "youTubeOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "4c81e286-8f54-4fe3-980d-de801b8d04d0",
              "name": "videoname",
              "value": "={{ $json.snippet.title }}",
              "type": "string"
            },
            {
              "id": "ba8319e3-e4ba-4cbb-a115-5e9f3de5dc8b",
              "name": "url",
              "value": "=https://www.youtube.com/watch?v={{ $json.snippet.resourceId.videoId }}",
              "type": "string"
            },
            {
              "id": "c7f9de6d-63b7-41ef-bd0e-438190921c34",
              "name": "pubilsh_time",
              "value": "={{ $json.contentDetails.videoPublishedAt }}",
              "type": "string"
            },
            {
              "id": "fe8ad35d-35f1-4248-af6e-adb7e28ac419",
              "name": "videoId",
              "value": "={{ $json.snippet.resourceId.videoId }}",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        -368,
        -160
      ],
      "id": "db70c9c3-2a5f-4130-bcf2-63b945354aae",
      "name": "Edit Fields"
    },
    {
      "parameters": {
        "options": {}
      },
      "type": "n8n-nodes-base.splitInBatches",
      "typeVersion": 3,
      "position": [
        -80,
        -160
      ],
      "id": "26b80b65-59c5-4547-b990-80e469385cad",
      "name": "Loop Over Items"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "http://host.docker.internal:8081/add",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"url\": \"{{ $json.url }}\",\n  \"quality\": \"720p\",\n  \"format\": \"mp4\", \n  \"folder\": \"demo/assets\"\n}  ",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [
        176,
        -144
      ],
      "id": "c67b8af3-0b94-4041-8e6b-78211d19f5d0",
      "name": "HTTP Request"
    },
    {
      "parameters": {
        "fileSelector": "=./n8ndata/downloads/demo/assets/{{ $('Loop Over Items').item.json.videoname }}.*.vtt",
        "options": {}
      },
      "type": "n8n-nodes-base.readWriteFile",
      "typeVersion": 1,
      "position": [
        1264,
        -128
      ],
      "id": "b8955f92-7d2e-480f-9013-41fb46dadbd7",
      "name": "Read/Write Files from Disk"
    },
    {
      "parameters": {
        "operation": "text",
        "options": {}
      },
      "type": "n8n-nodes-base.extractFromFile",
      "typeVersion": 1.1,
      "position": [
        1504,
        -128
      ],
      "id": "75e3ed32-8afb-4ef1-b487-387457cbc8b9",
      "name": "Extract from File"
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "=\u5b57\u5e55\u5185\u5bb9\u5982\u4e0b\uff1a{{ $json.data }}",
        "hasOutputParser": true,
        "options": {
          "systemMessage": "# Role\n\u4f60\u662f\u4e00\u4f4d\u4e13\u4e1a\u7684\u89c6\u9891\u5185\u5bb9\u5206\u6790\u4e13\u5bb6\uff0c\u64c5\u957f\u4ece\u5197\u957f\u7684\u89c6\u9891\u5b57\u5e55\u4e2d\u63d0\u53d6\u6838\u5fc3\u89c2\u70b9\uff0c\u5e76\u5c06\u5176\u6574\u7406\u6210\u7ed3\u6784\u6e05\u6670\u3001\u5e26\u6807\u7b7e\u5206\u7c7b\u3001\u6613\u4e8e\u68c0\u7d22\u7684\u6458\u8981\u548c\u4e8c\u7ea7\u5927\u7eb2\u3002\n\n# Task\n\u8bf7\u9605\u8bfb\u63d0\u4f9b\u7684\u89c6\u9891\u5b57\u5e55\u6587\u4ef6\uff08\u5305\u542b\u65f6\u95f4\u6233\uff09\uff0c\u5e76\u6309\u7167\u4ee5\u4e0b\u56fa\u5b9a\u6a21\u677f\u751f\u6210\u5185\u5bb9\uff1a\n\n1. \u5185\u5bb9\u6807\u7b7e\uff1a\u63d0\u53d6 3-5 \u4e2a\u6838\u5fc3\u5173\u952e\u8bcd\u4f5c\u4e3a\u6807\u7b7e\uff08\u4f8b\u5982\uff1a#AI #n8n #\u81ea\u52a8\u5316 #\u6559\u7a0b\uff09\u3002\u8981\u6c42\u6db5\u76d6\u89c6\u9891\u6d89\u53ca\u7684\u6838\u5fc3\u5de5\u5177\u3001\u6280\u672f\u9886\u57df\u548c\u89c6\u9891\u6027\u8d28\u3002\n2. \u89c6\u9891\u6458\u8981\uff1a\u7528\u4e00\u6bb5\u8bdd\uff08\u7ea6 150-200 \u5b57\uff09\u9ad8\u5ea6\u6982\u62ec\u89c6\u9891\u7684\u6838\u5fc3\u5185\u5bb9\u3001\u903b\u8f91\u6d41\u7a0b\u4ee5\u53ca\u6700\u7ec8\u7ed3\u8bba\u3002\n3. \u4eae\u70b9\u5927\u7eb2\uff08\u4e8c\u7ea7\u7ed3\u6784\uff09\uff1a\n   - \u4e00\u7ea7\u6807\u9898\uff1a\u6807\u6ce8\u8be5\u7ae0\u8282\u7684\u8d77\u59cb\u65f6\u95f4\u6233\u53ca\u6838\u5fc3\u4e3b\u9898\u3002\n   - \u4e8c\u7ea7\u8981\u70b9\uff1a\u7f57\u5217\u8be5\u7ae0\u8282\u4e0b\u7684\u5177\u4f53\u7ec6\u8282\u3001\u64cd\u4f5c\u6b65\u9aa4\u6216\u5173\u952e\u8bba\u70b9\uff0c\u5e76\u7cbe\u786e\u6807\u6ce8\u5bf9\u5e94\u7684\u51fa\u73b0\u65f6\u95f4\u3002\n\n# Constraints\n- \u603b\u7ed3\u8981\u6c42\uff1a\u8bed\u6c14\u5ba2\u89c2\u4e13\u4e1a\uff0c\u80fd\u591f\u8ba9\u7528\u6237\u4e0d\u770b\u89c6\u9891\u4e5f\u80fd\u638c\u63e1 80% \u7684\u6838\u5fc3\u4fe1\u606f\u3002\n- \u65f6\u95f4\u6233\u7cbe\u5ea6\uff1a\u5fc5\u987b\u4e25\u683c\u57fa\u4e8e\u5b57\u5e55\u4e2d\u63d0\u4f9b\u7684\u65f6\u95f4\u4fe1\u606f\uff0c\u786e\u4fdd\u51c6\u786e\u6027\u3002\n- \u6807\u7b7e\u8981\u6c42\uff1a\u6807\u7b7e\u9700\u5177\u6709\u68c0\u7d22\u4ef7\u503c\uff0c\u4f18\u5148\u63d0\u53d6\u5de5\u5177\u540d\u3001\u6280\u672f\u540d\u8bcd\u6216\u573a\u666f\u5206\u7c7b\u3002\n- \u8bed\u8a00\uff1a\u7edf\u4e00\u4f7f\u7528\u4e2d\u6587\u3002\n- \u7b80\u6d01\u6027\uff1a\u4fdd\u6301\u7b80\u660e\u627c\u8981\uff0c\u4e25\u7981\u5197\u957f\u5e9f\u8bdd\u3002"
        }
      },
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 3,
      "position": [
        1728,
        -128
      ],
      "id": "5aff7633-6bbb-4935-b406-21fc664da379",
      "name": "AI Agent"
    },
    {
      "parameters": {
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatDeepSeek",
      "typeVersion": 1,
      "position": [
        1696,
        80
      ],
      "id": "afc66731-a9e2-4300-beb2-acf809264831",
      "name": "DeepSeek Chat Model",
      "credentials": {
        "deepSeekApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsonSchemaExample": "{\n  \"tags\":[\"\u6807\u7b7e\",\"\u6807\u7b7e\",\"\u6807\u7b7e\"],\n  \"summary\": \"\u6b64\u5904\u586b\u5199\u751f\u6210\u7684\u89c6\u9891\u603b\u7ed3\u5168\u6587\uff0c\u8981\u6c42\u903b\u8f91\u8fde\u8d2f\uff0c\u6db5\u76d6\u89c6\u9891\u7684\u8d77\u56e0\u3001\u7ecf\u8fc7\u3001\u7ed3\u679c\u548c\u535a\u4e3b\u5efa\u8bae\u3002\",\n  \"highlights\": [\n    {\n      \"timestamp\": \"00:00\",\n      \"title\": \"\u4e00\u7ea7\u6807\u9898\u540d\u79f0\",\n      \"sub_points\": [\n        {\n          \"timestamp\": \"00:18\",\n          \"content\": \"\u4e8c\u7ea7\u8be6\u7ec6\u8981\u70b9 1\"\n        },\n        {\n          \"timestamp\": \"01:54\",\n          \"content\": \"\u4e8c\u7ea7\u8be6\u7ec6\u8981\u70b9 2\"\n        }\n      ]\n    },\n    {\n      \"timestamp\": \"06:48\",\n      \"title\": \"\u4e00\u7ea7\u6807\u9898\u540d\u79f0\",\n      \"sub_points\": [\n        {\n          \"timestamp\": \"07:35\",\n          \"content\": \"\u4e8c\u7ea7\u8be6\u7ec6\u8981\u70b9 1\"\n        },\n        {\n          \"timestamp\": \"08:42\",\n          \"content\": \"\u4e8c\u7ea7\u8be6\u7ec6\u8981\u70b9 2\"\n        }\n      ]\n    }\n  ]\n}"
      },
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "typeVersion": 1.3,
      "position": [
        1904,
        80
      ],
      "id": "2bf84f2a-2d70-481b-805d-dd6fd16e1f64",
      "name": "Structured Output Parser"
    },
    {
      "parameters": {
        "resource": "databasePage",
        "databaseId": {
          "__rl": true,
          "value": "2ee629a6-152d-809d-963e-db8a25c99189",
          "mode": "list",
          "cachedResultName": "\u89c6\u9891\u6536\u85cf",
          "cachedResultUrl": "https://www.notion.so/2ee629a6152d809d963edb8a25c99189"
        },
        "title": "={{ $('Loop Over Items').item.json.videoname }}",
        "propertiesUi": {
          "propertyValues": [
            {
              "key": "\u6807\u9898|title",
              "title": "={{ $('Loop Over Items').item.json.videoname }}"
            },
            {
              "key": "\u6458\u8981|rich_text",
              "textContent": "={{ $json.output.summary }}"
            },
            {
              "key": "\u6765\u6e90|select",
              "selectValue": "YouTube"
            },
            {
              "key": "\u7f51\u5740|url",
              "urlValue": "={{ $('Loop Over Items').item.json.url }}"
            },
            {
              "key": "Tag\u6807\u7b7e|multi_select",
              "multiSelectValue": "={{ $json.output.tags }}"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.notion",
      "typeVersion": 2.2,
      "position": [
        2128,
        -352
      ],
      "id": "25713bcb-9d44-4274-87c4-3925291d4dfe",
      "name": "Create a database page",
      "credentials": {
        "notionApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "method": "PATCH",
        "url": "=https://api.notion.com/v1/blocks/{{ $json.id }}/children",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "notionApi",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"children\": [\n    {\n      \"object\": \"block\",\n      \"type\": \"video\",\n      \"video\": {\n        \"type\": \"external\",\n        \"external\": {\n          \"url\": \"{{ $('Loop Over Items').item.json.url }}\"\n        }\n      }\n    }\n  ]\n} ",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [
        2352,
        -352
      ],
      "id": "8cb98ecb-3fca-448a-8224-1426bda6a609",
      "name": "HTTP Request1",
      "credentials": {
        "notionApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "357c5018-717c-4518-aac9-bd74d992bdb4",
              "name": "time_line",
              "value": "={{ $('AI Agent').item.json.output.highlights }}",
              "type": "array"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        2880,
        -352
      ],
      "id": "a41ec582-d312-4123-b2b6-7d07e342df16",
      "name": "Edit Fields1"
    },
    {
      "parameters": {
        "fieldToSplitOut": "time_line",
        "include": "allOtherFields",
        "options": {}
      },
      "type": "n8n-nodes-base.splitOut",
      "typeVersion": 1,
      "position": [
        3120,
        -352
      ],
      "id": "98825180-ba72-41ca-a73f-e8aa62e2abe0",
      "name": "Split Out"
    },
    {
      "parameters": {
        "resource": "block",
        "blockId": {
          "__rl": true,
          "value": "={{ $('Create a database page').item.json.url }}",
          "mode": "url"
        },
        "blockUi": {
          "blockValues": [
            {
              "type": "heading_3",
              "textContent": "={{ $json.time_line.timestamp }} {{ $json.time_line.title }}"
            },
            {
              "textContent": "={{ $json.time_line.sub_points.map(item => `- ${item.timestamp} ${item.content}`).join('\\n') }}"
            }
          ]
        }
      },
      "type": "n8n-nodes-base.notion",
      "typeVersion": 2.2,
      "position": [
        3376,
        -352
      ],
      "id": "61969a11-2fc2-40e2-853a-81794877127a",
      "name": "Append a block",
      "credentials": {
        "notionApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "resource": "block",
        "blockId": {
          "__rl": true,
          "value": "={{ $('Create a database page').item.json.url }}",
          "mode": "url"
        },
        "blockUi": {
          "blockValues": [
            {
              "textContent": "={{ $('AI Agent').item.json.output.summary }}"
            },
            {
              "type": "heading_2",
              "textContent": "\u5185\u5bb9\u65f6\u95f4\u8f74\uff1a"
            }
          ]
        }
      },
      "type": "n8n-nodes-base.notion",
      "typeVersion": 2.2,
      "position": [
        2608,
        -352
      ],
      "id": "25ec4ed3-9f40-41f4-a291-9182fde7a21a",
      "name": "Append a block1",
      "credentials": {
        "notionApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// \u83b7\u53d6\u8f93\u5165\u6570\u636e\nconst videoName = $('Loop Over Items').first().json.videoname;\nconst url = $('Loop Over Items').first().json.url;\nconst data = $input.first().json.output;\nconst now = new Date();\n\n// \u683c\u5f0f\u5316\u65f6\u95f4\u4e3a\u4e0a\u6d77\u65f6\u533a YYYY-MM-DD HH:mm\nconst formatDateTime = (date) => {\n  // \u8f6c\u6362\u4e3a\u4e0a\u6d77\u65f6\u533a (UTC+8)\n  const shanghaiTime = new Date(date.toLocaleString('en-US', { timeZone: 'Asia/Shanghai' }));\n  \n  const year = shanghaiTime.getFullYear();\n  const month = String(shanghaiTime.getMonth() + 1).padStart(2, '0');\n  const day = String(shanghaiTime.getDate()).padStart(2, '0');\n  const hours = String(shanghaiTime.getHours()).padStart(2, '0');\n  const minutes = String(shanghaiTime.getMinutes()).padStart(2, '0');\n  return `${year}-${month}-${day} ${hours}:${minutes}`;\n};\n\n// \u63d0\u53d6\u89c6\u9891ID\uff08\u4eceYouTube URL\u4e2d\uff09\nconst getVideoId = (url) => {\n  const match = url.match(/(?:v=|\\/)([\\w-]{11})/);\n  return match ? match[1] : '';\n};\n\n// \u751f\u6210\u6587\u4ef6\u540d\uff08\u4f7f\u7528\u89c6\u9891\u6807\u9898\uff0c\u5904\u7406\u7279\u6b8a\u5b57\u7b26\u548c\u6807\u7b7e\uff09\nconst generateFileName = (title) => {\n  // \u79fb\u9664 #tag \u6807\u7b7e\n  let cleanTitle = title.replace(/#\\S+/g, '').trim();\n  \n  // \u79fb\u9664\u6216\u66ff\u6362\u6587\u4ef6\u540d\u4e2d\u4e0d\u5141\u8bb8\u7684\u7279\u6b8a\u5b57\u7b26\n  const sanitizedTitle = cleanTitle\n    .replace(/[<>:\"/\\\\|?*]/g, '') // \u79fb\u9664Windows\u4e0d\u5141\u8bb8\u7684\u5b57\u7b26\n    .replace(/\\s+/g, '_')          // \u7a7a\u683c\u66ff\u6362\u4e3a\u4e0b\u5212\u7ebf\n    .substring(0, 100);            // \u9650\u5236\u957f\u5ea6\u907f\u514d\u6587\u4ef6\u540d\u8fc7\u957f\n  \n  return `${sanitizedTitle}.md`;\n};\n\n// \u751f\u6210YAML\u524d\u7f6e\u6570\u636e\uff08\u5305\u542btags\u6570\u7ec4\uff09\nconst yamlFrontMatter = `---\nurl: ${url}\ntags: ${data.tags.join(', ')}\n\u6765\u6e90: YouTube\n\u6dfb\u52a0\u65f6\u95f4: ${formatDateTime(now)}\n---`;\n\n// \u751f\u6210\u89c6\u9891\u5d4c\u5165\uff08\u4f7f\u7528videoName\u4f5c\u4e3a\u6807\u9898\uff09\nconst videoEmbed = `![${videoName}](${url})`;\n\n// \u76f4\u63a5\u8f93\u51fa\u6458\u8981\u5185\u5bb9\uff0c\u4e0d\u5e26\"\u6458\u8981\"\u6807\u9898\nconst summarySection = `${data.summary}`;\n\n// \u751f\u6210\u9ad8\u4eae/\u8981\u70b9\u90e8\u5206\nlet highlightsSection = '## \u8981\u70b9\\n\\n';\n\ndata.highlights.forEach((highlight) => {\n  // \u683c\u5f0f\u5316\u4e00\u7ea7\u6807\u9898\u7684\u65f6\u95f4\u6233\n  const titleTimeParts = highlight.timestamp.split(':');\n  const titleHours = parseInt(titleTimeParts[0]);\n  const titleMinutes = parseInt(titleTimeParts[1]);\n  const titleSeconds = parseFloat(titleTimeParts[2]);\n  const titleTotalSeconds = titleHours * 3600 + titleMinutes * 60 + titleSeconds;\n  const titleDisplayMinutes = String(Math.floor(titleTotalSeconds / 60)).padStart(2, '0');\n  const titleDisplaySeconds = String(Math.floor(titleTotalSeconds % 60)).padStart(2, '0');\n  const titleDisplayTime = `${titleDisplayMinutes}:${titleDisplaySeconds}`;\n  \n  // \u83b7\u53d6\u89c6\u9891ID\n  const videoId = getVideoId(url);\n  \n  // \u751f\u6210\u4e00\u7ea7\u6807\u9898\u7684\u65f6\u95f4\u94fe\u63a5\n  const titleTimeLink = `https://www.youtube.com/watch?v=${videoId}&t=${Math.floor(titleTotalSeconds)}#t=${highlight.timestamp}`;\n  \n  // \u4e00\u7ea7\u6807\u9898\uff08\u65f6\u95f4\u94fe\u63a5\u5728\u5916\u9762\uff0c\u6807\u9898\u52a0\u7c97\uff09\n  highlightsSection += `[${titleDisplayTime}](${titleTimeLink}) **${highlight.title}**\\n\\n`;\n  \n  // \u4e8c\u7ea7\u5185\u5bb9\uff08\u65e0\u5e8f\u5217\u8868\uff09\n  if (highlight.sub_points && highlight.sub_points.length > 0) {\n    highlight.sub_points.forEach((point) => {\n      // \u5c06\u65f6\u95f4\u6233\u8f6c\u6362\u4e3a\u79d2\u6570\n      const timeParts = point.timestamp.split(':');\n      const hours = parseInt(timeParts[0]);\n      const minutes = parseInt(timeParts[1]);\n      const seconds = parseFloat(timeParts[2]);\n      const totalSeconds = hours * 3600 + minutes * 60 + seconds;\n      \n      // \u683c\u5f0f\u5316\u65f6\u95f4\u4e3a MM:SS\n      const displayMinutes = String(Math.floor(totalSeconds / 60)).padStart(2, '0');\n      const displaySeconds = String(Math.floor(totalSeconds % 60)).padStart(2, '0');\n      const displayTime = `${displayMinutes}:${displaySeconds}`;\n      \n      // \u751f\u6210\u5e26\u65f6\u95f4\u6233\u94fe\u63a5\u7684\u5217\u8868\u9879\n      const timeLink = `https://www.youtube.com/watch?v=${videoId}&t=${Math.floor(totalSeconds)}#t=${point.timestamp}`;\n      highlightsSection += `- [${displayTime}](${timeLink}) ${point.content}\\n`;\n    });\n    highlightsSection += '\\n';\n  }\n});\n\n// \u7ec4\u5408\u5b8c\u6574\u7684markdown\u5185\u5bb9\nconst markdownContent = `${yamlFrontMatter}\n\n${videoEmbed}\n\n${summarySection}\n\n${highlightsSection}`;\n\n// \u8fd4\u56de\u7b26\u5408n8n\u89c4\u8303\u7684\u5bf9\u8c61\u6570\u7ec4\uff0c\u5305\u542b\u6587\u4ef6\u76f8\u5173\u4fe1\u606f\nreturn [\n  {\n    json: {\n      fileContent: markdownContent,\n      fileName: generateFileName(videoName),\n      mimeType: 'text/markdown',\n      title: videoName\n    }\n  }\n];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2112,
        0
      ],
      "id": "830dcd8f-f978-4c70-9b1b-fd82aafe6324",
      "name": "Code in JavaScript"
    },
    {
      "parameters": {
        "operation": "toText",
        "sourceProperty": "fileContent",
        "options": {
          "fileName": "={{ $json.fileName }}"
        }
      },
      "type": "n8n-nodes-base.convertToFile",
      "typeVersion": 1.1,
      "position": [
        2320,
        0
      ],
      "id": "9f16ec9c-fd12-4727-bbd3-749548d7c120",
      "name": "Convert to File"
    },
    {
      "parameters": {
        "operation": "write",
        "fileName": "=./n8ndata/downloads/demo/{{ $('Code in JavaScript').item.json.fileName }}",
        "options": {}
      },
      "type": "n8n-nodes-base.readWriteFile",
      "typeVersion": 1,
      "position": [
        2528,
        0
      ],
      "id": "1cf8f67d-1956-491a-9219-61dac493c134",
      "name": "Read/Write Files from Disk1"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "aebcfddb-1fa4-49a0-8855-9f49375ee54a",
              "leftValue": "={{ $json.hasRunningTasks }}",
              "rightValue": false,
              "operator": {
                "type": "boolean",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        1024,
        -128
      ],
      "id": "b28a4d34-d09d-4937-84b2-af66b58bddf4",
      "name": "If"
    },
    {
      "parameters": {
        "url": "http://host.docker.internal:8081/history",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [
        592,
        -192
      ],
      "id": "f935eed6-0e0d-4536-8bd8-93fbef90e6e5",
      "name": "HTTP Request4"
    },
    {
      "parameters": {
        "jsCode": "// \u4ece HTTP Request \u8282\u70b9\u83b7\u53d6\u6570\u636e\nconst input = $input.first().json;\n\ntry {\n  // \u89e3\u6790 JSON \u5b57\u7b26\u4e32\n  const history = JSON.parse(input.data);\n  \n  // ========== 1. \u68c0\u67e5\u4efb\u52a1\u8fdb\u5ea6 ==========\n  const queueCount = history.queue?.length || 0;\n  const pendingCount = history.pending?.length || 0;\n  const hasRunningTasks = queueCount > 0 || pendingCount > 0;\n  \n  if (hasRunningTasks) {\n    return [{\n      json: {\n        hasRunningTasks: true,\n        status: '\u4efb\u52a1\u8fd8\u5728\u8fdb\u884c\u4e2d',\n        queueCount: queueCount,\n        pendingCount: pendingCount,\n        message: `\u8fd8\u6709 ${queueCount + pendingCount} \u4e2a\u4efb\u52a1\u672a\u5b8c\u6210\uff08\u961f\u5217\u4e2d: ${queueCount}, \u5f85\u5904\u7406: ${pendingCount}\uff09`\n      }\n    }];\n  }\n  \n  // ========== 2. \u627e\u5230\u6700\u65b0\u5b8c\u6210\u7684\u4efb\u52a1 ==========\n  const doneTasks = history.done || [];\n  \n  if (doneTasks.length === 0) {\n    return [{\n      json: {\n        hasRunningTasks: false,\n        status: '\u6ca1\u6709\u5df2\u5b8c\u6210\u7684\u4efb\u52a1',\n        error: true,\n        message: '\u6ca1\u6709\u627e\u5230\u4efb\u4f55\u5df2\u5b8c\u6210\u7684\u4efb\u52a1'\n      }\n    }];\n  }\n  \n  // \u6309\u65f6\u95f4\u6233\u964d\u5e8f\u6392\u5e8f\uff0c\u53d6\u7b2c\u4e00\u4e2a\uff08\u6700\u65b0\u7684\uff09\n  const latestTask = doneTasks.reduce((latest, current) => {\n    return (current.timestamp > latest.timestamp) ? current : latest;\n  }, doneTasks[0]);\n  \n  // ========== 3. \u68c0\u67e5\u5b57\u5e55\u6587\u4ef6\uff08\u4e25\u683c\u6392\u9664\u5f39\u5e55\uff09==========\n  const requestedSubtitles = latestTask.entry?.requested_subtitles || {};\n  \n  // \u83b7\u53d6\u6240\u6709\u5b57\u5e55\u8bed\u8a00\uff0c\u4e25\u683c\u6392\u9664 danmaku\n  const subtitleLanguages = Object.keys(requestedSubtitles).filter(\n    lang => lang !== 'danmaku'\n  );\n  \n  const hasSubtitles = subtitleLanguages.length > 0;\n  const hasDanmaku = requestedSubtitles.hasOwnProperty('danmaku');\n  \n  // ========== 4. \u8fd4\u56de\u5b8c\u6574\u7ed3\u679c ==========\n  return [{\n    json: {\n      // \u4efb\u52a1\u8fdb\u5ea6\n      hasRunningTasks: false,\n      status: '\u6240\u6709\u4efb\u52a1\u5df2\u5b8c\u6210',\n      totalCompleted: doneTasks.length,\n      \n      // \u6700\u65b0\u4efb\u52a1\u4fe1\u606f\n      latestTask: {\n        id: latestTask.id,\n        title: latestTask.title,\n        url: latestTask.url,\n        timestamp: latestTask.timestamp,\n        timestampReadable: new Date(latestTask.timestamp / 1000000).toLocaleString('zh-CN'),\n        size: latestTask.size,\n        sizeMB: (latestTask.size / (1024 * 1024)).toFixed(2),\n        status: latestTask.status\n      },\n      \n      // \u5b57\u5e55\u68c0\u6d4b\u7ed3\u679c\n      subtitleCheck: {\n        hasSubtitles: hasSubtitles,\n        hasDanmaku: hasDanmaku,\n        subtitleLanguages: subtitleLanguages,\n        subtitleCount: subtitleLanguages.length,\n        result: hasSubtitles \n          ? `\u2705 \u5305\u542b\u5b57\u5e55\u6587\u4ef6\uff1a${subtitleLanguages.join(', ')}`\n          : (hasDanmaku ? '\u274c \u4ec5\u6709\u5f39\u5e55\uff0c\u65e0\u5b57\u5e55\u6587\u4ef6' : '\u274c \u65e0\u5b57\u5e55\u3001\u65e0\u5f39\u5e55')\n      },\n      \n      // \u8be6\u7ec6\u5b57\u5e55\u6587\u4ef6\u4fe1\u606f\n      subtitleFiles: hasSubtitles ? subtitleLanguages.map(lang => ({\n        language: lang,\n        url: requestedSubtitles[lang].url,\n        extension: requestedSubtitles[lang].ext\n      })) : [],\n      \n      // \u5f39\u5e55\u4fe1\u606f\uff08\u5982\u679c\u6709\uff09\n      danmaku: hasDanmaku ? {\n        url: requestedSubtitles.danmaku.url,\n        extension: requestedSubtitles.danmaku.ext\n      } : null,\n      \n      // \u603b\u7ed3\u6d88\u606f\n      message: hasSubtitles \n        ? `\u2705 \u6700\u65b0\u4efb\u52a1\u5df2\u5b8c\u6210\uff0c\u5305\u542b ${subtitleLanguages.length} \u4e2a\u5b57\u5e55\u6587\u4ef6`\n        : '\u26a0\ufe0f \u6700\u65b0\u4efb\u52a1\u5df2\u5b8c\u6210\uff0c\u4f46\u672a\u5305\u542b\u5b57\u5e55\u6587\u4ef6'\n    }\n  }];\n  \n} catch (error) {\n  return [{\n    json: {\n      error: true,\n      errorMessage: error.message,\n      errorStack: error.stack\n    }\n  }];\n}\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        816,
        -176
      ],
      "id": "0033c96f-984b-4d7e-909f-2f7a91e2717a",
      "name": "Code in JavaScript1"
    },
    {
      "parameters": {
        "amount": 1
      },
      "type": "n8n-nodes-base.wait",
      "typeVersion": 1.1,
      "position": [
        384,
        -160
      ],
      "id": "ecadcfe9-0b97-4b33-ac23-eb0903895d6a",
      "name": "Wait"
    }
  ],
  "connections": {
    "When clicking \u2018Execute workflow\u2019": {
      "main": [
        [
          {
            "node": "Get many playlist items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get many playlist items": {
      "main": [
        [
          {
            "node": "Edit Fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Edit Fields": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items": {
      "main": [
        [],
        [
          {
            "node": "HTTP Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request": {
      "main": [
        [
          {
            "node": "Wait",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read/Write Files from Disk": {
      "main": [
        [
          {
            "node": "Extract from File",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract from File": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "DeepSeek Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "AI Agent",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent": {
      "main": [
        [
          {
            "node": "Code in JavaScript",
            "type": "main",
            "index": 0
          },
          {
            "node": "Create a database page",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create a database page": {
      "main": [
        [
          {
            "node": "HTTP Request1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request1": {
      "main": [
        [
          {
            "node": "Append a block1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Edit Fields1": {
      "main": [
        [
          {
            "node": "Split Out",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Out": {
      "main": [
        [
          {
            "node": "Append a block",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Append a block1": {
      "main": [
        [
          {
            "node": "Edit Fields1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code in JavaScript": {
      "main": [
        [
          {
            "node": "Convert to File",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Convert to File": {
      "main": [
        [
          {
            "node": "Read/Write Files from Disk1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If": {
      "main": [
        [
          {
            "node": "Read/Write Files from Disk",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Wait",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request4": {
      "main": [
        [
          {
            "node": "Code in JavaScript1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code in JavaScript1": {
      "main": [
        [
          {
            "node": "If",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait": {
      "main": [
        [
          {
            "node": "HTTP Request4",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "08b246e7-a2b1-4d2d-aab3-7c1fc3651438",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "id": "rBgHbHMlrO0J0v9k",
  "tags": []
}

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

视频剪藏工作流 Demo. Uses youTube, httpRequest, readWriteFile, agent. Event-driven trigger; 23 nodes.

Source: https://github.com/soluckysummer/n8n_workflows/blob/46aac817454c783de8f17975d5fa0379b8b6acf3/workflows/video_collection.json — 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

RAG CHATBOT Main. Uses telegram, telegramTrigger, lmChatOpenAi, n8n-nodes-mcp. Event-driven trigger; 87 nodes.

Telegram, Telegram Trigger, OpenAI Chat +8
AI & RAG

AI Agent Workflow. Uses telegramTrigger, chatTrigger, telegram, openAi. Event-driven trigger; 82 nodes.

Telegram Trigger, Chat Trigger, Telegram +7
AI & RAG

Deep Research new (fr). Uses outputParserStructured, formTrigger, chainLlm, form. Event-driven trigger; 82 nodes.

Output Parser Structured, Form Trigger, Chain Llm +8
AI & RAG

Digital marketers, content creators, social media managers, and businesses who want to use AI marketing automation for YouTube Shorts without spending hours on production. This AI workflow helps anyon

OpenAI, HTTP Request, OpenAI Chat +7
AI & RAG

Who is this for? Agencies, consultants, and service providers who conduct discovery calls and need to quickly turn conversations into professional proposals.

Tool Think, Tool Calculator, Agent Tool +18