Saltar al contenido

AI-Powered YouTube Playlist & Video Summarization and Analysis v2

Chatbot n8n que resume y analiza playlists o videos de YouTube. Extrae transcripciones, las procesa con IA (Gemini), crea embeddings en Qdrant y responde preguntas del usuario sobre el contenido del video.

Repo Original 72 nodos 23 tipos conectado
Cargando workflow...

Nodos

LmChatGoogleGemini Agent SplitOut ChainLlm Summarize Limit VectorStoreQdrant TextSplitterRecursiveCharacterTextSplitter EmbeddingsGoogleGemini ChatTrigger Merge Set HttpRequest DocumentDefaultDataLoader MemoryBufferWindow StickyNote N8n-nodes-youtube-transcription-dmr.youtubeTranscripter OutputParserStructured Redis Switch Code If ToolVectorStore

Herramientas

Google Gemini Qdrant YouTube Redis Langchain Agents

Detalles

ID
2745
Nodos
72
Conex.
Tipos
23

Pertenece a:

¿Qué hace este workflow?

Este workflow n8n transforma la forma en que interactúas con el contenido de YouTube. Configura un potente chatbot que extrae automáticamente las transcripciones de cualquier video o playlist, las procesa con inteligencia artificial (Google Gemini) y las almacena de forma optimizada en Qdrant para búsquedas contextuales. Los usuarios pueden hacer preguntas complejas sobre el contenido del video, y el chatbot generará respuestas precisas y resúmenes detallados. Es ideal para investigadores, estudiantes que desean sintetizar clases o tutoriales, o equipos de marketing que necesitan analizar tendencias y contenido de la competencia de forma eficiente. Reduce drásticamente el tiempo dedicado a la revisión manual de videos largos y permite obtener insights valiosos en minutos, mejorando la toma de decisiones y el aprendizaje. Este sistema permite explorar contenido multimedia de YouTube como si fuera un documento de texto, facilitando la extracción de conocimiento.

¿Cómo funciona?

Este workflow usa 72 nodos conectados con 23 tipos diferentes: LmChatGoogleGemini, Agent, SplitOut, ChainLlm, Summarize y 18 más. La estructura está totalmente conectada — listo para importar.

¿Para quién es?

Diseñado para empresas de Educación y Formación y equipos de IT & DevOps. Nivel avanzado — recomendado para usuarios experimentados. Alto valor de negocio: automatiza una tarea recurrente con impacto directo.

¿Lo quieres en tu empresa?

Lo implementamos por ti end-to-end: integración, deploy, mantenimiento y soporte. Consultoría B2B con Genai Sapiens.

Hablemos de tu proyecto

¿Quieres aprender a hacerlo?

Sprints de 30 días con companion IA + comunidad. Aprende n8n, automatización y agentes IA desde cero o nivel avanzado.

Ver formación Momentum

Workflows similares

