AutomationFlowsContent & Video › Content Pipeline: Podcast RSS + Vimeo Intake

Content Pipeline: Podcast RSS + Vimeo Intake

Content Pipeline: Podcast RSS + Vimeo Intake. Uses httpRequest, googleDrive. Scheduled trigger; 40 nodes.

Cron / scheduled trigger★★★★★ complexity40 nodesHTTP RequestGoogle Drive
Content & Video Trigger: Cron / scheduled Nodes: 40 Complexity: ★★★★★ Added:

This workflow follows the Google Drive → HTTP Request recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "name": "Content Pipeline: Podcast RSS + Vimeo Intake",
  "nodes": [
    {
      "name": "Tue + Fri 10am PT",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.3,
      "position": [
        0,
        608
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 0 10 * * 2,5"
            }
          ]
        }
      }
    },
    {
      "name": "Dedup by URL",
      "type": "n8n-nodes-base.removeDuplicates",
      "typeVersion": 2,
      "position": [
        1088,
        608
      ],
      "parameters": {
        "operation": "removeItemsSeenInPreviousExecutions",
        "dedupeValue": "={{ $json.link || $json.guid || ($json.enclosure && $json.enclosure.url) || $json.id || $json.title }}",
        "options": {
          "historySize": 10000
        }
      },
      "disabled": false
    },
    {
      "name": "Relevance Gate",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        1600,
        608
      ],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": false,
            "leftValue": "",
            "typeValidation": "loose",
            "version": 1
          },
          "conditions": [
            {
              "id": "1",
              "leftValue": "={{ $json.is_relevant }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      }
    },
    {
      "name": "Preserve Episode Metadata",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        1872,
        352
      ],
      "parameters": {
        "mode": "manual",
        "assignments": {
          "assignments": [
            {
              "id": "1",
              "name": "_episode_title",
              "type": "string",
              "value": "={{ $json.title }}"
            },
            {
              "id": "2",
              "name": "_episode_url",
              "type": "string",
              "value": "={{ $json.link }}"
            },
            {
              "id": "3",
              "name": "_episode_published",
              "type": "string",
              "value": "={{ $json.isoDate }}"
            },
            {
              "id": "4",
              "name": "_podcast_name",
              "type": "string",
              "value": "={{ $json.podcast_name }}"
            },
            {
              "id": "5",
              "name": "_default_topics",
              "type": "array",
              "value": "={{ $json.default_topics }}"
            },
            {
              "id": "6",
              "name": "audio_url",
              "type": "string",
              "value": "={{ $json.audio_url }}"
            },
            {
              "id": "7",
              "name": "_podcast_priority",
              "type": "string",
              "value": "={{ $json.podcast_priority }}"
            },
            {
              "id": "8",
              "name": "source_type",
              "type": "string",
              "value": "podcast"
            }
          ]
        },
        "options": {}
      }
    },
    {
      "name": "AssemblyAI: Submit",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.4,
      "position": [
        2128,
        400
      ],
      "parameters": {
        "method": "POST",
        "url": "https://api.assemblyai.com/v2/transcript",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ audio_url: $(\"Preserve Episode Metadata\").item.json.audio_url, speech_model: \"universal\", speaker_labels: true, auto_chapters: true, auto_highlights: true, entity_detection: true, punctuate: true, format_text: true, word_boost: [\"Claude\",\"Anthropic\",\"OpenAI\",\"ChatGPT\",\"Sonnet\",\"Opus\",\"Haiku\",\"Gemini\",\"Grok\",\"Llama\",\"Mistral\",\"Cohere\",\"Perplexity\",\"GPT-5\",\"GPT-4o\",\"Codex\",\"Cursor\",\"MCP\",\"Model Context Protocol\",\"n8n\",\"Zapier\",\"Notion\",\"Vercel\",\"Supabase\",\"Agentic\",\"LLM\",\"RAG\",\"Fine-tuning\",\"Embedding\",\"Vector\",\"Inference\",\"Token\",\"Hallucination\",\"MMA\",\"Marketing + Media Alliance\",\"CMO\",\"CRO\",\"CAP\",\"ALTT\",\"ACE\",\"A3\",\"SIFT\",\"AURA\",\"ARC\",\"RAIL\",\"Nvidia\",\"H100\",\"Blackwell\",\"DeepSeek\",\"Qwen\",\"Kimi\"], boost_param: \"high\" }) }}",
        "options": {
          "timeout": 60000
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      }
    },
    {
      "name": "AssemblyAI: Wait 30s",
      "type": "n8n-nodes-base.wait",
      "typeVersion": 1.1,
      "position": [
        2384,
        400
      ],
      "parameters": {
        "amount": 30
      }
    },
    {
      "name": "AssemblyAI: Poll",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.4,
      "position": [
        2640,
        400
      ],
      "parameters": {
        "url": "=https://api.assemblyai.com/v2/transcript/{{ $json.id }}",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "options": {
          "timeout": 60000
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      }
    },
    {
      "name": "AssemblyAI: Completed?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        2912,
        400
      ],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "1",
              "leftValue": "={{ $json.status }}",
              "rightValue": "completed",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      }
    },
    {
      "name": "AssemblyAI: Extract Transcript",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        3168,
        320
      ],
      "parameters": {
        "mode": "manual",
        "assignments": {
          "assignments": [
            {
              "id": "1",
              "name": "transcript",
              "type": "string",
              "value": "={{ ($json.utterances && $json.utterances.length) ? $json.utterances.map(u => (u.speaker ? \"Speaker \" + u.speaker + \": \" : \"\") + u.text).join(\"\\n\") : $json.text }}"
            },
            {
              "id": "2",
              "name": "transcript_source",
              "type": "string",
              "value": "AssemblyAI"
            },
            {
              "id": "3",
              "name": "transcript_id",
              "type": "string",
              "value": "={{ $json.id }}"
            },
            {
              "id": "4",
              "name": "chapters_json",
              "type": "string",
              "value": "={{ JSON.stringify($json.chapters || []) }}"
            },
            {
              "id": "5",
              "name": "highlights_json",
              "type": "string",
              "value": "={{ JSON.stringify((($json.auto_highlights_result || {}).results) || []) }}"
            },
            {
              "id": "6",
              "name": "_episode_title",
              "type": "string",
              "value": "={{ $(\"Preserve Episode Metadata\").item.json._episode_title }}"
            },
            {
              "id": "7",
              "name": "_episode_url",
              "type": "string",
              "value": "={{ $(\"Preserve Episode Metadata\").item.json._episode_url }}"
            },
            {
              "id": "8",
              "name": "_episode_published",
              "type": "string",
              "value": "={{ $(\"Preserve Episode Metadata\").item.json._episode_published }}"
            },
            {
              "id": "9",
              "name": "_podcast_name",
              "type": "string",
              "value": "={{ $(\"Preserve Episode Metadata\").item.json._podcast_name }}"
            },
            {
              "id": "10",
              "name": "_default_topics",
              "type": "array",
              "value": "={{ $(\"Preserve Episode Metadata\").item.json._default_topics }}"
            },
            {
              "id": "11",
              "name": "_podcast_priority",
              "type": "string",
              "value": "={{ $(\"Preserve Episode Metadata\").item.json._podcast_priority }}"
            },
            {
              "id": "12",
              "name": "source_type",
              "type": "string",
              "value": "podcast"
            }
          ]
        },
        "options": {}
      }
    },
    {
      "name": "Merge Transcripts (RSS + Vimeo)",
      "type": "n8n-nodes-base.merge",
      "typeVersion": 3.2,
      "position": [
        3424,
        1400
      ],
      "parameters": {
        "mode": "append",
        "numberInputs": 1
      }
    },
    {
      "name": "Vimeo: List Recent Videos",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.4,
      "position": [
        288,
        2400
      ],
      "parameters": {
        "method": "GET",
        "url": "https://api.vimeo.com/me/videos",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Accept",
              "value": "application/vnd.vimeo.*+json;version=3.4"
            }
          ]
        },
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "sort",
              "value": "date"
            },
            {
              "name": "direction",
              "value": "desc"
            },
            {
              "name": "per_page",
              "value": "25"
            },
            {
              "name": "fields",
              "value": "uri,name,description,created_time,privacy,duration,link,metadata"
            }
          ]
        },
        "options": {
          "timeout": 60000
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      }
    },
    {
      "name": "Vimeo: Filter Public + Dedup",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        560,
        2400
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "language": "javaScript",
        "jsCode": "const items = $input.all();\nconst staticData = $getWorkflowStaticData('global');\nif (!staticData.vimeoSeen) staticData.vimeoSeen = {};\nconst seen = staticData.vimeoSeen;\nconst now = Date.now();\nfor (const k of Object.keys(seen)) { if (now - seen[k] > 90*24*3600*1000) delete seen[k]; }\nconst out = [];\nconst allowedPrivacy = ['anybody','unlisted'];\nfor (const it of items) {\n  const videos = (it.json && it.json.data) || [];\n  for (const v of videos) {\n    if (!v || !v.uri) continue;\n    const priv = (v.privacy && v.privacy.view) || 'nobody';\n    if (!allowedPrivacy.includes(priv)) continue;\n    if (seen[v.uri]) continue;\n    seen[v.uri] = now;\n    const videoId = String(v.uri).replace('/videos/','').trim();\n    out.push({ json: { video_id: videoId, video_uri: v.uri, name: v.name || '', description: v.description || '', created_time: v.created_time || '', link: v.link || '', privacy_view: priv, duration: v.duration || 0 } });\n  }\n}\nreturn out;"
      }
    },
    {
      "name": "Vimeo: Preserve Metadata",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        832,
        2400
      ],
      "parameters": {
        "mode": "manual",
        "assignments": {
          "assignments": [
            {
              "id": "1",
              "name": "_episode_title",
              "type": "string",
              "value": "={{ $json.name }}"
            },
            {
              "id": "2",
              "name": "_episode_url",
              "type": "string",
              "value": "={{ $json.link }}"
            },
            {
              "id": "3",
              "name": "_episode_published",
              "type": "string",
              "value": "={{ $json.created_time }}"
            },
            {
              "id": "4",
              "name": "_podcast_name",
              "type": "string",
              "value": "MMA Vimeo"
            },
            {
              "id": "5",
              "name": "_default_topics",
              "type": "array",
              "value": "={{ [\"Marketing AI\",\"AI Strategy\"] }}"
            },
            {
              "id": "6",
              "name": "_podcast_priority",
              "type": "string",
              "value": "high"
            },
            {
              "id": "7",
              "name": "video_id",
              "type": "string",
              "value": "={{ $json.video_id }}"
            },
            {
              "id": "8",
              "name": "audio_url",
              "type": "string",
              "value": ""
            },
            {
              "id": "9",
              "name": "source_type",
              "type": "string",
              "value": "vimeo"
            }
          ]
        },
        "includeOtherFields": true,
        "options": {}
      }
    },
    {
      "name": "Vimeo: Get Text Tracks",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.4,
      "position": [
        1104,
        2400
      ],
      "parameters": {
        "method": "GET",
        "url": "=https://api.vimeo.com/videos/{{ $json.video_id }}/texttracks",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Accept",
              "value": "application/vnd.vimeo.*+json;version=3.4"
            }
          ]
        },
        "options": {
          "timeout": 60000,
          "response": {
            "response": {
              "neverError": true
            }
          }
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      }
    },
    {
      "name": "Vimeo Has Caption?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        1376,
        2400
      ],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": false,
            "leftValue": "",
            "typeValidation": "loose",
            "version": 1
          },
          "conditions": [
            {
              "id": "1",
              "leftValue": "={{ ($json.data && $json.data.find(t => t.active && typeof t.language === \"string\" && t.language.toLowerCase().startsWith(\"en\")) && $json.data.find(t => t.active && typeof t.language === \"string\" && t.language.toLowerCase().startsWith(\"en\")).link) ? \"yes\" : \"no\" }}",
              "rightValue": "yes",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      }
    },
    {
      "name": "Vimeo: Fetch Caption VTT",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.4,
      "position": [
        1648,
        2272
      ],
      "parameters": {
        "method": "GET",
        "url": "={{ $json.data.find(t => t.active && typeof t.language === \"string\" && t.language.toLowerCase().startsWith(\"en\")).link }}",
        "options": {
          "timeout": 60000,
          "response": {
            "response": {
              "responseFormat": "text"
            }
          }
        }
      }
    },
    {
      "name": "Vimeo: Parse VTT to Text",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1920,
        2272
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "language": "javaScript",
        "jsCode": "const items = $input.all();\nconst metaAll = $('Vimeo: Preserve Metadata').all();\nconst out = [];\nfor (let i = 0; i < items.length; i++) {\n  const raw = items[i].json && (items[i].json.data || items[i].json.body || '');\n  const text = typeof raw === 'string' ? raw : JSON.stringify(raw);\n  const lines = text.split(/\\r?\\n/);\n  const plain = [];\n  for (const line of lines) {\n    if (!line) continue;\n    if (/^WEBVTT/i.test(line)) continue;\n    if (/^NOTE/i.test(line)) continue;\n    if (/^\\d+$/.test(line.trim())) continue;\n    if (line.includes('-->')) continue;\n    if (/^(Kind|Language|STYLE|Region):/i.test(line)) continue;\n    plain.push(line.replace(/<[^>]+>/g,'').trim());\n  }\n  const transcript = plain.filter(Boolean).join(' ');\n  const meta = metaAll[i] ? metaAll[i].json : (metaAll[0] ? metaAll[0].json : {});\n  out.push({ json: { transcript, transcript_source: 'Vimeo', _episode_title: meta._episode_title || '', _episode_url: meta._episode_url || '', _episode_published: meta._episode_published || '', _podcast_name: meta._podcast_name || 'MMA Vimeo', _default_topics: meta._default_topics || [], _podcast_priority: meta._podcast_priority || 'high', source_type: 'vimeo' } });\n}\nreturn out;"
      }
    },
    {
      "name": "Vimeo: Get Download URL",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.4,
      "position": [
        1648,
        2528
      ],
      "parameters": {
        "method": "GET",
        "url": "=https://api.vimeo.com/videos/{{ $(\"Vimeo: Preserve Metadata\").item.json.video_id }}",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Accept",
              "value": "application/vnd.vimeo.*+json;version=3.4"
            }
          ]
        },
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "fields",
              "value": "download,files"
            }
          ]
        },
        "options": {
          "timeout": 60000
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      }
    },
    {
      "name": "Vimeo: Set Audio URL",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        1920,
        2528
      ],
      "parameters": {
        "mode": "manual",
        "assignments": {
          "assignments": [
            {
              "id": "1",
              "name": "audio_url",
              "type": "string",
              "value": "={{ (() => { const files = ($json.files || []); const mp4 = files.filter(f => f && f.type && f.type.includes(\"mp4\") && f.link); if (mp4.length === 0) return (files[0] && files[0].link) || \"\"; mp4.sort((a,b) => (a.size||0) - (b.size||0)); return mp4[0].link || \"\"; })() }}"
            },
            {
              "id": "2",
              "name": "_episode_title",
              "type": "string",
              "value": "={{ $(\"Vimeo: Preserve Metadata\").item.json._episode_title }}"
            },
            {
              "id": "3",
              "name": "_episode_url",
              "type": "string",
              "value": "={{ $(\"Vimeo: Preserve Metadata\").item.json._episode_url }}"
            },
            {
              "id": "4",
              "name": "_episode_published",
              "type": "string",
              "value": "={{ $(\"Vimeo: Preserve Metadata\").item.json._episode_published }}"
            },
            {
              "id": "5",
              "name": "_podcast_name",
              "type": "string",
              "value": "={{ $(\"Vimeo: Preserve Metadata\").item.json._podcast_name }}"
            },
            {
              "id": "6",
              "name": "_default_topics",
              "type": "array",
              "value": "={{ $(\"Vimeo: Preserve Metadata\").item.json._default_topics }}"
            },
            {
              "id": "7",
              "name": "_podcast_priority",
              "type": "string",
              "value": "={{ $(\"Vimeo: Preserve Metadata\").item.json._podcast_priority }}"
            },
            {
              "id": "8",
              "name": "source_type",
              "type": "string",
              "value": "vimeo"
            },
            {
              "id": "9",
              "name": "video_id",
              "type": "string",
              "value": "={{ $(\"Vimeo: Preserve Metadata\").item.json.video_id }}"
            }
          ]
        },
        "options": {}
      }
    },
    {
      "name": "Vimeo AssemblyAI: Submit",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.4,
      "position": [
        2192,
        2528
      ],
      "parameters": {
        "method": "POST",
        "url": "https://api.assemblyai.com/v2/transcript",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ audio_url: $(\"Vimeo: Set Audio URL\").item.json.audio_url, speech_model: \"universal\", speaker_labels: true, auto_chapters: true, punctuate: true, format_text: true, word_boost: [\"Claude\",\"Anthropic\",\"OpenAI\",\"ChatGPT\",\"Sonnet\",\"Opus\",\"Haiku\",\"Gemini\",\"MCP\",\"Marketing + Media Alliance\",\"MMA\",\"CMO\",\"CAP\",\"ALTT\",\"ACE\",\"A3\",\"SIFT\",\"AURA\",\"ARC\",\"RAIL\"], boost_param: \"high\" }) }}",
        "options": {
          "timeout": 60000
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      }
    },
    {
      "name": "Vimeo AssemblyAI: Wait 30s",
      "type": "n8n-nodes-base.wait",
      "typeVersion": 1.1,
      "position": [
        2448,
        2528
      ],
      "parameters": {
        "amount": 30
      }
    },
    {
      "name": "Vimeo AssemblyAI: Poll",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.4,
      "position": [
        2704,
        2528
      ],
      "parameters": {
        "url": "=https://api.assemblyai.com/v2/transcript/{{ $json.id }}",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "options": {
          "timeout": 60000
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      }
    },
    {
      "name": "Vimeo AssemblyAI: Completed?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        2976,
        2528
      ],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "1",
              "leftValue": "={{ $json.status }}",
              "rightValue": "completed",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      }
    },
    {
      "name": "Vimeo AssemblyAI: Extract Transcript",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        3232,
        2528
      ],
      "parameters": {
        "mode": "manual",
        "assignments": {
          "assignments": [
            {
              "id": "1",
              "name": "transcript",
              "type": "string",
              "value": "={{ $json.text }}"
            },
            {
              "id": "2",
              "name": "transcript_source",
              "type": "string",
              "value": "AssemblyAI"
            },
            {
              "id": "3",
              "name": "_episode_title",
              "type": "string",
              "value": "={{ $(\"Vimeo: Set Audio URL\").item.json._episode_title }}"
            },
            {
              "id": "4",
              "name": "_episode_url",
              "type": "string",
              "value": "={{ $(\"Vimeo: Set Audio URL\").item.json._episode_url }}"
            },
            {
              "id": "5",
              "name": "_episode_published",
              "type": "string",
              "value": "={{ $(\"Vimeo: Set Audio URL\").item.json._episode_published }}"
            },
            {
              "id": "6",
              "name": "_podcast_name",
              "type": "string",
              "value": "={{ $(\"Vimeo: Set Audio URL\").item.json._podcast_name }}"
            },
            {
              "id": "7",
              "name": "_default_topics",
              "type": "array",
              "value": "={{ $(\"Vimeo: Set Audio URL\").item.json._default_topics }}"
            },
            {
              "id": "8",
              "name": "_podcast_priority",
              "type": "string",
              "value": "={{ $(\"Vimeo: Set Audio URL\").item.json._podcast_priority }}"
            },
            {
              "id": "9",
              "name": "source_type",
              "type": "string",
              "value": "vimeo"
            }
          ]
        },
        "options": {}
      }
    },
    {
      "name": "Attach Episode Context",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        3680,
        1400
      ],
      "parameters": {
        "mode": "manual",
        "assignments": {
          "assignments": [
            {
              "id": "1",
              "name": "transcript",
              "type": "string",
              "value": "={{ $json.transcript }}"
            },
            {
              "id": "2",
              "name": "transcript_source",
              "type": "string",
              "value": "={{ $json.transcript_source }}"
            },
            {
              "id": "3",
              "name": "transcript_id",
              "type": "string",
              "value": "={{ $json.transcript_id || \"\" }}"
            },
            {
              "id": "4",
              "name": "source_page_id",
              "type": "string",
              "value": "={{ $json.source_page_id || \"\" }}"
            },
            {
              "id": "5",
              "name": "_episode_title",
              "type": "string",
              "value": "={{ $json._episode_title }}"
            },
            {
              "id": "6",
              "name": "_episode_url",
              "type": "string",
              "value": "={{ $json._episode_url }}"
            },
            {
              "id": "7",
              "name": "_episode_published",
              "type": "string",
              "value": "={{ $json._episode_published }}"
            },
            {
              "id": "8",
              "name": "_podcast_name",
              "type": "string",
              "value": "={{ $json._podcast_name }}"
            },
            {
              "id": "9",
              "name": "_default_topics",
              "type": "array",
              "value": "={{ $json._default_topics }}"
            },
            {
              "id": "10",
              "name": "_podcast_priority",
              "type": "string",
              "value": "={{ $json._podcast_priority || \"medium\" }}"
            },
            {
              "id": "11",
              "name": "source_type",
              "type": "string",
              "value": "={{ $json.source_type || \"podcast\" }}"
            },
            {
              "id": "12",
              "name": "chapters_json",
              "type": "string",
              "value": "={{ $json.chapters_json || \"[]\" }}"
            },
            {
              "id": "13",
              "name": "highlights_json",
              "type": "string",
              "value": "={{ $json.highlights_json || \"[]\" }}"
            }
          ]
        },
        "options": {}
      }
    },
    {
      "name": "Claude Extract Ideas",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.4,
      "position": [
        3952,
        1272
      ],
      "parameters": {
        "method": "POST",
        "url": "https://api.anthropic.com/v1/messages",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "anthropic-version",
              "value": "2023-06-01"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ model: \"claude-sonnet-5\", thinking: { type: \"disabled\" }, max_tokens: 16000, system: [{ type: \"text\", text: \"You extract neutral, objective research material from podcast/video transcripts for Alec Foster\\u0027s content pipeline. Alec is Chief AI Architect & Responsible AI Lead at Marketing + Media Alliance (MMA). Alec\\u0027s core interests and areas of expertise (use these to score Relevance): Claude (all Anthropic products), Claude Code and agent SDKs, agentic AI, AI governance, responsible AI, AI safety, marketing AI, enterprise AI adoption, MCP / Model Context Protocol, prompt engineering, LLM evals, AI strategy for CMOs, MMA frameworks (ALTT, ACE, CAP, AURA, RAIL, ARC, SIFT). Output is neutral reference stock, not first-person drafts. Calibrate depth by priority tier: HIGH = 4-8 ideas. MEDIUM = 2-5. LOW = 0-3. Transcripts may be speaker-diarized (Speaker A: / Speaker B:) \u2014 map labels to real names when introductions reveal them. Be generous with depth.\", cache_control: { type: \"ephemeral\" } }], messages: [{ role: \"user\", content: \"Extract every distinct content-worthy topic from this \" + ($json.source_type === \"vimeo\" ? \"Vimeo video\" : \"podcast episode\") + \".\\nSource type: \" + ($json.source_type || \"podcast\") + \"\\nPriority tier: \" + (($json._podcast_priority || \"medium\").toUpperCase()) + \"\\n\\nFor EACH idea return:\\n\" + \"- topic_headline: punchy, specific (not generic)\\n\" + \"- hook: 2-3 sentences\\n\" + \"- key_points: 5-10 bullets, each >=15 words, with numbers/names/specifics from the transcript\\n\" + \"- observations: 2-5 secondary bullets of nuance, context, or counterpoints\\n\" + \"- tips: 0-5 actionable takeaways (empty array if analytical)\\n\" + \"- quotes: 2-4 {speaker, quote, timestamp}. INCLUDE both direct host/guest quotes AND quotes attributed to cited third parties (researcher, company, paper) \u2014 for those use the ORIGINAL source as speaker (e.g. \\\"Dario Amodei (cited by host)\\\"). Use real names when intros reveal speaker identities. Quote must be >=10 words verbatim. Omit the entry rather than returning an empty string.\\n\" + \"- why_it_matters: 3-5 sentences with Alec/MMA angle when relevant\\n\" + \"- open_question: 1 sentence\\n\" + \"- draft_angle: 1-2 sentence post/infographic spine\\n\" + \"- further_reading: 0-4 {title, url} \u2014 only if a real URL is explicit/obvious. Never fabricate.\\n\" + \"- topics: (Claude|Agents|AI Governance|Marketing AI|Measurement|AI Strategy|LLMs|MCP|Voice AI|AI Safety|Enterprise AI|Creator Economy|Policy|Research|Content|Prompt Engineering|Reddit/Search|OpenAI|Anthropic|Google|Meta|Codex)\\n\" + \"- audience: (Marketers|AI Practitioners|Execs/CMOs|Governance|Builders|General)\\n\" + \"- hot_take_potential: High|Medium|Low \u2014 contrarian/debate-worthy\\n\" + \"- utility: High|Medium|Low \u2014 practical/educational value\\n\" + \"- relevance: High|Medium|Low \u2014 fit to ALEC\\u0027S INTERESTS (Claude/Claude Code, agentic AI, AI governance, responsible AI, marketing AI, enterprise AI, MCP, prompt engineering, MMA frameworks). High = Alec has clear standing/expertise to speak publicly on this; Low = outside his lane (e.g. hardware deep-dives, consumer celebrity AI news, non-AI business stories). Be honest \u2014 not every idea needs to be High.\\n\" + \"- format: Hot Take|Explainer|How-To|Framework|Announcement|Case Study\\n\\n\" + \"Chapter markers (guide for idea boundaries, optional):\\n\" + ($json.chapters_json && $json.chapters_json !== \"[]\" ? (JSON.parse($json.chapters_json).slice(0, 25).map(c => \"- \" + (c.headline || \"\") + \": \" + (c.gist || c.summary || \"\")).join(\"\\n\")) : \"(none)\") + \"\\n\\n\" + \"AssemblyAI auto-highlights (quote candidates, optional):\\n\" + ($json.highlights_json && $json.highlights_json !== \"[]\" ? (JSON.parse($json.highlights_json).slice(0, 15).map(h => \"- \" + (h.text || \"\")).join(\"\\n\")) : \"(none)\") + \"\\n\\n\" + \"Ignore sponsor reads, intros/outros, promos. Return ONLY JSON:\\n\" + \"{\\\"episode_summary\\\":\\\"3-5 sentence overview\\\",\\\"ideas\\\":[...]}\\n\\n\" + \"Episode: \" + $json._episode_title + \"\\nPodcast: \" + $json._podcast_name + \"\\nPublished: \" + $json._episode_published + \"\\n\\nTranscript:\\n\" + $json.transcript }] }) }}",
        "options": {
          "timeout": 300000
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "onError": "continueRegularOutput",
      "retryOnFail": true,
      "maxTries": 3,
      "waitBetweenTries": 5000
    },
    {
      "name": "Tag: Claude Sonnet 4.6",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        4224,
        1144
      ],
      "parameters": {
        "mode": "manual",
        "assignments": {
          "assignments": [
            {
              "id": "1",
              "name": "extraction_model",
              "type": "string",
              "value": "Sonnet 4.6"
            },
            {
              "id": "2",
              "name": "_episode_title",
              "type": "string",
              "value": "={{ $(\"Attach Episode Context\").item.json._episode_title }}"
            },
            {
              "id": "3",
              "name": "_episode_url",
              "type": "string",
              "value": "={{ $(\"Attach Episode Context\").item.json._episode_url }}"
            },
            {
              "id": "4",
              "name": "_episode_published",
              "type": "string",
              "value": "={{ $(\"Attach Episode Context\").item.json._episode_published }}"
            },
            {
              "id": "5",
              "name": "_podcast_name",
              "type": "string",
              "value": "={{ $(\"Attach Episode Context\").item.json._podcast_name }}"
            },
            {
              "id": "6",
              "name": "_default_topics",
              "type": "array",
              "value": "={{ $(\"Attach Episode Context\").item.json._default_topics }}"
            },
            {
              "id": "7",
              "name": "transcript_source",
              "type": "string",
              "value": "={{ $(\"Attach Episode Context\").item.json.transcript_source }}"
            },
            {
              "id": "8",
              "name": "source_type",
              "type": "string",
              "value": "={{ $(\"Attach Episode Context\").item.json.source_type }}"
            }
          ]
        },
        "includeOtherFields": true,
        "options": {}
      }
    },
    {
      "name": "Parse Ideas + Split",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        4736,
        1400
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "language": "javaScript",
        "jsCode": "const TOPIC_ALIASES = {\n  \"google gemini\": \"Google\", \"gemini\": \"Google\", \"google\": \"Google\",\n  \"chatgpt\": \"OpenAI\", \"gpt-5\": \"OpenAI\", \"gpt-4\": \"OpenAI\", \"openai\": \"OpenAI\",\n  \"anthropic\": \"Anthropic\", \"claude sonnet\": \"Claude\", \"claude opus\": \"Claude\", \"claude haiku\": \"Claude\", \"claude\": \"Claude\",\n  \"meta ai\": \"Meta\", \"llama\": \"Meta\", \"meta\": \"Meta\",\n  \"agent\": \"Agents\", \"agents\": \"Agents\", \"agentic\": \"Agents\", \"agentic ai\": \"Agents\", \"ai agent\": \"Agents\",\n  \"governance\": \"AI Governance\", \"ai governance\": \"AI Governance\", \"responsible ai\": \"AI Governance\", \"ethics\": \"AI Governance\", \"ai ethics\": \"AI Governance\",\n  \"safety\": \"AI Safety\", \"ai safety\": \"AI Safety\", \"alignment\": \"AI Safety\",\n  \"policy\": \"Policy\", \"regulation\": \"Policy\", \"regulatory\": \"Policy\", \"eu ai act\": \"Policy\",\n  \"marketing\": \"Marketing AI\", \"marketing ai\": \"Marketing AI\", \"advertising\": \"Marketing AI\", \"adtech\": \"Marketing AI\", \"personalization\": \"Marketing AI\",\n  \"measurement\": \"Measurement\", \"attribution\": \"Measurement\", \"analytics\": \"Measurement\",\n  \"strategy\": \"AI Strategy\", \"ai strategy\": \"AI Strategy\", \"enterprise strategy\": \"AI Strategy\",\n  \"llm\": \"LLMs\", \"llms\": \"LLMs\", \"large language model\": \"LLMs\", \"foundation model\": \"LLMs\",\n  \"mcp\": \"MCP\", \"model context protocol\": \"MCP\",\n  \"voice\": \"Voice AI\", \"voice ai\": \"Voice AI\", \"tts\": \"Voice AI\", \"stt\": \"Voice AI\",\n  \"enterprise\": \"Enterprise AI\", \"enterprise ai\": \"Enterprise AI\", \"b2b ai\": \"Enterprise AI\",\n  \"creator\": \"Creator Economy\", \"creator economy\": \"Creator Economy\",\n  \"research\": \"Research\", \"paper\": \"Research\", \"arxiv\": \"Research\",\n  \"content\": \"Content\",\n  \"prompt\": \"Prompt Engineering\", \"prompt engineering\": \"Prompt Engineering\", \"prompting\": \"Prompt Engineering\",\n  \"search\": \"Reddit/Search\", \"reddit\": \"Reddit/Search\", \"perplexity\": \"Reddit/Search\",\n  \"codex\": \"Codex\", \"openai codex\": \"Codex\", \"codex cli\": \"Codex\"\n};\nconst VALID_TOPICS = new Set([\"Claude\",\"Agents\",\"AI Governance\",\"Marketing AI\",\"Measurement\",\"AI Strategy\",\"LLMs\",\"MCP\",\"Voice AI\",\"AI Safety\",\"Enterprise AI\",\"Creator Economy\",\"Policy\",\"Research\",\"Content\",\"Prompt Engineering\",\"Reddit/Search\",\"OpenAI\",\"Anthropic\",\"Google\",\"Meta\",\"Codex\"]);\nfunction normalizeTopics(topics) {\n  const out = new Set();\n  for (const t of (topics || [])) {\n    if (!t) continue;\n    const raw = String(t).trim();\n    if (VALID_TOPICS.has(raw)) { out.add(raw); continue; }\n    const lc = raw.toLowerCase();\n    if (TOPIC_ALIASES[lc]) { out.add(TOPIC_ALIASES[lc]); continue; }\n    // fuzzy contains\n    for (const [alias, canon] of Object.entries(TOPIC_ALIASES)) {\n      if (lc.includes(alias)) { out.add(canon); break; }\n    }\n  }\n  return Array.from(out);\n}\nconst items = $input.all();\nconst out = [];\nlet skipped = 0;\nfor (let i = 0; i < items.length; i++) {\n  const d = items[i].json;\n  const raw = (d.content && d.content[0] && d.content[0].text) ? d.content[0].text : \"{}\";\n  const cleaned = raw.replace(/^\\x60\\x60\\x60json\\s*/i, \"\").replace(/\\x60\\x60\\x60\\s*$/, \"\").trim();\n  const ctx = d;\n  let parsed;\n  try { parsed = JSON.parse(cleaned); } catch (e) {\n    out.push({ json: {\n      _parse_error: e.message, raw: raw.substring(0, 500),\n      episode_url: ctx._episode_url,\n      topic_headline: \"PARSE FAILED: \" + (ctx._episode_title || \"unknown\"),\n      hook: \"Extraction response could not be parsed as JSON.\",\n      key_points: [], observations: [], tips: [], quotes: [], why_it_matters: \"\",\n      open_question: \"\", draft_angle: \"\", further_reading: [], topics: [], audience: [],\n      hot_take_potential: \"Low\", utility: \"Low\", relevance: \"Low\", format: \"Explainer\",\n      episode_title: ctx._episode_title, episode_published: ctx._episode_published,\n      podcast_name: ctx._podcast_name, merged_topics: [],\n      extraction_model: \"Sonnet 4.6\",\n      transcript_source: ctx.transcript_source || \"Unknown\",\n      transcript_id: ctx.transcript_id || \"\",\n      source_page_id: ctx.source_page_id || \"\",\n      source_type: ctx.source_type || \"podcast\"\n    } });\n    continue;\n  }\n  const ideas = parsed.ideas || [];\n  for (const idea of ideas) {\n    const rel = idea.relevance || \"Medium\";\n    const util = idea.utility || \"Medium\";\n    // NOISE FILTER: drop only if BOTH relevance and utility are Low\n    if (rel === \"Low\" && util === \"Low\") { skipped++; continue; }\n    const mergedTopics = Array.from(new Set([\n      ...normalizeTopics(idea.topics || []),\n      ...normalizeTopics(ctx._default_topics || [])\n    ]));\n    out.push({ json: {\n      topic_headline: idea.topic_headline || \"Untitled\",\n      hook: idea.hook || \"\",\n      key_points: idea.key_points || [],\n      observations: idea.observations || [],\n      tips: idea.tips || [],\n      quotes: (idea.quotes || []).filter(q => q && q.quote && String(q.quote).trim().length >= 10),\n      why_it_matters: idea.why_it_matters || \"\",\n      open_question: idea.open_question || \"\",\n      draft_angle: idea.draft_angle || \"\",\n      further_reading: (idea.further_reading || []).filter(r => r && r.url && r.title),\n      topics: idea.topics || [],\n      audience: idea.audience || [],\n      hot_take_potential: idea.hot_take_potential || \"Medium\",\n      utility: util,\n      relevance: rel,\n      format: idea.format || \"Explainer\",\n      episode_summary: parsed.episode_summary || \"\",\n      episode_title: ctx._episode_title || \"\",\n      episode_url: ctx._episode_url || \"\",\n      episode_published: ctx._episode_published || \"\",\n      podcast_name: ctx._podcast_name || \"\",\n      merged_topics: mergedTopics,\n      extraction_model: \"Sonnet 4.6\",\n      transcript_source: ctx.transcript_source || \"Unknown\",\n      transcript_id: ctx.transcript_id || \"\",\n      source_page_id: ctx.source_page_id || \"\",\n      source_type: ctx.source_type || \"podcast\"\n    } });\n  }\n}\nconsole.log(\"Noise filter skipped\", skipped, \"low-rel-low-util ideas\");\nreturn out;\n"
      }
    },
    {
      "name": "Notion: Create Idea Page",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.4,
      "position": [
        4992,
        1400
      ],
      "parameters": {
        "method": "POST",
        "url": "https://api.notion.com/v1/pages",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Notion-Version",
              "value": "2022-06-28"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ parent: { database_id: \"aaaaaaaa-0000-4000-8000-000000000001\" }, properties: { Title: { title: [{ text: { content: ($json.topic_headline || \"Untitled\").substring(0, 200) } }] }, Episode: { rich_text: [{ type: \"text\", text: { content: (($json.podcast_name || \"\") + \" \u2014 \" + ($json.episode_title || \"\")).substring(0, 2000), link: $json.episode_url ? { url: $json.episode_url } : null } }] }, \"Source Type\": { select: { name: $json.source_type === \"vimeo\" ? \"vimeo\" : \"podcast\" } }, Type: { select: { name: \"Idea\" } }, Published: { date: { start: ($json.episode_published || \"\").substring(0, 10) || null } }, \"Hot Take Potential\": { select: { name: $json.hot_take_potential || \"Medium\" } }, Utility: { select: { name: $json.utility || \"Medium\" } }, Relevance: { select: { name: $json.relevance || \"Medium\" } }, Format: { select: { name: $json.format || \"Explainer\" } }, Topics: { multi_select: ($json.merged_topics || []).map(t => ({ name: t })) }, Audience: { multi_select: ($json.audience || []).map(a => ({ name: a })) }, Summary: { rich_text: [{ text: { content: ($json.hook || \"\").substring(0, 2000) } }] }, \"Extraction Model\": { select: { name: $json.extraction_model || \"Sonnet 4.6\" } }, \"Transcript Source\": { select: { name: $json.transcript_source || \"Unknown\" } }, \"Transcript ID\": { rich_text: [{ text: { content: ($json.transcript_id || \"\").substring(0, 2000) } }] }, \"Episode Source\": $json.source_page_id ? { relation: [{ id: $json.source_page_id }] } : { relation: [] } }, children: [{ object: \"block\", type: \"heading_2\", heading_2: { rich_text: [{ type: \"text\", text: { content: \"Hook\" } }] } }, { object: \"block\", type: \"paragraph\", paragraph: { rich_text: [{ type: \"text\", text: { content: ($json.hook || \"\").substring(0, 2000) } }] } }, { object: \"block\", type: \"heading_2\", heading_2: { rich_text: [{ type: \"text\", text: { content: \"Key Points\" } }] } }, ...($json.key_points || []).map(p => ({ object: \"block\", type: \"bulleted_list_item\", bulleted_list_item: { rich_text: [{ type: \"text\", text: { content: String(p).substring(0, 2000) } }] } })), ...(($json.observations || []).length ? [{ object: \"block\", type: \"heading_2\", heading_2: { rich_text: [{ type: \"text\", text: { content: \"Observations\" } }] } }, ...($json.observations || []).map(p => ({ object: \"block\", type: \"bulleted_list_item\", bulleted_list_item: { rich_text: [{ type: \"text\", text: { content: String(p).substring(0, 2000) } }] } }))] : []), ...(($json.tips || []).length ? [{ object: \"block\", type: \"heading_2\", heading_2: { rich_text: [{ type: \"text\", text: { content: \"Tips\" } }] } }, ...($json.tips || []).map(p => ({ object: \"block\", type: \"bulleted_list_item\", bulleted_list_item: { rich_text: [{ type: \"text\", text: { content: String(p).substring(0, 2000) } }] } }))] : []), ...(($json.quotes || []).length ? [{ object: \"block\", type: \"heading_2\", heading_2: { rich_text: [{ type: \"text\", text: { content: \"Quotes\" } }] } }, ...($json.quotes || []).map(q => ({ object: \"block\", type: \"quote\", quote: { rich_text: [{ type: \"text\", text: { content: (\"\\\"\" + (q.quote || \"\") + \"\\\" \u2014 \" + (q.speaker || \"Unknown\") + (q.timestamp ? \" (\" + q.timestamp + \")\" : \"\")).substring(0, 2000) } }] } }))] : []), { object: \"block\", type: \"heading_2\", heading_2: { rich_text: [{ type: \"text\", text: { content: \"Why It Matters\" } }] } }, { object: \"block\", type: \"paragraph\", paragraph: { rich_text: [{ type: \"text\", text: { content: ($json.why_it_matters || \"\").substring(0, 2000) } }] } }, { object: \"block\", type: \"heading_2\", heading_2: { rich_text: [{ type: \"text\", text: { content: \"Open Question\" } }] } }, { object: \"block\", type: \"paragraph\", paragraph: { rich_text: [{ type: \"text\", text: { content: ($json.open_question || \"\").substring(0, 2000) } }] } }, { object: \"block\", type: \"heading_2\", heading_2: { rich_text: [{ type: \"text\", text: { content: \"Draft Angle\" } }] } }, { object: \"block\", type: \"callout\", callout: { icon: { type: \"emoji\", emoji: \"\ud83d\udca1\" }, rich_text: [{ type: \"text\", text: { content: ($json.draft_angle || \"\").substring(0, 2000) } }] } }, ...(($json.further_reading || []).length ? [{ object: \"block\", type: \"heading_2\", heading_2: { rich_text: [{ type: \"text\", text: { content: \"Further Reading\" } }] } }, ...($json.further_reading || []).map(r => ({ object: \"block\", type: \"bulleted_list_item\", bulleted_list_item: { rich_text: [{ type: \"text\", text: { content: (r.title || r.url || \"\").substring(0, 2000), link: r.url ? { url: r.url } : null } }] } }))] : []), { object: \"block\", type: \"divider\", divider: {} }, { object: \"block\", type: \"paragraph\", paragraph: { rich_text: [{ type: \"text\", text: { content: \"Source: \" + ($json.podcast_name || \"\") + \" \u2014 \" + ($json.episode_title || \"\") + \" [model: \" + ($json.extraction_model || \"\") + \" | transcript: \" + ($json.transcript_source || \"\") + \" | type: \" + ($json.source_type || \"podcast\") + \"]\" } }] } } ] }) }}",
        "options": {
          "batching": {
            "batch": {
              "batchSize": 3,
              "batchInterval": 400
            }
          },
          "timeout": 60000
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "onError": "continueRegularOutput",
      "retryOnFail": true,
      "maxTries": 3,
      "waitBetweenTries": 5000
    },
    {
      "name": "Feed Config List",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        288,
        608
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "language": "javaScript",
        "jsCode": "// Emit one item per podcast feed, carrying metadata so the downstream\n// enrich step can attach it to each RSS item. Nate's Notebook excluded\n// (Substack private feed 403s from n8n cloud IPs \u2014 fix separately with HTTP+UA).\nconst feeds = [\n  { url: 'https://www.patreon.com/rss/AIDailyBrief?auth=REDACTED_ROTATE_ME&show=1430346', podcast_name: 'AI Daily Brief', always_relevant: true, default_topics: ['AI Strategy'], podcast_priority: 'high' },\n  { url: 'https://feeds.megaphone.fm/marketingai', podcast_name: 'The Artificial Intelligence Show', always_relevant: true, default_topics: ['Marketing AI'], podcast_priority: 'high' },\n  { url: 'https://feeds.simplecast.com/l2i9YnTd', podcast_name: 'Hard Fork', always_relevant: false, default_topics: [], podcast_priority: 'high' },\n  { url: 'https://feeds.simplecast.com/Rz_NWJDG', podcast_name: 'Decoding AI for Marketing', always_relevant: true, default_topics: ['Marketing AI','Measurement'], podcast_priority: 'high' },\n  { url: 'https://feeds.megaphone.fm/buildingbettercmos', podcast_name: 'Building Better CMOs', always_relevant: false, default_topics: [], podcast_priority: 'low' },\n  { url: 'https://rss.libsyn.com/shows/45920/destinations/151434.xml', podcast_name: 'AI in Business', always_relevant: true, default_topics: ['Enterprise AI'], podcast_priority: 'medium' },\n  { url: 'https://feeds.megaphone.fm/PDP6186156462', podcast_name: 'Frontier CMO', always_relevant: false, default_topics: [], podcast_priority: 'low' },\n  { url: 'https://rss.art19.com/the-cmo-podcast', podcast_name: 'The CMO Podcast', always_relevant: false, default_topics: [], podcast_priority: 'low' },\n  { url: 'https://feeds.buzzsprout.com/2418777.rss', podcast_name: 'AI Explained', always_relevant: true, default_topics: ['Research'], podcast_priority: 'high' },\n  { url: 'https://changelog.com/practicalai/feed', podcast_name: 'Practical AI', always_relevant: true, default_topics: ['AI Strategy'], podcast_priority: 'medium' },\n  { url: 'https://feeds.megaphone.fm/vergecast', podcast_name: 'The Vergecast', always_relevant: false, default_topics: ['Policy'], podcast_priority: 'medium' },\n  { url: 'https://rss.buzzsprout.com/1786427.rss', podcast_name: 'The Good Robot', always_relevant: true, default_topics: ['AI Governance','AI Safety'], podcast_priority: 'high' },\n  { url: 'https://feeds.transistor.fm/in-ai-we-trust', podcast_name: 'In AI We Trust', always_relevant: false, default_topics: ['AI Governance'], podcast_priority: 'low' },\n  { url: 'https://rss.libsyn.com/shows/539322/destinations/4646017.xml', podcast_name: 'AI Governance (Enzai)', always_relevant: true, default_topics: ['AI Governance','Policy'], podcast_priority: 'high' },\n  { url: 'https://feeds.simplecast.com/rZ0cYk12', podcast_name: 'Your Undivided Attention', always_relevant: true, default_topics: ['AI Governance','AI Safety'], podcast_priority: 'high' },\n  { url: 'https://feeds.megaphone.fm/CSIS8973369418', podcast_name: 'The AI Policy Podcast', always_relevant: true, default_topics: ['Policy','AI Governance'], podcast_priority: 'high' },\n  { url: 'https://rss.buzzsprout.com/2175779.rss', podcast_name: 'Everyday AI', always_relevant: false, default_topics: ['Marketing AI','AI Strategy'], podcast_priority: 'medium' },\n  { url: 'https://rss.libsyn.com/shows/123267/destinations/727317.xml', podcast_name: 'Eye on AI', always_relevant: false, default_topics: ['Research','Enterprise AI'], podcast_priority: 'medium' },\n];\nreturn feeds.map(f => ({ json: f }));"
      }
    },
    {
      "name": "HTTP: Fetch Raw RSS",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.4,
      "position": [
        544,
        608
      ],
      "parameters": {
        "method": "GET",
        "url": "={{ $json.url }}",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "User-Agent",
              "value": "Mozilla/5.0 (content-pipeline/1.0)"
            },
            {
              "name": "Accept",
              "value": "application/rss+xml, application/xml, text/xml, */*"
            }
          ]
        },
        "options": {
          "timeout": 30000,
          "response": {
            "response": {
              "responseFormat": "text"
            }
          }
        }
      },
      "onError": "continueRegularOutput"
    },
    {
      "name": "Parse + Filter + Enrich",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        800,
        608
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "language": "javaScript",
        "jsCode": "const WINDOW_DAYS = 7;\nconst cutoff = Date.now() - WINDOW_DAYS * 24 * 60 * 60 * 1000;\nconst keywords = [\"ai\",\"artificial intelligence\",\"claude\",\"gpt\",\"anthropic\",\"openai\",\"gemini\",\"agent\",\"llm\",\"machine learning\",\"marketing ai\",\"martech\",\"copilot\",\"automation\",\"mcp\",\"model context protocol\"];\nfunction getTag(tag, block) {\n  const re = new RegExp(\"<\" + tag + \"(?:\\\\s[^>]*)?>([\\\\s\\\\S]*?)<\\\\/\" + tag + \">\", \"i\");\n  const m = block.match(re);\n  if (!m) return \"\";\n  let v = m[1];\n  v = v.replace(/^\\s*<!\\[CDATA\\[/, \"\").replace(/\\]\\]>\\s*$/, \"\");\n  return v.trim();\n}\nfunction getAttr(tag, name, block) {\n  const re = new RegExp(\"<\" + tag + \"[^>]*\\\\b\" + name + \"=\\\"([^\\\"]*)\\\"\", \"i\");\n  const m = block.match(re);\n  return m ? m[1] : \"\";\n}\nfunction pickEpisodeUrl(block) {\n  const link = getTag(\"link\", block);\n  if (link && /^https?:\\/\\//i.test(link)) return link;\n  const atomHref = getAttr(\"atom:link\", \"href\", block);\n  if (atomHref && /^https?:\\/\\//i.test(atomHref)) return atomHref;\n  const gipm = /<guid[^>]*isPermaLink=\\\"true\\\"[^>]*>([\\s\\S]*?)<\\/guid>/i.exec(block);\n  if (gipm) {\n    const v = gipm[1].replace(/^\\s*<!\\[CDATA\\[/, \"\").replace(/\\]\\]>\\s*$/, \"\").trim();\n    if (/^https?:\\/\\//i.test(v)) return v;\n  }\n  const g = getTag(\"guid\", block);\n  if (g && /^https?:\\/\\//i.test(g)) return g;\n  return \"\";\n}\nconst out = [];\nconst httpItems = $input.all();\nfor (let i = 0; i < httpItems.length; i++) {\n  const it = httpItems[i].json;\n  if (it._http_error || it.error) continue;\n  const xml = (typeof it.data === \"string\" ? it.data : (typeof it.body === \"string\" ? it.body : \"\"));\n  if (!xml) continue;\n  const feed = $(\"Feed Config List\").itemMatching(i).json;\n  const itemRe = /<item(?:\\s[^>]*)?>[\\s\\S]*?<\\/item>/gi;\n  let m;\n  while ((m = itemRe.exec(xml)) !== null) {\n    const block = m[0];\n    const pub = getTag(\"pubDate\", block) || getTag(\"dc:date\", block) || getTag(\"published\", block);\n    if (!pub) continue;\n    const t = new Date(pub).getTime();\n    if (isNaN(t) || t < cutoff) continue;\n    const title = getTag(\"title\", block);\n    const episodeUrl = pickEpisodeUrl(block);\n    const enclosureUrl = getAttr(\"enclosure\", \"url\", block);\n    if (!enclosureUrl) continue;\n    const descRaw = getTag(\"description\", block) || getTag(\"content:encoded\", block) || \"\";\n    const descText = descRaw.replace(/<[^>]+>/g, \" \").replace(/\\s+/g, \" \").trim().substring(0, 500);\n    const text = (title + \" \" + descText).toLowerCase();\n    const keywordHit = keywords.some(k => text.includes(k));\n    const isRelevant = feed.always_relevant || keywordHit;\n    if (!isRelevant) continue;\n    out.push({ json: {\n      title,\n      link: episodeUrl,\n      isoDate: new Date(t).toISOString(),\n      pubDate: pub,\n      contentSnippet: descText,\n      audio_url: enclosureUrl,\n      podcast_name: feed.podcast_name,\n      default_topics: feed.default_topics,\n      podcast_priority: feed.podcast_priority\n    }});\n  }\n}\nreturn out;\n"
      }
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.notion.com/v1/pages",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Notion-Version",
              "value": "2022-06-28"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify((() => {\n  const title = ($json._podcast_name || \"Source\") + \" \u2014 \" + ($json._episode_title || \"Episode\");\n  const transcript = $json.transcript || \"\";\n  const chapters = JSON.parse($json.chapters_json || \"[]\");\n  const chaptersTextForProp = chapters.map(c => (c.headline || \"\") + \": \" + (c.gist || c.summary || \"\")).join(\" | \");\n  const tChunks = [];\n  for (let i = 0; i < transcript.length; i += 1900) tChunks.push(transcript.substring(i, i + 1900));\n  if (!tChunks.length) tChunks.push(\"\");\n  const tBlocks = tChunks.slice(0, 80).map(c => ({ object: \"block\", type: \"paragraph\", paragraph: { rich_text: [{ type: \"text\", text: { content: c } }] } }));\n  const chBlocks = chapters.length ? [\n    { object: \"block\", type: \"heading_2\", heading_2: { rich_text: [{ type: \"text\", text: { content: \"Chapters\" } }] } },\n    ...chapters.map(c => ({ object: \"block\", type: \"bulleted_list_item\", bulleted_list_item: { rich_text: [{ type: \"text\", text: { content: ((c.headline || \"\") + \" \u2014 \" + (c.gist || c.summary || \"\")).substring(0, 2000) } }] } }))\n  ] : [];\n  return {\n    parent: { databas

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Content Pipeline: Podcast RSS + Vimeo Intake. Uses httpRequest, googleDrive. Scheduled trigger; 40 nodes.

Source: https://github.com/alectivism/n8n-workflows/blob/main/podcast-intake/workflow.json — original creator credit. Request a take-down →

More Content & Video workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Content & Video

Human Anatomy Shorts — Fully Synced + Visually Consistent (FLUX Keyframe + Hailuo 2.0 I2V). Uses googleSheets, httpRequest, telegram, googleDrive. Scheduled trigger; 33 nodes.

Google Sheets, HTTP Request, Telegram +2
Content & Video

This workflow automates the entire process of creating, managing, and publishing AI-generated videos using OpenAI Sora2 Pro, Google Sheets, Google Drive, and YouTube.

HTTP Request, Google Sheets, Google Drive +1
Content & Video

watch this video

YouTube, Google Sheets, Agent +2
Content & Video

Auto WordPress Blog Generator (GPT + Postgres + WP Media). Uses httpRequest, postgres. Scheduled trigger; 46 nodes.

HTTP Request, Postgres
Content & Video

This n8n workflow automatically syncs your WordPress website content — including posts, categories, tags, and media — into Google Sheets.

HTTP Request, Google Sheets