8
n8n 한국어amn8n.com

⚡AI驱动의YouTube播放列表및视频摘要与분석v2

고급

이것은Other, AI분야의자동화 워크플로우로, 72개의 노드를 포함합니다.주로 If, Set, Code, Limit, Merge 등의 노드를 사용하며인공지능 기술을 결합하여 스마트 자동화를 구현합니다. AI YouTube播放列表与视频분석채팅봇

사전 요구사항
  • Redis 서버 연결 정보
  • 대상 API의 인증 정보가 필요할 수 있음
  • Qdrant 서버 연결 정보
  • Google Gemini API Key

카테고리

워크플로우 미리보기
노드 연결 관계를 시각적으로 표시하며, 확대/축소 및 이동을 지원합니다
워크플로우 내보내기
다음 JSON 구성을 복사하여 n8n에 가져오면 이 워크플로우를 사용할 수 있습니다
{
  "id": "4Tq5HZBdETVe7jEb",
  "meta": {
    "instanceId": "2cb7a61f866faf57392b91b31f47e08a2b3640258f0abd08dd71f087f3243a5a",
    "templateCredsSetupCompleted": true
  },
  "name": "⚡AI-Powered YouTube Playlist & Video Summarization and Analysis v2",
  "tags": [],
  "nodes": [
    {
      "id": "505077d1-a2e4-4b0d-99d6-756940022c3d",
      "name": "Google Gemini 채팅 모델1",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        -440,
        -40
      ],
      "parameters": {
        "options": {},
        "modelName": "models/gemini-2.0-pro-exp"
      },
      "credentials": {
        "googlePalmApi": {
          "id": "2zwuT5znDglBrUCO",
          "name": "Google Gemini(PaLM) Api account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "5da369db-b801-4653-888d-0e6042620298",
      "name": "Handle Queries",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        -160,
        -280
      ],
      "parameters": {
        "text": "={{ $('Chat').item.json.chatInput }}",
        "options": {
          "systemMessage": "=You are an intelligent assistant that can respond to queries related to the content of a Youtube Playlist or a single Video.\n\n# YOUR TASK\nDecide if the user has provided the info required and reply accordingly. If there is no url in context you have to suggest the user to provide one. \n\n\n1. If the user provided a YouTube Playlist or Video URL: reply in structured markdown format to the user based on the formulated questions and context. Assume the user is here because they don't won't / have time to watch such videos so:\n- Use the tool called `chat_playlist_data`, which can analyze YouTube videos. Use this tool effectively to process video content and generate structured summaries.\n- Your answers needs to be exhaustive and minimise bullet points\n- Be verbose in your response\n\n2. 1. If the user provided a YouTube Playlist or Video URL:\n- Do not ask for more specific details - always try to summarize the videos with the data from the tool `chat_playlist_data`\n- Never reply \"already provided a detailed summary\" - always try to summarize again the videos with more info from the tool `chat_playlist_data` - even if you have already provided the data before (so repeat yourself).\n\n3. If the user HAS NOT provided a YouTube Playlist URL or a invaid URL: gently invite the user to provide the URL so you can process it. \n\n# Rules\n\n## YouTube Playlist URL Definition\n- A URL from www.youtube.com or youtube.com.\n- Contains the query parameter `list=` followed by a playlist ID.\n- Example: https://www.youtube.com/playlist?list=PLXXXXXX (where PLXXXXXX is the playlist ID).\n\n## YouTube Video URL Definition\n- A URL from www.youtube.com, youtube.com, or youtu.be.\n- For www.youtube.com or youtube.com, it contains the query parameter `v=` followed by a video ID.\n- For youtu.be, it follows the format https://youtu.be/VIDEO_ID.\n- Examples:\n  - https://www.youtube.com/watch?v=VIDEO_ID (where VIDEO_ID is the video ID).\n  - https://youtu.be/VIDEO_ID\n- Does NOT have a query parameter `list=`\n\n# Context\n{\n  \"intent\": {{ $('Default Intent').item.json.output?.intent || \"NONE\" }},\n  \"url\": {{ $('Default Intent').item.json.output?.url || \"\" }},\n  \"id\": {{ $('Default Intent').item.json.output?.id || \"\" }},\n  \"limit\": {{ $('Default Intent').item.json.output?.limit || 0 }},\n  \"status\": {{ $('Default Intent').item.json.output?.status || 'PENDING' }}\n}"
        },
        "promptType": "define"
      },
      "typeVersion": 1.7
    },
    {
      "id": "866bf387-3482-4615-94d5-fd72d5db21da",
      "name": "분할 출력",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        1380,
        -200
      ],
      "parameters": {
        "include": "selectedOtherFields",
        "options": {},
        "fieldToSplitOut": "transcript",
        "fieldsToInclude": "youtubeId"
      },
      "typeVersion": 1
    },
    {
      "id": "359404ce-4bc9-4e4d-9a26-22b9f9b176c9",
      "name": "요약 & Analyze Transcript",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        660,
        540
      ],
      "parameters": {
        "text": "=Please analyze the given text and create a structured summary following these guidelines:\n\n1. Break down the content into main topics using Level 2 headers (##)\n2. Under each header:\n   - List only the most essential concepts and key points\n   - Use bullet points for clarity\n   - Keep explanations concise\n   - Preserve technical accuracy\n   - Highlight key terms in bold\n3. Format requirements:\n   - Use markdown formatting\n   - Keep bullet points simple (no nesting)\n   - Bold important terms using **term**\n   - Use tables for comparisons\n   - Include relevant technical details\n\nPlease provide a clear, structured summary that captures the core concepts while maintaining technical accuracy.\n\n**Make sure the summary is 300-400 max characters long.**\n\nInclude metadata such as video number, id, and title in the summary.\n\n**Here is the text**\n\nVideo number: {{ $json.video_number }}\nTitle: {{ $json.title }}\nYoutube ID: {{ $json.youtubeId }}\nTranscript:\n{{ $json.transcript_text }}",
        "promptType": "define"
      },
      "typeVersion": 1.4
    },
    {
      "id": "036765df-6da4-4430-bcea-af4066fb7c24",
      "name": "Concatenate",
      "type": "n8n-nodes-base.summarize",
      "position": [
        1700,
        -200
      ],
      "parameters": {
        "options": {},
        "fieldsToSplitBy": "youtubeId",
        "fieldsToSummarize": {
          "values": [
            {
              "field": "transcript.text",
              "separateBy": " ",
              "aggregation": "concatenate"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "9152725c-15ca-41a0-8f98-108834e0c8be",
      "name": "분할 출력1",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        660,
        40
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "videos"
      },
      "typeVersion": 1
    },
    {
      "id": "fee0e045-614a-41f0-ac75-051dff773e77",
      "name": "제한",
      "type": "n8n-nodes-base.limit",
      "position": [
        860,
        40
      ],
      "parameters": {
        "maxItems": "={{ $('Update Context Intent').item.json.output.limit }}"
      },
      "typeVersion": 1
    },
    {
      "id": "a691c1c7-d8c4-4eab-861b-f7cfcbeb0fc8",
      "name": "Qdrant 벡터 스토어",
      "type": "@n8n/n8n-nodes-langchain.vectorStoreQdrant",
      "position": [
        1680,
        480
      ],
      "parameters": {
        "mode": "insert",
        "options": {},
        "qdrantCollection": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Update Context Intent').first().json.output.id }}"
        }
      },
      "credentials": {
        "qdrantApi": {
          "id": "mb8rw8tmUeP6aPJm",
          "name": "QdrantApi account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "c3949e8f-0deb-4106-aaa5-e64403024243",
      "name": "재귀적 문자 텍스트 분할기",
      "type": "@n8n/n8n-nodes-langchain.textSplitterRecursiveCharacterTextSplitter",
      "position": [
        1800,
        860
      ],
      "parameters": {
        "options": {},
        "chunkSize": 1200,
        "chunkOverlap": 200
      },
      "typeVersion": 1
    },
    {
      "id": "a3b23c6b-14c0-4805-8220-7c6166268276",
      "name": "Google Gemini 임베딩",
      "type": "@n8n/n8n-nodes-langchain.embeddingsGoogleGemini",
      "position": [
        1660,
        700
      ],
      "parameters": {
        "modelName": "models/text-embedding-004"
      },
      "credentials": {
        "googlePalmApi": {
          "id": "2zwuT5znDglBrUCO",
          "name": "Google Gemini(PaLM) Api account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "6f4ee00d-dcdc-4468-9713-115912c1e571",
      "name": "Google Gemini 채팅 모델2",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        640,
        740
      ],
      "parameters": {
        "options": {},
        "modelName": "models/gemini-2.0-flash"
      },
      "credentials": {
        "googlePalmApi": {
          "id": "2zwuT5znDglBrUCO",
          "name": "Google Gemini(PaLM) Api account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "75442631-512e-4b0e-a5a8-ed3e3a3e1f94",
      "name": "Google Gemini 임베딩1",
      "type": "@n8n/n8n-nodes-langchain.embeddingsGoogleGemini",
      "position": [
        -120,
        320
      ],
      "parameters": {
        "modelName": "models/text-embedding-004"
      },
      "credentials": {
        "googlePalmApi": {
          "id": "2zwuT5znDglBrUCO",
          "name": "Google Gemini(PaLM) Api account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "c33ceeca-9bf0-4dd2-b8df-fc2a1ccdf512",
      "name": "Chat",
      "type": "@n8n/n8n-nodes-langchain.chatTrigger",
      "position": [
        -2780,
        -460
      ],
      "webhookId": "e66183cc-1eed-4968-b34b-bcecf1bb55e8",
      "parameters": {
        "public": true,
        "options": {
          "loadPreviousSession": "notSupported"
        },
        "initialMessages": "Hi there! 👋\nPlease provide a URL of a Youtube playlist you would like me to analise."
      },
      "typeVersion": 1.1
    },
    {
      "id": "06bb2dfd-027c-4902-9559-2de080f6c145",
      "name": "Video Titles",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        1160,
        40
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "id,title"
      },
      "typeVersion": 1
    },
    {
      "id": "d9bbdda2-ef26-4b6c-94d0-7542f88f1530",
      "name": "병합",
      "type": "n8n-nodes-base.merge",
      "position": [
        1700,
        20
      ],
      "parameters": {
        "mode": "combineBySql",
        "query": "SELECT \n  ROW_NUMBER() AS video_number,\n  input1.youtubeId, input2.title, input1.concatenated_transcript_text as transcript_text FROM input1 LEFT JOIN input2 ON input1.youtubeId = input2.id"
      },
      "typeVersion": 3
    },
    {
      "id": "e6febdb9-370b-478d-b470-d6c2d3314d7b",
      "name": "Edit Fields",
      "type": "n8n-nodes-base.set",
      "position": [
        980,
        540
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "b5e935c5-4973-40a3-adb9-fa76904d2ed9",
              "name": "video_number",
              "type": "number",
              "value": "={{ $('Merge').item.json.video_number }}"
            },
            {
              "id": "e98f417d-123f-4a85-b2f7-64430e7b0250",
              "name": "youtubeId",
              "type": "string",
              "value": "={{ $('Merge').item.json.youtubeId }}"
            },
            {
              "id": "d0ced7fd-c9a3-4a09-bf09-e4b5e45dd03d",
              "name": "title",
              "type": "string",
              "value": "={{ $('Merge').item.json.title }}"
            },
            {
              "id": "31a80e6d-9b02-4d21-b888-1a00c036a04b",
              "name": "summary",
              "type": "string",
              "value": "={{ $json.text }}"
            },
            {
              "id": "ef12f3f2-3d63-4e78-835f-7da004393a07",
              "name": "transcript_text",
              "type": "string",
              "value": "={{ $('Merge').item.json.transcript_text }}"
            },
            {
              "id": "afa841e2-6f8b-4b27-9f28-10368ee32c2e",
              "name": "playlistId",
              "type": "string",
              "value": "={{ $('Update Context Intent').first().json.output.id }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "2736a1e6-a982-4f60-aa8d-658e9a3e9193",
      "name": "AI 에이전트",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        2720,
        480
      ],
      "parameters": {
        "text": "=Please analyze the given \"Transcript summary\" and create a full summary overview, following the below guidelines.\n\n1. Provide a full descriptive break down of the content of each video. Assume the user does not won't or have time to watch such videos, so:\n- Your summary needs to be exhaustive, descriptive, and minimise bullet points\n- Your summary needs to captures all the core concepts while maintaining technical accuracy\n- Your summary will be verbose\n\n2. Consider that the intent of the user is not to watch the videos but rather have all the content required and summaries from on the \"Transcript summary\".\n\n3. Use the tool called `chat_playlist_data`, which can analyze YouTube videos. Use this tool effectively to process video content and generate structured summaries.\n\nUser message:\n{{ $('Chat').item.json.chatInput }}\n\nTranscript summary:\n{{ $('Full Summary').item.json.concatenated_summary }}",
        "agent": "conversationalAgent",
        "options": {},
        "promptType": "define"
      },
      "executeOnce": true,
      "typeVersion": 1.7
    },
    {
      "id": "cf1e5c50-9c89-465f-beca-482cbd9affba",
      "name": "Google Gemini 채팅 모델4",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        2520,
        720
      ],
      "parameters": {
        "options": {},
        "modelName": "models/gemini-2.0-flash"
      },
      "credentials": {
        "googlePalmApi": {
          "id": "2zwuT5znDglBrUCO",
          "name": "Google Gemini(PaLM) Api account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "1cbcec5e-b58c-4fce-b944-08c47a7385db",
      "name": "Delete Collection",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueRegularOutput",
      "position": [
        1340,
        480
      ],
      "parameters": {
        "url": "=https://3114dbb7-bd13-4807-8815-c3c8784f66d6.eu-west-1-0.aws.cloud.qdrant.io/collections/{{ $('Update Context Intent').first().json.playlistID }}/points/delete",
        "method": "POST",
        "options": {},
        "jsonBody": "{\n  \"filter\": {}\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "nodeCredentialType": "qdrantApi"
      },
      "credentials": {
        "qdrantApi": {
          "id": "mb8rw8tmUeP6aPJm",
          "name": "QdrantApi account"
        }
      },
      "executeOnce": true,
      "typeVersion": 4.2
    },
    {
      "id": "16d7eaec-1d98-42dd-89aa-2681a9d1697d",
      "name": "Default Data Loader",
      "type": "@n8n/n8n-nodes-langchain.documentDefaultDataLoader",
      "position": [
        1820,
        700
      ],
      "parameters": {
        "options": {
          "metadata": {
            "metadataValues": [
              {
                "name": "video_number",
                "value": "={{ $input.item.json.video_number }}"
              },
              {
                "name": "=youtubeId",
                "value": "={{ $input.item.json.youtubeId }}"
              },
              {
                "name": "summary",
                "value": "={{ $input.item.json.summary }}"
              },
              {
                "name": "title",
                "value": "={{ $input.item.json.title }}"
              },
              {
                "name": "playlistId",
                "value": "={{ $input.item.json.playlistId }}"
              }
            ]
          }
        }
      },
      "typeVersion": 1
    },
    {
      "id": "d3bc9db2-7618-46fd-b825-2cc0ad45fc22",
      "name": "Chat Buffer 메모리",
      "type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
      "position": [
        -260,
        -40
      ],
      "parameters": {
        "sessionKey": "={{ $('Chat').item.json.sessionId }}",
        "sessionIdType": "customKey",
        "contextWindowLength": 10
      },
      "typeVersion": 1.3
    },
    {
      "id": "fb55b13f-880f-404c-9446-9f8a238c8a5c",
      "name": "Full Summary",
      "type": "n8n-nodes-base.summarize",
      "position": [
        2520,
        480
      ],
      "parameters": {
        "options": {},
        "fieldsToSummarize": {
          "values": [
            {
              "field": "summary",
              "separateBy": "\n",
              "aggregation": "concatenate"
            }
          ]
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "efc2fc99-c738-425e-9ee1-669e378e197f",
      "name": "메모2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -560,
        -400
      ],
      "parameters": {
        "color": 7,
        "width": 1080,
        "height": 900,
        "content": "## RAG & Reply to User Query\n- Retrieves and provides answers to user queries combining retrieval-augmented generation.\n- Processes messages without specific routing rules.\n     "
      },
      "typeVersion": 1
    },
    {
      "id": "0040adf6-2cfc-4b79-ba81-b76740bfd158",
      "name": "메모3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        560,
        -400
      ],
      "parameters": {
        "color": 7,
        "width": 1380,
        "height": 700,
        "content": "## Fetch and prepare Playlist video transcripts data for processing \n- Collects and organizes playlist video transcripts.\n- Prepares data for analysis and summarization."
      },
      "typeVersion": 1
    },
    {
      "id": "59b29fc5-5d88-40c0-a273-9dc71d9f009e",
      "name": "Chat Buffer 메모리1",
      "type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
      "position": [
        2700,
        720
      ],
      "parameters": {
        "sessionKey": "={{ $('Chat').item.json.sessionId }}",
        "sessionIdType": "customKey",
        "contextWindowLength": 10
      },
      "typeVersion": 1.3
    },
    {
      "id": "afb6f6be-d299-402e-a9c6-2c60fbf4974e",
      "name": "YouTube Transcript",
      "type": "n8n-nodes-youtube-transcription-dmr.youtubeTranscripter",
      "position": [
        1160,
        -200
      ],
      "parameters": {
        "videoId": "={{ $json.id }}",
        "continueOnFail": true
      },
      "typeVersion": 1
    },
    {
      "id": "9a43eb4a-9d4c-4fce-b19c-94485aa8af76",
      "name": "메모4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        560,
        340
      ],
      "parameters": {
        "color": 7,
        "width": 640,
        "height": 700,
        "content": "## Summarize & Analyze Transcript\n- Creates summarized data from transcripts."
      },
      "typeVersion": 1
    },
    {
      "id": "676677f0-3dae-4873-a449-92930ced534e",
      "name": "메모5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1240,
        340
      ],
      "parameters": {
        "color": 7,
        "width": 980,
        "height": 700,
        "content": "## Store Embeddings\n- Saves embedded data for future use.\n- Updates current context to maintain the flow of the conversation.     "
      },
      "typeVersion": 1
    },
    {
      "id": "9ecd4d0d-b8bd-4a5d-981f-49fa515c17be",
      "name": "메모6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2260,
        340
      ],
      "parameters": {
        "color": 7,
        "width": 940,
        "height": 880,
        "content": "## First Summary Analysis\n- Conducts initial analysis of summarized data.\n- Return to the user insights from processed transcripts."
      },
      "typeVersion": 1
    },
    {
      "id": "45ae8377-0848-45fb-a7a3-aba8d44e3d35",
      "name": "Message Intent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "onError": "continueRegularOutput",
      "position": [
        -2260,
        -460
      ],
      "parameters": {
        "text": "= {{ $('Chat').item.json.chatInput }}",
        "options": {
          "systemMessage": "=**# YOUR TASK:**\nPlease analyze the user's message and decide if the user has provided the info required - and ALWAYS reply using the **Output format** defined below.\n\n# Output format\nYou use the following JSON structure to reply, don't include anything else, and alway inlude all the fields:\n```\n{\n  \"intent\": PLAYLIST|VIDEO|NONE,\n  \"url\": Youtube Playlist or Video URL or empty string,\n  \"id\": Youtube Playlist or Video ID or empty string,\n  \"limit\": number, default 0,\n  \"status\": Previous context status `{{ $json.context_intent?.status }}` or \"PENDING\"\n}\n```\n\n## INTENT field GUIDELINES:\n\n**Respond with \"PLAYLIST\" if:**\n- The messsage contains a valid Youtube Playlist URL\n\n**Respond with \"VIDEO\" if:**\n- The messsage contains a valid Youtube Video URL\n\n**Respond with \"NONE\" if:**\n- The messsage does not contains a valid Youtube Playlist or Video URL\n\n## LIMIT field GUIDELINE:\nIf the \"Previous Context\" intent or the current intent is a Playlist: Based on current or most recent user message, check if there is an indication of how many videos to process, otherwise default to 0.\n\n## STATUS field GUIDELINE\nIf intent is a Playlist or Video and _different_ from the the \"Previous Context\" then use \"PENDING\" since the user intent is to run a new process. Otherwise use the \"Previous Context\" status value.\n\n\n# Rules for Playlist and Video\n\n## YouTube Playlist URL Definition\n- A URL from www.youtube.com or youtube.com.\n- Contains the query parameter `&list=` followed by a playlist ID.\n- Example: https://www.youtube.com/...&list=PLXXXXXX (where PLXXXXXX is the playlist ID).\n\n## YouTube Video URL Definition\n- A URL from www.youtube.com, youtube.com, or youtu.be.\n- For www.youtube.com or youtube.com, it contains the query parameter `v=` followed by a video ID.\n- For youtu.be, it follows the format https://youtu.be/VIDEO_ID.\n- Examples:\n  - https://www.youtube.com/watch?v=VIDEO_ID (where VIDEO_ID is the video ID).\n  - https://youtu.be/VIDEO_ID\n- IMPORTANT: YouTube Video URL **Does NOT have a query parameter `list=`**\n\n\n# Previous Context\n{{ JSON.stringify($json.context_intent) }}\n"
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "retryOnFail": true,
      "typeVersion": 1.7,
      "alwaysOutputData": true
    },
    {
      "id": "a29403f0-ed5c-465c-a43d-84e8dee69662",
      "name": "구조화된 출력 파서1",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        -2020,
        -220
      ],
      "parameters": {
        "jsonSchemaExample": "{\n  \"intent\": \"PLAYLIST|VIDEO|NONE\",\n  \"url\": \"Youtube Playlist or Video URL or empty string,\",\n  \"id\": \"Youtube Playlist or Video ID or empty string,\",\n  \"limit\": \"number of playlist videos to process or 0\",\n  \"status\": \"PENDING|READY|DONE\"\n}"
      },
      "typeVersion": 1.2
    },
    {
      "id": "b3f43325-aa7b-47f3-8bbb-e27fa0c44a1e",
      "name": "Update Context Intent",
      "type": "n8n-nodes-base.redis",
      "position": [
        -1160,
        -640
      ],
      "parameters": {
        "key": "=context_intent_{{ $('Chat').item.json.sessionId }}",
        "value": "=intent {{ $('Process Status').item.json.output?.intent || null }} url {{ $('Process Status').item.json.output?.url || \"\" }} id {{ $('Process Status').item.json.output?.id || \"\" }} limit {{ $('Process Status').item.json.output?.limit || 0 }} status {{ $('Process Status').item.json.output?.status || 'PENDING'  }}",
        "keyType": "hash",
        "operation": "set",
        "valueIsJSON": false
      },
      "credentials": {
        "redis": {
          "id": "mA0f9F1ROUThyrRW",
          "name": "Redis account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "9c296501-049c-44b5-ae8d-8dda2c523278",
      "name": "Get Previous Context Intent",
      "type": "n8n-nodes-base.redis",
      "onError": "continueRegularOutput",
      "position": [
        -2440,
        -460
      ],
      "parameters": {
        "key": "=context_intent_{{ $('Chat').item.json.sessionId }}",
        "keyType": "hash",
        "options": {
          "dotNotation": false
        },
        "operation": "get",
        "valueIsJSON": false,
        "propertyName": "context_intent"
      },
      "credentials": {
        "redis": {
          "id": "mA0f9F1ROUThyrRW",
          "name": "Redis account"
        }
      },
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "9499d9f2-7d6d-432b-bdde-b4b98b90b224",
      "name": "Route Message Intent",
      "type": "n8n-nodes-base.switch",
      "position": [
        -1700,
        -460
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "PROCESS",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "44e008af-4a1a-429d-adb6-039e74b643a6",
                    "operator": {
                      "type": "boolean",
                      "operation": "true",
                      "singleValue": true
                    },
                    "leftValue": "={{ \n  ($json.output.intent == \"VIDEO\" || $json.output.intent == \"PLAYLIST\")\n  && $json.output.status != \"DONE\" \n}}",
                    "rightValue": "/PLAYLIST|VIDEO/"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "QUERY",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "12641857-945d-4470-968e-f3f805bfe1cd",
                    "operator": {
                      "type": "boolean",
                      "operation": "true",
                      "singleValue": true
                    },
                    "leftValue": "={{ \n  $json.output.intent == \"NONE\" || $json.output.status == \"DONE\"\n}}",
                    "rightValue": "NONE"
                  }
                ]
              },
              "renameOutput": true
            }
          ]
        },
        "options": {
          "fallbackOutput": "extra"
        }
      },
      "typeVersion": 3.2
    },
    {
      "id": "dfd329e8-98b1-4ae8-8cc1-a1a5215b1c09",
      "name": "Process Status",
      "type": "n8n-nodes-base.code",
      "position": [
        -1340,
        -640
      ],
      "parameters": {
        "jsCode": "// Loop over input items and add a new field called 'myNewField' to the JSON of each one\nif ($input.last().json.output.intent == 'VIDEO') {\n  $input.last().json.output.status = 'READY'\n}\n\nelse if ($input.last().json.output.intent == 'PLAYLIST' && parseInt($input.last().json.output.limit) > 0) {\n  $input.last().json.output.status = 'READY'\n}\n\nelse {\n  $input.last().json.output = {\n    intent: $('Default Intent').first().json.output.intent,\n    url: $('Default Intent').first().json.output.url,\n    id: $('Default Intent').first().json.output.id,\n    limit: $('Default Intent').first().json.output.limit,\n    status: 'PENDING',\n  }\n}\n\n\nreturn $input.all();"
      },
      "typeVersion": 2
    },
    {
      "id": "c84c21c6-0948-4628-b7a8-7cd2a5602cdc",
      "name": "심플 메모리",
      "type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
      "position": [
        -2180,
        -220
      ],
      "parameters": {
        "sessionKey": "=intent_{{ $('Chat').item.json.sessionId }}",
        "sessionIdType": "customKey"
      },
      "typeVersion": 1.3
    },
    {
      "id": "8ad2e1d1-b657-47cd-afa5-4fc49dc7e0e6",
      "name": "심플 메모리3",
      "type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
      "position": [
        1040,
        -1180
      ],
      "parameters": {
        "sessionKey": "=pl_n_{{ $('Chat').item.json.sessionId }}",
        "sessionIdType": "customKey"
      },
      "typeVersion": 1.3
    },
    {
      "id": "cf4d7c73-d9b1-42da-9ccc-6abccde4110c",
      "name": "메모7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2540,
        -620
      ],
      "parameters": {
        "color": 7,
        "width": 1080,
        "height": 580,
        "content": "## Message intent routing\n- Retrieves the previous context for continuity.\n- Ensures data integrity before processing.\n- Routes incoming messages based on intent.\n     "
      },
      "typeVersion": 1
    },
    {
      "id": "c0ecf826-b803-421a-aa2a-cb713131fbb7",
      "name": "Google Gemini 채팅 모델6",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        -2340,
        -220
      ],
      "parameters": {
        "options": {},
        "modelName": "models/gemini-2.0-flash-lite"
      },
      "credentials": {
        "googlePalmApi": {
          "id": "2zwuT5znDglBrUCO",
          "name": "Google Gemini(PaLM) Api account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "513a8c71-e982-47df-87bd-1e3d3ae9c613",
      "name": "메모9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1420,
        -1020
      ],
      "parameters": {
        "color": 7,
        "width": 460,
        "height": 580,
        "content": "## Update Context\n- Updates any issues detected in the context.\n- Prepares data for workflow progression.\n     "
      },
      "typeVersion": 1
    },
    {
      "id": "d4a9d7aa-dfee-418f-900a-9649f0405861",
      "name": "메모10",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        800,
        -1480
      ],
      "parameters": {
        "color": 7,
        "width": 480,
        "height": 460,
        "content": "## Ask number of Playlist videos to process"
      },
      "typeVersion": 1
    },
    {
      "id": "f89481a4-64a2-4895-821f-effe48f7d331",
      "name": "Numb of Videos",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        900,
        -1380
      ],
      "parameters": {
        "text": "={{ $('Chat').item.json.chatInput }}",
        "options": {
          "systemMessage": "=**Objective:**\n\nWe are here because the user wants to analyse a playlist in context, but we are missing how many videos he would like to process. Please reply to the user asking user to provide a number.\n\n## Context\n{{ JSON.stringify($json.output) }}"
        },
        "promptType": "define"
      },
      "typeVersion": 1.7
    },
    {
      "id": "bb8fa898-4953-4148-8339-2d205b86fc91",
      "name": "Default Intent",
      "type": "n8n-nodes-base.code",
      "position": [
        -1920,
        -460
      ],
      "parameters": {
        "jsCode": "if(\n  ($('Message Intent').first().json?.output?.intent == 'NONE' \n     || Object.keys($('Message Intent').first().json?.output || {}).length == 0)\n  && Object.keys($('Get Previous Context Intent').first().json.context_intent).length > 0\n) {\n  //use prev context intent\n  if(!$input.first().json.output) {\n    $input.first().json.output = {}\n  }\n  $input.first().json.output.intent = $('Get Previous Context Intent').first().json.context_intent?.intent || \"NONE\";\n  $input.first().json.output.url = $('Get Previous Context Intent').first().json.context_intent?.url || \"\";\n  $input.first().json.output.id = $('Get Previous Context Intent').first().json.context_intent?.id || \"\";\n  $input.first().json.output.limit = $('Get Previous Context Intent').first().json.context_intent?.limit || 0;\n  $input.first().json.output.status = $('Get Previous Context Intent').first().json.context_intent?.status || \"PENDING\";\n} else {\n  // $input.first().json.output.intent = $('Message Intent').first().json.context_intent?.intent || \"NONE\";\n  // $input.first().json.output.url = $('Message Intent').first().json.context_intent?.url || \"\";\n  // $input.first().json.output.id = $('Message Intent').first().json.context_intent?.id || \"\";\n  // $input.first().json.output.limit = $('Message Intent').first().json.context_intent?.limit || 0;\n  // $input.first().json.output.status = $('Message Intent').first().json.context_intent?.status || \"PENDING\";\n}\n\n// else use message intent\n\nreturn $input.all();"
      },
      "typeVersion": 2
    },
    {
      "id": "0f1d1bb6-22c0-4b65-beaf-eaf4401d7550",
      "name": "Playlist 제한",
      "type": "n8n-nodes-base.if",
      "position": [
        160,
        -860
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "6ee01f0a-9533-4fb3-b023-cfcc422d9011",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $('Process Status').item.json.output.intent }}",
              "rightValue": "PLAYLIST"
            },
            {
              "id": "e9575bb2-3c60-498b-b2c7-436b62e5195c",
              "operator": {
                "type": "number",
                "operation": "lte"
              },
              "leftValue": "={{ parseInt($('Process Status').item.json.output.limit) }}",
              "rightValue": 0
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "083c17aa-de83-4f3c-8d71-f665903ce3d5",
      "name": "Playlist or Video",
      "type": "n8n-nodes-base.switch",
      "position": [
        160,
        -640
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "VIDEO",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "cc3ec644-7c3d-4d9f-b7a7-89b85824e3e3",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $('Route Message Intent').item.json.output.intent }}",
                    "rightValue": "VIDEO"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "PLAYLIST",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "33beac83-b96b-4e76-9d18-e22df163ea4d",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $('Route Message Intent').item.json.output.intent }}",
                    "rightValue": "PLAYLIST"
                  }
                ]
              },
              "renameOutput": true
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3.2
    },
    {
      "id": "0626bc2d-9e3a-4a4f-a331-62e8b6c69840",
      "name": "Get Fields for Summary",
      "type": "n8n-nodes-base.code",
      "position": [
        2340,
        480
      ],
      "parameters": {
        "jsCode": "return $('Edit Fields').all();"
      },
      "typeVersion": 2
    },
    {
      "id": "4aaaed18-ce90-4296-aba2-b5fa9492655d",
      "name": "Update Context Process Done1",
      "type": "n8n-nodes-base.redis",
      "position": [
        2040,
        480
      ],
      "parameters": {
        "key": "=context_intent_{{ $('Chat').first().json.sessionId }}",
        "value": "=intent {{ $('Process Status').first().json.output?.intent || null }} url {{ $('Process Status').first().json.output?.url || \"\" }} id {{ $('Process Status').first().json.output?.id || \"\" }} limit {{ $('Process Status').first().json.output?.limit || 0 }} status DONE",
        "keyType": "hash",
        "operation": "set",
        "valueIsJSON": false
      },
      "credentials": {
        "redis": {
          "id": "mA0f9F1ROUThyrRW",
          "name": "Redis account"
        }
      },
      "executeOnce": true,
      "typeVersion": 1
    },
    {
      "id": "d3f71d59-a158-43e2-bfbd-a3bec20dea5b",
      "name": "Google Gemini 채팅 모델8",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        880,
        -1180
      ],
      "parameters": {
        "options": {},
        "modelName": "models/gemini-2.0-flash-thinking-exp"
      },
      "credentials": {
        "googlePalmApi": {
          "id": "2zwuT5znDglBrUCO",
          "name": "Google Gemini(PaLM) Api account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "fa6b8a79-436e-4742-9732-cd5c1b2d3c88",
      "name": "Playlist HTTP 요청",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        660,
        -200
      ],
      "parameters": {
        "url": "={{ $('Update Context Intent').item.json.output.url }}",
        "options": {}
      },
      "typeVersion": 4.2
    },
    {
      "id": "99d6da96-8983-4e7d-8343-b9ac975f5d20",
      "name": "YouTube Transcript1",
      "type": "n8n-nodes-youtube-transcription-dmr.youtubeTranscripter",
      "position": [
        1200,
        -860
      ],
      "parameters": {
        "videoId": "={{ $('Update Context Intent').item.json.output.id }}",
        "continueOnFail": true
      },
      "typeVersion": 1
    },
    {
      "id": "41a07802-3fba-42fa-8482-f526a7e1b173",
      "name": "Video HTTP 요청",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        900,
        -860
      ],
      "parameters": {
        "url": "={{ $('Update Context Intent').item.json.output.url }}",
        "options": {}
      },
      "typeVersion": 4.2
    },
    {
      "id": "02103114-9c22-49b1-9dee-746b84cdef66",
      "name": "Get Title and Desc",
      "type": "n8n-nodes-base.code",
      "position": [
        1200,
        -640
      ],
      "parameters": {
        "jsCode": "/**\n * This code node contains a modified version of play-dl,\n * which is licensed under the GNU General Public License Version 3 (GPLv3).\n *\n * Original Library Name: play-dl\n * Original Library Source: https://github.com/play-dl/play-dl/tree/main\n * Original Library License: GNU General Public License Version 3 (GPLv3)\n * (See: https://www.gnu.org/licenses/gpl-3.0.en.html)\n *\n * Modifications were made to the original library for use within this N8N workflow.\n * These modifications are also licensed under the GNU General Public License Version 3 (GPLv3).\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <https://www.gnu.org/licenses/>.\n */\n\n\n/**\n * Basic function to get specific data (title, description, duration)\n * from pre-fetched HTML body data of a YouTube video page.\n * Assumes the HTML body is passed as the first argument.\n *\n * @param {string} body HTML body data of the YouTube video page.\n * @param {string} video_id YouTube video ID.\n * @param {string} url YouTube video URL.\n * @returns {Promise<{title: string, description: string, duration: number}>} Video Basic Info.\n * @throws {Error} If video ID cannot be extracted, captcha is detected,\n * or necessary data cannot be parsed.\n */\nasync function video_basic_info(body, video_id, url) {\n  // --- Input Validation ---\n  if (typeof body !== 'string') {\n    throw new Error('body parameter must be a string of HTML');\n  }\n  if (typeof video_id !== 'string' || !video_id.trim()) {\n    throw new Error('video_id parameter must be a non-empty string');\n  }\n  if (typeof url !== 'string' || !url.trim()) {\n    throw new Error('url parameter must be a non-empty URL string');\n  }\n\n  // --- Captcha Check ---\n  // Added check for consent page as well\n  if (body.includes('Our systems have detected unusual traffic') || body.includes('consent.google.com')) {\n    throw new Error('Captcha or Consent page encountered: YouTube likely requires interaction or detected bot-like activity.');\n  }\n\n  // --- Extract Player Data ---\n  let player_data;\n  try {\n    // More robust regex to find ytInitialPlayerResponse, stopping at the next semicolon\n    const player_data_match = body.match(/var ytInitialPlayerResponse\\s*=\\s*({.+?});\\s*(?:var |<\\/script)/);\n    if (!player_data_match || !player_data_match[1]) {\n      // Fallback attempt with simpler split (less reliable)\n      const split_data = body.split('var ytInitialPlayerResponse = ');\n      player_data = split_data?.[1]?.split(';</script>')?.[0];\n    } else {\n      player_data = player_data_match[1];\n    }\n\n    if (!player_data) {\n      // Check for common failure indicators in the HTML if data isn't found\n      if (body.includes('<title>YouTube</title>') && !body.includes('videoDetails')) {\n        throw new Error('Could not find ytInitialPlayerResponse data. The page might be a generic YouTube page, not a video page, or the structure changed.');\n      }\n      throw new Error('Could not find ytInitialPlayerResponse data.');\n    }\n  } catch (error) {\n    console.log(\"Error during player_data extraction:\", error);\n    throw new Error(`Failed during player data extraction: ${error}`);\n  }\n\n\n  let player_response;\n  try {\n    player_response = JSON.parse(player_data);\n  } catch (e) {\n    console.log(\"Raw player_data that failed parsing:\", player_data.substring(0, 500) + '...'); // Log start of data\n    throw new Error(`Failed to parse ytInitialPlayerResponse JSON: ${e}`);\n  }\n\n  // --- Extract Required Video Details ---\n  // Use optional chaining for safety\n  const vid = player_response?.videoDetails;\n\n  // Add more robust checking, including playability status\n  if (!vid) {\n    const playabilityStatus = player_response?.playabilityStatus;\n    let reason = \"videoDetails object not found in the response.\";\n    if (playabilityStatus?.status && playabilityStatus.status !== 'OK') {\n      reason = ` Playability status: ${playabilityStatus.status}. Reason: ${playabilityStatus.reason ||\n        playabilityStatus.errorScreen?.playerErrorMessageRenderer?.reason?.simpleText ||\n        playabilityStatus.errorScreen?.playerKavRenderer?.reason?.simpleText ||\n        'No specific reason provided.'\n        }`;\n    } else if (playabilityStatus?.status === 'OK' && !vid) {\n      reason = \" Playability status is OK, but videoDetails is still missing. Response structure might have changed.\";\n    }\n    throw new Error(`Could not get video details. ${reason}`);\n  }\n\n  // --- Return Simplified Data ---\n  // Ensure values exist before accessing, provide defaults if necessary\n  return {\n    title: vid.title || 'N/A',\n    description: vid.shortDescription || '', // Default to empty string if missing\n    duration: Number(vid.lengthSeconds) || 0, // Default to 0 if missing/invalid\n  };\n}\n\n\nreturn video_basic_info($input.first().json.data, $('Update Context Intent').first().json.output.id, $('Update Context Intent').first().json.output.url);"
      },
      "retryOnFail": true,
      "typeVersion": 2,
      "alwaysOutputData": true,
      "waitBetweenTries": 500
    },
    {
      "id": "6cea694e-0147-4cd0-a601-9b232813a1d3",
      "name": "분할 출력2",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        1440,
        -860
      ],
      "parameters": {
        "include": "selectedOtherFields",
        "options": {},
        "fieldToSplitOut": "transcript",
        "fieldsToInclude": "youtubeId"
      },
      "typeVersion": 1
    },
    {
      "id": "c479fb51-e17d-477a-b40b-65458cc3e679",
      "name": "Concatenate1",
      "type": "n8n-nodes-base.summarize",
      "position": [
        1660,
        -860
      ],
      "parameters": {
        "options": {},
        "fieldsToSplitBy": "youtubeId",
        "fieldsToSummarize": {
          "values": [
            {
              "field": "transcript.text",
              "separateBy": " ",
              "aggregation": "concatenate"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "ccca5021-248b-4a98-af6b-ee92b2d63dca",
      "name": "메모12",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        800,
        -1000
      ],
      "parameters": {
        "color": 7,
        "width": 1140,
        "height": 560,
        "content": "## Fetch and prepare single video transcripts data for processing\n- Retrieves and pre-processes single video transcripts.\n- Prepares data for analysis and summarization.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "1e9ecc6e-2b4d-4ae8-8949-d4b92eaf9287",
      "name": "Get Videos",
      "type": "n8n-nodes-base.code",
      "position": [
        1520,
        480
      ],
      "parameters": {
        "jsCode": "return $('Edit Fields').all();"
      },
      "typeVersion": 2
    },
    {
      "id": "f8ea7a40-b1f9-4dc2-959d-0e765331b191",
      "name": "Get Playlist Videos Data",
      "type": "n8n-nodes-base.code",
      "position": [
        860,
        -200
      ],
      "parameters": {
        "jsCode": "/**\n * This code node contains a modified version of play-dl,\n * which is licensed under the GNU General Public License Version 3 (GPLv3).\n *\n * Original Library Name: play-dl\n * Original Library Source: https://github.com/play-dl/play-dl/tree/main\n * Original Library License: GNU General Public License Version 3 (GPLv3)\n * (See: https://www.gnu.org/licenses/gpl-3.0.en.html)\n *\n * Modifications were made to the original library for use within this N8N workflow.\n * These modifications are also licensed under the GNU General Public License Version 3 (GPLv3).\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program.  If not, see <https://www.gnu.org/licenses/>.\n */\n\n\n/**\n * Gets YouTube playlist info from a playlist url.\n *\n * Example\n * ```js\n * const playlist = await play.playlist_info('youtube playlist url')\n *\n * const playlist = await play.playlist_info('youtube playlist url', { incomplete : true })\n * ```\n * @param body HTML body of the playlist page\n * @param url Playlist URL\n * @returns YouTube Playlist\n */\nfunction playlist_info(body, url) {\n  let url_ = url.trim();\n  if (body.indexOf('Our systems have detected unusual traffic from your computer network.') !== -1)\n    throw new Error('Captcha page: YouTube has detected that you are a bot!');\n\n  const response = JSON.parse(\n    body\n      .split('var ytInitialData = ')[1]\n      .split(';</script>')[0]\n      .split(/;\\s*(var|const|let)\\s/)[0]\n  );\n\n  if (response.alerts) {\n    if (response.alerts[0].alertWithButtonRenderer?.type === 'INFO') {\n      throw new Error(\n        `While parsing playlist url\\n${response.alerts[0].alertWithButtonRenderer.text.simpleText}`\n      );\n    } else if (response.alerts[0].alertRenderer?.type === 'ERROR')\n      throw new Error(`While parsing playlist url\\n${response.alerts[0].alertRenderer.text.runs[0].text}`);\n    else throw new Error('While parsing playlist url\\nUnknown Playlist Error');\n  }\n  if (response.currentVideoEndpoint) {\n    return getWatchPlaylist(response, body, url_);\n  } else return getNormalPlaylist(response, body);\n}\n\n/**\n * Function to parse Playlist from YouTube search\n * @param data html data of that request\n * @param limit No. of videos to parse\n * @returns Array of YouTube Video objects.\n */\nfunction getPlaylistVideos(data, limit = Infinity) {\n  const videos = [];\n\n  for (let i = 0; i < data.length; i++) {\n    if (limit === videos.length) break;\n    const info = data[i].playlistVideoRenderer;\n    if (!info || !info.shortBylineText) continue;\n\n    videos.push({\n      id: info.videoId,\n      duration: parseInt(info.lengthSeconds) || 0,\n      duration_raw: info.lengthText?.simpleText ?? '0:00',\n      thumbnails: info.thumbnail.thumbnails,\n      title: info.title.runs[0].text,\n      upcoming: info.upcomingEventData?.startTime\n        ? new Date(parseInt(info.upcomingEventData.startTime) * 1000)\n        : undefined,\n      channel: {\n        id: info.shortBylineText.runs[0].navigationEndpoint.browseEndpoint.browseId || undefined,\n        name: info.shortBylineText.runs[0].text || undefined,\n        url: `https://www.youtube.com${info.shortBylineText.runs[0].navigationEndpoint.browseEndpoint.canonicalBaseUrl ||\n          info.shortBylineText.runs[0].navigationEndpoint.commandMetadata.webCommandMetadata.url\n          }`,\n        icon: undefined\n      }\n    });\n  }\n  return videos;\n}\n\n\nfunction getWatchPlaylist(response, body, url) {\n  const playlist_details = response.contents.twoColumnWatchNextResults.playlist?.playlist;\n  if (!playlist_details)\n    throw new Error(\"Watch playlist unavailable due to YouTube layout changes.\")\n\n  const videos = getWatchPlaylistVideos(playlist_details.contents);\n  const videoCount = playlist_details.totalVideos;\n  const channel = playlist_details.shortBylineText?.runs?.[0];\n  const badge = playlist_details.badges?.[0]?.metadataBadgeRenderer?.style.toLowerCase();\n\n  return {\n    id: playlist_details.playlistId || '',\n    title: playlist_details.title || '',\n    videoCount: parseInt(videoCount) || 0,\n    videos: videos,\n    url: url,\n    channel: {\n      id: channel?.navigationEndpoint?.browseEndpoint?.browseId || null,\n      name: channel?.text || null,\n      url: `https://www.youtube.com${channel?.navigationEndpoint?.browseEndpoint?.canonicalBaseUrl ||\n        channel?.navigationEndpoint?.commandMetadata?.webCommandMetadata?.url\n        }`,\n      verified: Boolean(badge?.includes('verified')),\n      artist: Boolean(badge?.includes('artist'))\n    }\n  };\n}\n\nfunction getNormalPlaylist(response, body) {\n  const json_data =\n    response.contents.twoColumnBrowseResultsRenderer.tabs[0].tabRenderer.content.sectionListRenderer.contents[0]\n      .itemSectionRenderer.contents[0].playlistVideoListRenderer.contents;\n  const playlist_details = response.sidebar.playlistSidebarRenderer.items;\n  const videos = getPlaylistVideos(json_data, 100);\n\n  const data = playlist_details[0].playlistSidebarPrimaryInfoRenderer;\n  if (!data.title.runs || !data.title.runs.length) throw new Error('Failed to Parse Playlist info.');\n\n  const author = playlist_details[1]?.playlistSidebarSecondaryInfoRenderer.videoOwner;\n  const views = data.stats.length === 3 ? data.stats[1].simpleText.replace(/\\D/g, '') : 0;\n  const lastUpdate =\n    data.stats\n      .find((x) => 'runs' in x && x['runs'].find((y) => y.text.toLowerCase().includes('last update')))\n      ?.runs.pop()?.text ?? null;\n  const videosCount = data.stats[0].runs[0].text.replace(/\\D/g, '') || 0;\n\n  return {\n    id: data.title.runs[0].navigationEndpoint.watchEndpoint.playlistId,\n    title: data.title.runs[0].text,\n    videoCount: parseInt(videosCount) || 0,\n    lastUpdate: lastUpdate,\n    views: parseInt(views) || 0,\n    videos: videos,\n    url: `https://www.youtube.com/playlist?list=${data.title.runs[0].navigationEndpoint.watchEndpoint.playlistId}`,\n    link: `https://www.youtube.com${data.title.runs[0].navigationEndpoint.commandMetadata.webCommandMetadata.url}`,\n    channel: author\n      ? {\n        name: author.videoOwnerRenderer.title.runs[0].text,\n        id: author.videoOwnerRenderer.title.runs[0].navigationEndpoint.browseEndpoint.browseId,\n        url: `https://www.youtube.com${author.videoOwnerRenderer.navigationEndpoint.commandMetadata.webCommandMetadata.url ||\n          author.videoOwnerRenderer.navigationEndpoint.browseEndpoint.canonicalBaseUrl\n          }`,\n        icons: author.videoOwnerRenderer.thumbnail.thumbnails ?? []\n      }\n      : {},\n    thumbnail: data.thumbnailRenderer.playlistVideoThumbnailRenderer?.thumbnail.thumbnails.length\n      ? data.thumbnailRenderer.playlistVideoThumbnailRenderer.thumbnail.thumbnails[\n      data.thumbnailRenderer.playlistVideoThumbnailRenderer.thumbnail.thumbnails.length - 1\n      ]\n      : null\n  };\n}\n\nfunction parseDuration(text) {\n  if (!text) return 0;\n  const split = text.split(':');\n\n  switch (split.length) {\n    case 2:\n      return parseInt(split[0]) * 60 + parseInt(split[1]);\n\n    case 3:\n      return parseInt(split[0]) * 60 * 60 + parseInt(split[1]) * 60 + parseInt(split[2]);\n\n    default:\n      return 0;\n  }\n}\n\nfunction getWatchPlaylistVideos(data, limit = Infinity) {\n  const videos = [];\n\n  for (let i = 0; i < data.length; i++) {\n    if (limit === videos.length) break;\n    const info = data[i].playlistPanelVideoRenderer;\n    if (!info || !info.shortBylineText) continue;\n    const channel_info = info.shortBylineText.runs[0];\n\n    videos.push({\n      id: info.videoId,\n      duration: parseDuration(info.lengthText?.simpleText) || 0,\n      duration_raw: info.lengthText?.simpleText ?? '0:00',\n      thumbnails: info.thumbnail.thumbnails,\n      title: info.title.simpleText,\n      upcoming:\n        info.thumbnailOverlays[0].thumbnailOverlayTimeStatusRenderer?.style === 'UPCOMING' || undefined,\n      channel: {\n        id: channel_info.navigationEndpoint.browseEndpoint.browseId || undefined,\n        name: channel_info.text || undefined,\n        url: `https://www.youtube.com${channel_info.navigationEndpoint.browseEndpoint.canonicalBaseUrl ||\n          channel_info.navigationEndpoint.commandMetadata.webCommandMetadata.url\n          }`,\n        icon: undefined\n      }\n    });\n  }\n\n  return videos;\n}\n\n\nreturn playlist_info($input.first().json.data, $('Update Context Intent').first().json.output.url);"
      },
      "retryOnFail": true,
      "typeVersion": 2,
      "alwaysOutputData": true,
      "waitBetweenTries": 500
    },
    {
      "id": "71b60b8e-06df-45a8-85a3-7b9e938fb6f0",
      "name": "Google Gemini 임베딩2",
      "type": "@n8n/n8n-nodes-langchain.embeddingsGoogleGemini",
      "position": [
        2640,
        1060
      ],
      "parameters": {
        "modelName": "models/text-embedding-004"
      },
      "credentials": {
        "googlePalmApi": {
          "id": "2zwuT5znDglBrUCO",
          "name": "Google Gemini(PaLM) Api account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "58feccf5-1b97-4c88-b274-444e177f4515",
      "name": "Qdrant 벡터 스토어3",
      "type": "@n8n/n8n-nodes-langchain.vectorStoreQdrant",
      "position": [
        -100,
        160
      ],
      "parameters": {
        "options": {},
        "qdrantCollection": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Default Intent').first().json.output?.id }}"
        }
      },
      "credentials": {
        "qdrantApi": {
          "id": "mb8rw8tmUeP6aPJm",
          "name": "QdrantApi account"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "6cff2236-3e78-4e8c-bb3d-5140f106c530",
      "name": "Answer questions with a vector store",
      "type": "@n8n/n8n-nodes-langchain.toolVectorStore",
      "position": [
        180,
        -40
      ],
      "parameters": {
        "name": "chat_playlist_data",
        "topK": 10,
        "description": "=Retrive data about the Playlist or Video from the vector store.\nplaylistId or youtubeId: {{ $('Default Intent').item.json.output?.id }}\n\n**User Message:**\n{{ $('Chat').item.json.chatInput }}"
      },
      "typeVersion": 1
    },
    {
      "id": "312081d9-9279-4700-a432-e9f878d5361e",
      "name": "Qdrant 벡터 스토어4",
      "type": "@n8n/n8n-nodes-langchain.vectorStoreQdrant",
      "position": [
        2700,
        900
      ],
      "parameters": {
        "options": {},
        "qdrantCollection": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Default Intent').first().json.output?.id }}"
        }
      },
      "credentials": {
        "qdrantApi": {
          "id": "mb8rw8tmUeP6aPJm",
          "name": "QdrantApi account"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "f5cba8b5-226d-4b0a-8cb6-a51728ac8247",
      "name": "Answer questions with a vector store1",
      "type": "@n8n/n8n-nodes-langchain.toolVectorStore",
      "position": [
        2860,
        700
      ],
      "parameters": {
        "name": "chat_playlist_data",
        "topK": 6,
        "description": "=User Message:\n{{ $('Chat').item.json.chatInput }}"
      },
      "typeVersion": 1
    },
    {
      "id": "22f18788-b47f-4187-9146-28e6de5ec7a6",
      "name": "Google Gemini 채팅 모델",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        3000,
        900
      ],
      "parameters": {
        "options": {},
        "modelName": "models/gemini-2.0-flash"
      },
      "credentials": {
        "googlePalmApi": {
          "id": "2zwuT5znDglBrUCO",
          "name": "Google Gemini(PaLM) Api account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "2aa52dd2-169b-43dc-8202-1d60f5fd55c0",
      "name": "Google Gemini 채팅 모델3",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        220,
        160
      ],
      "parameters": {
        "options": {},
        "modelName": "models/gemini-2.0-flash"
      },
      "credentials": {
        "googlePalmApi": {
          "id": "2zwuT5znDglBrUCO",
          "name": "Google Gemini(PaLM) Api account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "d96d3670-ab95-4afc-a275-33f03383a204",
      "name": "Qdrant 벡터 스토어2",
      "type": "@n8n/n8n-nodes-langchain.vectorStoreQdrant",
      "position": [
        -820,
        -880
      ],
      "parameters": {
        "mode": "load",
        "prompt": "Are there any documents in the store?",
        "options": {},
        "qdrantCollection": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Process Status').item.json.output?.id }}"
        }
      },
      "credentials": {
        "qdrantApi": {
          "id": "mb8rw8tmUeP6aPJm",
          "name": "QdrantApi account"
        }
      },
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "7c289d61-09b2-461e-b771-8781f60828c7",
      "name": "Google Gemini 임베딩4",
      "type": "@n8n/n8n-nodes-langchain.embeddingsGoogleGemini",
      "position": [
        -840,
        -640
      ],
      "parameters": {
        "modelName": "models/text-embedding-004"
      },
      "credentials": {
        "googlePalmApi": {
          "id": "2zwuT5znDglBrUCO",
          "name": "Google Gemini(PaLM) Api account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "59be01b0-3ff9-4cc2-b569-c0cb4dcae3ec",
      "name": "If",
      "type": "n8n-nodes-base.if",
      "position": [
        -260,
        -880
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "795da689-23c3-49d5-a312-ca18e2c9d5e3",
              "operator": {
                "type": "number",
                "operation": "gt"
              },
              "leftValue": "={{ $json.count_document }}",
              "rightValue": 0
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "ab9bc74d-9659-44fe-aa08-4878609ef808",
      "name": "Count Content",
      "type": "n8n-nodes-base.summarize",
      "position": [
        -460,
        -880
      ],
      "parameters": {
        "options": {},
        "fieldsToSummarize": {
          "values": [
            {
              "field": "document"
            }
          ]
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "5c953435-1052-4e1c-9d2f-2439ba944b28",
      "name": "메모",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        20,
        -1020
      ],
      "parameters": {
        "color": 7,
        "width": 500,
        "height": 580,
        "content": "## Process or ask for more details\n- Decides next steps based on workflow conditions e.g. missing number of playlist videos to process.\n- Route to Playlist or Video processing."
      },
      "typeVersion": 1
    },
    {
      "id": "78760cd2-74db-482d-b660-bd53a3184b95",
      "name": "메모1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -920,
        -1020
      ],
      "parameters": {
        "color": 7,
        "width": 880,
        "height": 580,
        "content": "## Already Processed? \n- Check if we already have embeddings in the vector store."
      },
      "typeVersion": 1
    },
    {
      "id": "a8dc1b1e-2ba9-4b85-9f2f-c3d07ec67c32",
      "name": "Update Context Intent1",
      "type": "n8n-nodes-base.redis",
      "position": [
        -460,
        -640
      ],
      "parameters": {
        "key": "=context_intent_{{ $('Chat').item.json.sessionId }}",
        "value": "=intent {{ $('Process Status').item.json.output?.intent || null }} url {{ $('Process Status').item.json.output?.url || \"\" }} id {{ $('Process Status').item.json.output?.id || \"\" }} limit {{ $('Process Status').item.json.output?.limit || 0 }} status DONE",
        "keyType": "hash",
        "operation": "set",
        "valueIsJSON": false
      },
      "credentials": {
        "redis": {
          "id": "mA0f9F1ROUThyrRW",
          "name": "Redis account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "36ea2e25-8d29-4ec6-bc6a-15c98153c390",
      "name": "메모8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2540,
        20
      ],
      "parameters": {
        "width": 1080,
        "height": 1320,
        "content": "# AI-Powered YouTube Playlist & Video Summarization and Analysis Chat Bot\n\nThis N8N workflow transforms YouTube playlists or individual videos into interactive knowledge bases. Instead of watching videos, users can chat with the workflow to get summaries and answers based on the video transcripts.\n\n## How it Works:\n\n1.  **Chat Interaction & Intent Detection:**\n    * The workflow starts via a chat interface (`Chat Trigger`), prompting the user for a YouTube playlist or video URL.\n    * It retrieves any previous conversation context stored in Redis.\n    * A Google Gemini AI agent (`Message Intent`) analyzes the user's input to determine if it contains a valid YouTube playlist URL, a video URL, or neither (`NONE`). It extracts the URL, the corresponding ID (Playlist ID or Video ID), and checks if the user specified a limit for the number of playlist videos to process.\n    * The workflow maintains context (like the current URL, ID, and processing status) using Redis (`Update Context Intent`, `Get Previous Context Intent`).\n\n2.  **Routing & Pre-processing Checks:**\n    * Based on the detected intent and whether the content needs processing, a `Switch` node (`Route Message Intent`) directs the workflow.\n    * If a valid URL is provided and hasn't been processed yet (`status != 'DONE'`), it proceeds to the processing pipeline.\n    * It checks if embeddings for the given ID already exist in the Qdrant vector store (`Qdrant Vector Store2`, `If`). If they do, it skips processing and moves to the query handling stage.\n    * If the input is a playlist URL but no video limit is specified (`limit=0`), it prompts the user to provide one (`Numb of Videos` agent).\n\n3.  **Video/Playlist Processing Pipeline:**\n    * **Data Fetching:**\n        * For **Playlists**: Fetches the playlist page (`Playlist HTTP Request`), extracts video details using custom code (`Get Playlist Videos Data`), limits the videos if specified (`Limit`), and then fetches the transcript for each video (`YouTube Transcript`).\n        * For **Videos**: Fetches the video page (`Video HTTP Request`), extracts title/description (`Get Title and Desc`), and fetches the transcript (`YouTube Transcript1`).\n    * **Transcript Processing & Summarization:**\n        * Transcripts are retrieved using the `youtubeTranscripter` node.\n        * Transcripts are concatenated (`Concatenate`, `Concatenate1`).\n        * Data (like video ID, title, transcript text) is merged and structured (`Merge`, `Edit Fields`).\n        * Each video's transcript is summarized by a Google Gemini AI chain (`Summarize & Analyze Transcript`).\n    * **Embedding & Storage:**\n        * Any existing data for the playlist/video ID is cleared from the Qdrant vector store (`Delete Collection`).\n        * The processed transcripts (potentially alongside summaries/metadata) are loaded (`Default Data Loader`).\n        * Text is split into manageable chunks (`Recursive Character Text Splitter`).\n        * Google Gemini generates vector embeddings for the text chunks (`Embeddings Google Gemini`).\n        * These embeddings are stored in a Qdrant collection, indexed by the playlist or video ID (`Qdrant Vector Store`).\n    * **Status Update & Final Summary:**\n        * The context status in Redis is updated to 'DONE' (`Update Context Process Done1`).\n        * All individual video summaries are combined (`Full Summary`).\n        * An AI agent (`AI Agent`) may generate a final, comprehensive summary or response based on the processed data, using a tool to query the vector store (`Answer questions with a vector store1`).\n\n4.  **Query Handling (Chatting with Content):**\n    * If the user's input is identified as a query rather than a new URL to process (or if processing for a URL is complete), the workflow activates the main query handler.\n    * A conversational AI agent (`Handle Queries`), powered by Google Gemini and equipped with chat memory (`Chat Buffer Memory`), answers user questions.\n    * This agent uses a specialized tool (`Answer questions with a vector store`) that retrieves relevant information directly from the Qdrant vector store based on the user's query and the stored embeddings."
      },
      "typeVersion": 1
    }
  ],
  "active": true,
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "7c1d0978-ccea-4618-bcbf-560b34f77023",
  "connections": {
    "59be01b0-3ff9-4cc2-b569-c0cb4dcae3ec": {
      "main": [
        [
          {
            "node": "a8dc1b1e-2ba9-4b85-9f2f-c3d07ec67c32",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Playlist Limit",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "c33ceeca-9bf0-4dd2-b8df-fc2a1ccdf512": {
      "main": [
        [
          {
            "node": "9c296501-049c-44b5-ae8d-8dda2c523278",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Limit": {
      "main": [
        [
          {
            "node": "afb6f6be-d299-402e-a9c6-2c60fbf4974e",
            "type": "main",
            "index": 0
          },
          {
            "node": "06bb2dfd-027c-4902-9559-2de080f6c145",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge": {
      "main": [
        [
          {
            "node": "Summarize & Analyze Transcript",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Out": {
      "main": [
        [
          {
            "node": "036765df-6da4-4430-bcea-af4066fb7c24",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "1e9ecc6e-2b4d-4ae8-8949-d4b92eaf9287": {
      "main": [
        [
          {
            "node": "Qdrant Vector Store",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Out1": {
      "main": [
        [
          {
            "node": "Limit",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Out2": {
      "main": [
        [
          {
            "node": "c479fb51-e17d-477a-b40b-65458cc3e679",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "036765df-6da4-4430-bcea-af4066fb7c24": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "e6febdb9-370b-478d-b470-d6c2d3314d7b": {
      "main": [
        [
          {
            "node": "1cbcec5e-b58c-4fce-b944-08c47a7385db",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "c479fb51-e17d-477a-b40b-65458cc3e679": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "fb55b13f-880f-404c-9446-9f8a238c8a5c": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "06bb2dfd-027c-4902-9559-2de080f6c145": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "ab9bc74d-9659-44fe-aa08-4878609ef808": {
      "main": [
        [
          {
            "node": "59be01b0-3ff9-4cc2-b569-c0cb4dcae3ec",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Simple Memory": {
      "ai_memory": [
        [
          {
            "node": "45ae8377-0848-45fb-a7a3-aba8d44e3d35",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "bb8fa898-4953-4148-8339-2d205b86fc91": {
      "main": [
        [
          {
            "node": "9499d9f2-7d6d-432b-bdde-b4b98b90b224",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "45ae8377-0848-45fb-a7a3-aba8d44e3d35": {
      "main": [
        [
          {
            "node": "bb8fa898-4953-4148-8339-2d205b86fc91",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "Playlist Limit": {
      "main": [
        [
          {
            "node": "f89481a4-64a2-4895-821f-effe48f7d331",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "083c17aa-de83-4f3c-8d71-f665903ce3d5",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "dfd329e8-98b1-4ae8-8cc1-a1a5215b1c09": {
      "main": [
        [
          {
            "node": "b3f43325-aa7b-47f3-8bbb-e27fa0c44a1e",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Simple Memory3": {
      "ai_memory": [
        [
          {
            "node": "f89481a4-64a2-4895-821f-effe48f7d331",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "1cbcec5e-b58c-4fce-b944-08c47a7385db": {
      "main": [
        [
          {
            "node": "1e9ecc6e-2b4d-4ae8-8949-d4b92eaf9287",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "083c17aa-de83-4f3c-8d71-f665903ce3d5": {
      "main": [
        [
          {
            "node": "Video HTTP Request",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Playlist HTTP Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Chat Buffer Memory": {
      "ai_memory": [
        [
          {
            "node": "5da369db-b801-4653-888d-0e6042620298",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "02103114-9c22-49b1-9dee-746b84cdef66": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Video HTTP Request": {
      "main": [
        [
          {
            "node": "99d6da96-8983-4e7d-8343-b9ac975f5d20",
            "type": "main",
            "index": 0
          },
          {
            "node": "02103114-9c22-49b1-9dee-746b84cdef66",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "afb6f6be-d299-402e-a9c6-2c60fbf4974e": {
      "main": [
        [
          {
            "node": "Split Out",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Chat Buffer Memory1": {
      "ai_memory": [
        [
          {
            "node": "AI Agent",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "16d7eaec-1d98-42dd-89aa-2681a9d1697d": {
      "ai_document": [
        [
          {
            "node": "Qdrant Vector Store",
            "type": "ai_document",
            "index": 0
          }
        ]
      ]
    },
    "Qdrant Vector Store": {
      "main": [
        [
          {
            "node": "4aaaed18-ce90-4296-aba2-b5fa9492655d",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "99d6da96-8983-4e7d-8343-b9ac975f5d20": {
      "main": [
        [
          {
            "node": "Split Out2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Qdrant Vector Store2": {
      "main": [
        [
          {
            "node": "ab9bc74d-9659-44fe-aa08-4878609ef808",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Qdrant Vector Store3": {
      "ai_tool": [
        []
      ],
      "ai_vectorStore": [
        [
          {
            "node": "6cff2236-3e78-4e8c-bb3d-5140f106c530",
            "type": "ai_vectorStore",
            "index": 0
          }
        ]
      ]
    },
    "Qdrant Vector Store4": {
      "ai_vectorStore": [
        [
          {
            "node": "f5cba8b5-226d-4b0a-8cb6-a51728ac8247",
            "type": "ai_vectorStore",
            "index": 0
          }
        ]
      ]
    },
    "9499d9f2-7d6d-432b-bdde-b4b98b90b224": {
      "main": [
        [
          {
            "node": "dfd329e8-98b1-4ae8-8cc1-a1a5215b1c09",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "5da369db-b801-4653-888d-0e6042620298",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "5da369db-b801-4653-888d-0e6042620298",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Playlist HTTP Request": {
      "main": [
        [
          {
            "node": "f8ea7a40-b1f9-4dc2-959d-0e765331b191",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "b3f43325-aa7b-47f3-8bbb-e27fa0c44a1e": {
      "main": [
        [
          {
            "node": "Qdrant Vector Store2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "0626bc2d-9e3a-4a4f-a331-62e8b6c69840": {
      "main": [
        [
          {
            "node": "fb55b13f-880f-404c-9446-9f8a238c8a5c",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "a8dc1b1e-2ba9-4b85-9f2f-c3d07ec67c32": {
      "main": [
        [
          {
            "node": "5da369db-b801-4653-888d-0e6042620298",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Embeddings Google Gemini": {
      "ai_embedding": [
        [
          {
            "node": "Qdrant Vector Store",
            "type": "ai_embedding",
            "index": 0
          }
        ]
      ]
    },
    "f8ea7a40-b1f9-4dc2-959d-0e765331b191": {
      "main": [
        [
          {
            "node": "Split Out1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "f5cba8b5-226d-4b0a-8cb6-a51728ac8247",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Embeddings Google Gemini1": {
      "ai_embedding": [
        [
          {
            "node": "Qdrant Vector Store3",
            "type": "ai_embedding",
            "index": 0
          }
        ]
      ]
    },
    "Embeddings Google Gemini2": {
      "ai_embedding": [
        [
          {
            "node": "Qdrant Vector Store4",
            "type": "ai_embedding",
            "index": 0
          }
        ]
      ]
    },
    "Embeddings Google Gemini4": {
      "ai_embedding": [
        [
          {
            "node": "Qdrant Vector Store2",
            "type": "ai_embedding",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model1": {
      "ai_languageModel": [
        [
          {
            "node": "5da369db-b801-4653-888d-0e6042620298",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model2": {
      "ai_languageModel": [
        [
          {
            "node": "Summarize & Analyze Transcript",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model3": {
      "ai_languageModel": [
        [
          {
            "node": "6cff2236-3e78-4e8c-bb3d-5140f106c530",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model4": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model6": {
      "ai_languageModel": [
        [
          {
            "node": "45ae8377-0848-45fb-a7a3-aba8d44e3d35",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model8": {
      "ai_languageModel": [
        [
          {
            "node": "f89481a4-64a2-4895-821f-effe48f7d331",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser1": {
      "ai_outputParser": [
        [
          {
            "node": "45ae8377-0848-45fb-a7a3-aba8d44e3d35",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "9c296501-049c-44b5-ae8d-8dda2c523278": {
      "main": [
        [
          {
            "node": "45ae8377-0848-45fb-a7a3-aba8d44e3d35",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "4aaaed18-ce90-4296-aba2-b5fa9492655d": {
      "main": [
        [
          {
            "node": "0626bc2d-9e3a-4a4f-a331-62e8b6c69840",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Summarize & Analyze Transcript": {
      "main": [
        [
          {
            "node": "e6febdb9-370b-478d-b470-d6c2d3314d7b",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Recursive Character Text Splitter": {
      "ai_textSplitter": [
        [
          {
            "node": "16d7eaec-1d98-42dd-89aa-2681a9d1697d",
            "type": "ai_textSplitter",
            "index": 0
          }
        ]
      ]
    },
    "6cff2236-3e78-4e8c-bb3d-5140f106c530": {
      "ai_tool": [
        [
          {
            "node": "5da369db-b801-4653-888d-0e6042620298",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "f5cba8b5-226d-4b0a-8cb6-a51728ac8247": {
      "ai_tool": [
        [
          {
            "node": "AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    }
  }
}
자주 묻는 질문

이 워크플로우를 어떻게 사용하나요?

위의 JSON 구성 코드를 복사하여 n8n 인스턴스에서 새 워크플로우를 생성하고 "JSON에서 가져오기"를 선택한 후, 구성을 붙여넣고 필요에 따라 인증 설정을 수정하세요.

이 워크플로우는 어떤 시나리오에 적합한가요?

고급 - 기타, 인공지능

유료인가요?

이 워크플로우는 완전히 무료이며 직접 가져와 사용할 수 있습니다. 다만, 워크플로우에서 사용하는 타사 서비스(예: OpenAI API)는 사용자 직접 비용을 지불해야 할 수 있습니다.

워크플로우 정보
난이도
고급
노드 수72
카테고리2
노드 유형23
난이도 설명

고급 사용자를 위한 16+개 노드의 복잡한 워크플로우

외부 링크
n8n.io에서 보기

이 워크플로우 공유

카테고리

카테고리: 34