')?.[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('YouTube') && !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":"Split Out2","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":"Sticky Note12","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 .\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(';')[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":"Embeddings Google Gemini2","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 Vector Store3","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 Vector Store4","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 Chat Model","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 Chat Model3","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 Vector Store2","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":"Embeddings Google Gemini4","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":"Sticky Note","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":"Sticky Note1","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":"Sticky Note8","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":{"If":{"main":[[{"node":"Update Context Intent1","type":"main","index":0}],[{"node":"Playlist Limit","type":"main","index":0}]]},"Chat":{"main":[[{"node":"Get Previous Context Intent","type":"main","index":0}]]},"Limit":{"main":[[{"node":"YouTube Transcript","type":"main","index":0},{"node":"Video Titles","type":"main","index":0}]]},"Merge":{"main":[[{"node":"Summarize & Analyze Transcript","type":"main","index":0}]]},"Split Out":{"main":[[{"node":"Concatenate","type":"main","index":0}]]},"Get Videos":{"main":[[{"node":"Qdrant Vector Store","type":"main","index":0}]]},"Split Out1":{"main":[[{"node":"Limit","type":"main","index":0}]]},"Split Out2":{"main":[[{"node":"Concatenate1","type":"main","index":0}]]},"Concatenate":{"main":[[{"node":"Merge","type":"main","index":0}]]},"Edit Fields":{"main":[[{"node":"Delete Collection","type":"main","index":0}]]},"Concatenate1":{"main":[[{"node":"Merge","type":"main","index":0}]]},"Full Summary":{"main":[[{"node":"AI Agent","type":"main","index":0}]]},"Video Titles":{"main":[[{"node":"Merge","type":"main","index":1}]]},"Count Content":{"main":[[{"node":"If","type":"main","index":0}]]},"Simple Memory":{"ai_memory":[[{"node":"Message Intent","type":"ai_memory","index":0}]]},"Default Intent":{"main":[[{"node":"Route Message Intent","type":"main","index":0}]]},"Message Intent":{"main":[[{"node":"Default Intent","type":"main","index":0}],[]]},"Playlist Limit":{"main":[[{"node":"Numb of Videos","type":"main","index":0}],[{"node":"Playlist or Video","type":"main","index":0}]]},"Process Status":{"main":[[{"node":"Update Context Intent","type":"main","index":0}]]},"Simple Memory3":{"ai_memory":[[{"node":"Numb of Videos","type":"ai_memory","index":0}]]},"Delete Collection":{"main":[[{"node":"Get Videos","type":"main","index":0}]]},"Playlist or Video":{"main":[[{"node":"Video HTTP Request","type":"main","index":0}],[{"node":"Playlist HTTP Request","type":"main","index":0}]]},"Chat Buffer Memory":{"ai_memory":[[{"node":"Handle Queries","type":"ai_memory","index":0}]]},"Get Title and Desc":{"main":[[{"node":"Merge","type":"main","index":1}]]},"Video HTTP Request":{"main":[[{"node":"YouTube Transcript1","type":"main","index":0},{"node":"Get Title and Desc","type":"main","index":0}]]},"YouTube Transcript":{"main":[[{"node":"Split Out","type":"main","index":0}]]},"Chat Buffer Memory1":{"ai_memory":[[{"node":"AI Agent","type":"ai_memory","index":0}]]},"Default Data Loader":{"ai_document":[[{"node":"Qdrant Vector Store","type":"ai_document","index":0}]]},"Qdrant Vector Store":{"main":[[{"node":"Update Context Process Done1","type":"main","index":0}]]},"YouTube Transcript1":{"main":[[{"node":"Split Out2","type":"main","index":0}]]},"Qdrant Vector Store2":{"main":[[{"node":"Count Content","type":"main","index":0}]]},"Qdrant Vector Store3":{"ai_tool":[[]],"ai_vectorStore":[[{"node":"Answer questions with a vector store","type":"ai_vectorStore","index":0}]]},"Qdrant Vector Store4":{"ai_vectorStore":[[{"node":"Answer questions with a vector store1","type":"ai_vectorStore","index":0}]]},"Route Message Intent":{"main":[[{"node":"Process Status","type":"main","index":0}],[{"node":"Handle Queries","type":"main","index":0}],[{"node":"Handle Queries","type":"main","index":0}]]},"Playlist HTTP Request":{"main":[[{"node":"Get Playlist Videos Data","type":"main","index":0}]]},"Update Context Intent":{"main":[[{"node":"Qdrant Vector Store2","type":"main","index":0}]]},"Get Fields for Summary":{"main":[[{"node":"Full Summary","type":"main","index":0}]]},"Update Context Intent1":{"main":[[{"node":"Handle Queries","type":"main","index":0}]]},"Embeddings Google Gemini":{"ai_embedding":[[{"node":"Qdrant Vector Store","type":"ai_embedding","index":0}]]},"Get Playlist Videos Data":{"main":[[{"node":"Split Out1","type":"main","index":0}]]},"Google Gemini Chat Model":{"ai_languageModel":[[{"node":"Answer questions with a vector store1","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":"Handle Queries","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":"Answer questions with a vector store","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":"Message Intent","type":"ai_languageModel","index":0}]]},"Google Gemini Chat Model8":{"ai_languageModel":[[{"node":"Numb of Videos","type":"ai_languageModel","index":0}]]},"Structured Output Parser1":{"ai_outputParser":[[{"node":"Message Intent","type":"ai_outputParser","index":0}]]},"Get Previous Context Intent":{"main":[[{"node":"Message Intent","type":"main","index":0}]]},"Update Context Process Done1":{"main":[[{"node":"Get Fields for Summary","type":"main","index":0}]]},"Summarize & Analyze Transcript":{"main":[[{"node":"Edit Fields","type":"main","index":0}]]},"Recursive Character Text Splitter":{"ai_textSplitter":[[{"node":"Default Data Loader","type":"ai_textSplitter","index":0}]]},"Answer questions with a vector store":{"ai_tool":[[{"node":"Handle Queries","type":"ai_tool","index":0}]]},"Answer questions with a vector store1":{"ai_tool":[[{"node":"AI Agent","type":"ai_tool","index":0}]]}}}