{
  "id": "",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "YTB Outlier Finder",
  "tags": [],
  "nodes": [
    {
      "id": "",
      "name": "Wait",
      "type": "n8n-nodes-base.wait",
      "position": [
        0,
        -460
      ],
      "parameters": {},
      "typeVersion": 1.1
    },
    {
      "id": "",
      "name": "If",
      "type": "n8n-nodes-base.if",
      "position": [
        -160,
        -640
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.data.status }}",
              "rightValue": "SUCCEEDED"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "",
      "name": "Check IF Finished",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -440,
        -640
      ],
      "parameters": {
        "url": "https://api.apify.com/v2/acts/streamers~youtube-scraper/runs/last?token=YOUR_TOKEN_HERE",
        "options": {}
      },
      "typeVersion": 4.2
    },
    {
      "id": "",
      "name": "Get Videos Data",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        160,
        -660
      ],
      "parameters": {
        "url": "https://api.apify.com/v2/acts/streamers~youtube-scraper/runs/last/dataset/items?token=YOUR_TOKEN_HERE",
        "options": {}
      },
      "typeVersion": 4.2
    },
    {
      "id": "",
      "name": "Create Videos Dataset",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -700,
        -640
      ],
      "parameters": {
        "url": "https://api.apify.com/v2/acts/streamers~youtube-scraper/runs?token=YOUR_TOKEN_HERE",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n    \"dateFilter\": \"week\",\n    \"downloadSubtitles\": true,\n    \"hasCC\": false,\n    \"hasLocation\": false,\n    \"hasSubtitles\": false,\n    \"is360\": false,\n    \"is3D\": false,\n    \"is4K\": false,\n    \"isBought\": false,\n    \"isHD\": false,\n    \"isHDR\": false,\n    \"isLive\": false,\n    \"isVR180\": false,\n    \"lengthFilter\": \"between420\",\n    \"maxResultStreams\": 0,\n    \"maxResults\": 3,\n    \"maxResultsShorts\": 0,\n    \"preferAutoGeneratedSubtitles\": false,\n    \"saveSubsToKVS\": false,\n    \"searchQueries\": [\n        \"{{ $json.keyword1 }}\",\n        \"{{ $json.keyword2 }}\",\n        \"{{ $json.keyword3 }}\"\n    ],\n    \"sortingOrder\": \"relevance\",\n    \"subtitlesLanguage\": \"en\"\n} ",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "",
      "name": "Loop Over Items",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        400,
        -660
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "",
      "name": "Mistral Cloud Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatMistralCloud",
      "position": [
        980,
        -300
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "mistralCloudApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "",
      "name": "No Operation, do nothing",
      "type": "n8n-nodes-base.noOp",
      "position": [
        900,
        -680
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "",
      "name": "Airtable",
      "type": "n8n-nodes-base.airtable",
      "position": [
        1460,
        -320
      ],
      "parameters": {
        "base": {
          "__rl": true,
          "mode": "list",
          "value": "",
          "cachedResultUrl": "https://airtable.com/[YOUR_DB]",
          "cachedResultName": "YTB Trend Finder"
        },
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "",
          "cachedResultUrl": "https://airtable.com/[YOUR_DB]",
          "cachedResultName": "Listing"
        },
        "columns": {
          "value": {
            "Link": "={{ $('Loop Over Items').item.json.url }}",
            "Title": "={{ $('Loop Over Items').item.json.title }}",
            "Duration": "={{ $('Loop Over Items').item.json.duration }}",
            "Structure": "={{ $json.text }}",
            "SubsCount": "={{ $('Loop Over Items').item.json.numberOfSubscribers }}",
            "Thumbnail": "={{ [{ \"url\": $('Loop Over Items').item.json.thumbnailUrl }] }}",
            "ViewsCount": "={{ $('Loop Over Items').item.json.viewCount }}",
            "ChannelName": "={{ $('Loop Over Items').item.json.channelName }}",
            "CommentsCount": "={{ $('Loop Over Items').item.json.commentsCount }}"
          },
          "schema": [
            {
              "id": "Link",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "Link",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Title",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "Title",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "ChannelName",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "ChannelName",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Thumbnail",
              "type": "array",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "Thumbnail",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "ViewsCount",
              "type": "number",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "ViewsCount",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "SubsCount",
              "type": "number",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "SubsCount",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "CommentsCount",
              "type": "number",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "CommentsCount",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Duration",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "Duration",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Structure",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "Structure",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "VSC Ratio",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": true,
              "required": false,
              "displayName": "VSC Ratio",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "create"
      },
      "credentials": {
        "airtableTokenApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -1220,
        -640
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "weeks",
              "triggerAtDay": [
                1
              ]
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1300,
        -900
      ],
      "parameters": {
        "color": 7,
        "width": 780,
        "height": 440,
        "content": "## SETUP\n\n**Scheduled Trigger :** Select the Frequency you want. If you change it, update the data accordingly in the \"Create Videos Dataset\" HTTP Request Node in Body \u27a1\ufe0f JSON \u27a1\ufe0f dateFilter.\n\n\n**Setup Keywords :** Enter Keyword Related to the niche you want. If you change the number of keywords, update the data accordingly in the \"Create Videos Dataset\" HTTP Request Node in Body \u27a1\ufe0f JSON \u27a1\ufe0f searchQueries.\n\n**Create Videos Dataset :** Refer to the Apify Documentation for more https://docs.apify.com/api/v2/getting-started\n\n**APIs :** For all HTTP Request node in the URL field, replace [YOUR_API_TOKEN] with your API Token. "
      },
      "typeVersion": 1
    },
    {
      "id": "",
      "name": "Text Cleaning",
      "type": "n8n-nodes-base.code",
      "position": [
        700,
        -500
      ],
      "parameters": {
        "jsCode": "// Assume input is a single string like SRT format\nconst input = $input.first().json.subtitles[0].srt; // or wherever your caption string is\n\n// Step-by-step cleanup\nconst cleaned = input\n  // Remove caption numbers (lines with only digits)\n  .replace(/^\\d+\\s*$/gm, \"\")\n  // Remove timing lines\n  .replace(/^\\d{2}:\\d{2}:\\d{1,2},\\d{1,3} --> \\d{2}:\\d{2}:\\d{1,2},\\d{1,3}\\s*$/gm, \"\")\n  // Remove leftover newlines\n  .replace(/\\n{2,}/g, \"\\n\")\n  // Trim and flatten everything to single paragraph\n  .replace(/\\n/g, \" \")\n  .trim();\n\nreturn [{ cleanedText: cleaned }];"
      },
      "typeVersion": 2
    },
    {
      "id": "",
      "name": "Text Synthesis ",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        960,
        -500
      ],
      "parameters": {
        "text": "={{ $json.cleanedText }}",
        "messages": {
          "messageValues": [
            {
              "type": "HumanMessagePromptTemplate",
              "message": "=You are a summarization assistant.  Given a transcript of a YouTube video, your task is to summarize the content using only information found in the transcript, do not invent, infer, or add anything beyond what is said.  Structure your output as follows: \n\n1. Intro how the video begins or introduces the topic.  Don't do any modification on this part. \n\n2. Structure of the Video A breakdown of the video\u2019s flow using bullet points: \nMajor Points: The main topics or arguments discussed.  \nSubpoints: Supporting details, examples, or smaller elements related to each major point. Use indentation or clear labeling to distinguish between major points and their related subpoints. \n"
            }
          ]
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 1.5
    },
    {
      "id": "",
      "name": "Setup Keywords",
      "type": "n8n-nodes-base.set",
      "position": [
        -960,
        -640
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "",
              "name": "keyword1",
              "type": "string",
              "value": "Healthy food"
            },
            {
              "id": "",
              "name": "keyword2",
              "type": "string",
              "value": "Meal prep healthy"
            },
            {
              "id": "",
              "name": "keyword3",
              "type": "string",
              "value": "High Protein Snack"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1300,
        -1200
      ],
      "parameters": {
        "color": 7,
        "width": 780,
        "height": 260,
        "content": "## How this is Working ?\n**1 -** Every Week retrieve Keywords you want to track\n**2 -** Thanks to Apify, scrap video from Youtube Search related to these Keywords filtered by relevance\n**3 -** Wait until the Dataset is completed\n**4 -** Get the Information contained in the Dataset\n**5 -** For each Video, clean and summarize the script\n**6 -** Upload everything in your Airtable Database\n\n**\ud83d\udcfa Youtube Video Tutorial : https://youtu.be/pH2hVaij3FY**\n**\ud83d\udee0\ufe0f Need Help with Your Workflows ? https://tally.so/r/wayeqB**\n**\ud83d\udc68\u200d\ud83d\udcbb\u00a0More Workflows : https://n8n.io/creators/nasser/**"
      },
      "typeVersion": 1
    },
    {
      "id": "",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1360,
        -700
      ],
      "parameters": {
        "color": 7,
        "width": 320,
        "height": 620,
        "content": "## Airtable DB Fields\n**1 -** Video Link (ID)\n**2 -** Video Title\n**3 -** Channel Name\n**4 -** Thumbnail \u2b07\ufe0f\nTo Upload an Image on Airtable Attachement Field you need an Array of the URL in this format : {{ [{ \"url\": $json.thumbnail}] }}\n**5 -** Views Count\n**6 -** Subs Count\n**7 -** Comments Count\n**8 -** Duration\n**9 -** Structure\n**10 -** VSC Ratio \u2b07\ufe0f\nFormula :(ViewsCount/SubsCount)*0.7 + (CommentsCount/ViewsCount)*0.3)\n"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "",
  "connections": {
    "If": {
      "main": [
        [
          {
            "node": "Get Videos Data",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Wait",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait": {
      "main": [
        [
          {
            "node": "Check IF Finished",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Airtable": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Text Cleaning": {
      "main": [
        [
          {
            "node": "Text Synthesis ",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Setup Keywords": {
      "main": [
        [
          {
            "node": "Create Videos Dataset",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Videos Data": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items": {
      "main": [
        [
          {
            "node": "No Operation, do nothing",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Text Cleaning",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Text Synthesis ": {
      "main": [
        [
          {
            "node": "Airtable",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Setup Keywords",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check IF Finished": {
      "main": [
        [
          {
            "node": "If",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Videos Dataset": {
      "main": [
        [
          {
            "node": "Check IF Finished",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Mistral Cloud Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Text Synthesis ",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    }
  }
}