This workflow follows the Execute Workflow Trigger → 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 →
{
"name": "02 - Video Pipeline",
"nodes": [
{
"parameters": {},
"name": "Execute Workflow Trigger",
"type": "n8n-nodes-base.executeWorkflowTrigger",
"position": [
250,
300
],
"typeVersion": 1.1
},
{
"parameters": {
"method": "GET",
"url": "={{ $json.link }}",
"options": {
"response": {
"response": {
"fullResponse": false
}
}
}
},
"name": "Fetch Article",
"type": "n8n-nodes-base.httpRequest",
"position": [
450,
300
],
"typeVersion": 1
},
{
"parameters": {
"dataType": "json",
"options": {}
},
"name": "HTML to Text",
"type": "n8n-nodes-base.extractFromFile",
"position": [
650,
300
],
"typeVersion": 1
},
{
"parameters": {
"method": "POST",
"url": "https://openrouter.ai/api/v1/chat/completions",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendBody": true,
"contentType": "json",
"body": {
"model": "google/gemini-2.0-flash-exp:free",
"messages": [
{
"role": "system",
"content": "You are a professional news script writer for 'The Update Desk' YouTube channel. Write engaging, factual news scripts in a broadcast news style."
},
{
"role": "user",
"content": "=Write a compelling news script based on this article:\n\nTitle: {{ $json.title }}\nSource: {{ $json.source }}\nContent: {{ $json.content }}\n\nRequirements:\n- Target length: 12-20 minutes of speech (very flexible based on story complexity)\n- Style: Professional news anchor, conversational yet authoritative\n- Structure: Hook intro (30s) \u2192 Context background (2-3min) \u2192 Main story development (6-12min) \u2192 Analysis/implications (3-5min) \u2192 Outro (30s)\n- Include specific visual cues for B-roll\n- Add lower third text suggestions\n- Optimize for YouTube virality: strong hook, clear narrative arc, memorable takeaways\n\nReturn JSON format:\n{\n \"youtubeTitle\": \"Viral-optimized title under 60 chars\",\n \"description\": \"SEO description with timestamps\",\n \"tags\": [\"tag1\", \"tag2\", \"tag3\"],\n \"segments\": [\n {\n \"type\": \"intro|background|development|analysis|outro\",\n \"script\": \"Spoken text...\",\n \"visualType\": \"stock_video|seedance|web_image|generated_image|static_title\",\n \"visualQuery\": \"Search query or prompt\",\n \"lowerThird\": \"Lower third text\",\n \"duration\": 120\n }\n ]\n}"
}
]
},
"options": {}
},
"name": "Generate Script",
"type": "n8n-nodes-base.httpRequest",
"position": [
950,
300
],
"typeVersion": 1
},
{
"parameters": {
"jsCode": "// Parse LLM response and prepare segments\nconst response = $input.all()[0].json;\nlet scriptData;\n\ntry {\n // Try to parse from content\n const content = response.choices?.[0]?.message?.content || response.content || response;\n const jsonMatch = content.match(/```json\\n?([\\s\\S]*?)\\n?```/) || content.match(/{[\\s\\S]*}/);\n scriptData = JSON.parse(jsonMatch ? jsonMatch[1] || jsonMatch[0] : content);\n} catch (e) {\n // Fallback structure\n scriptData = {\n youtubeTitle: 'Breaking News Update',\n description: 'Latest news from The Update Desk',\n tags: ['news', 'breaking'],\n segments: [{\n type: 'intro',\n script: 'Welcome to The Update Desk.',\n visualType: 'static_title',\n visualQuery: 'news studio',\n lowerThird: 'BREAKING NEWS',\n duration: 60\n }]\n };\n}\n\n// Add metadata\nreturn {\n ...scriptData,\n articleTitle: $input.all()[0].json.title,\n articleUrl: $input.all()[0].json.link,\n articleSource: $input.all()[0].json.source,\n timestamp: new Date().toISOString(),\n videoId: Math.random().toString(36).substring(7)\n};"
},
"name": "Parse Script",
"type": "n8n-nodes-base.code",
"position": [
1250,
300
],
"typeVersion": 2
},
{
"parameters": {
"jsCode": "// Split into individual items for each segment\nconst data = $input.all()[0].json;\nconst segments = data.segments || [];\n\nreturn segments.map((segment, index) => ({\n ...segment,\n videoId: data.videoId,\n youtubeTitle: data.youtubeTitle,\n description: data.description,\n tags: data.tags,\n articleTitle: data.articleTitle,\n articleUrl: data.articleUrl,\n segmentIndex: index,\n totalSegments: segments.length\n}));"
},
"name": "Split Segments",
"type": "n8n-nodes-base.code",
"position": [
1450,
300
],
"typeVersion": 2
},
{
"parameters": {
"method": "POST",
"url": "https://render-service-production-3b75.up.railway.app/generate-image",
"body": {
"prompt": "={{ $json.visualQuery }}",
"output": "=/files/images/{{ $json.videoId }}_{{ $json.segmentIndex }}.jpg",
"model": "black-forest-labs/flux.2-klein-4b",
"aspectRatio": "16:9"
},
"options": {}
},
"name": "Generate Thumbnail",
"type": "n8n-nodes-base.httpRequest",
"position": [
1650,
200
],
"typeVersion": 1
},
{
"parameters": {
"method": "POST",
"url": "https://api.speechify.ai/v1/audio/stream",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendBody": true,
"contentType": "json",
"body": {
"input": "={{ $json.script }}",
"voice_id": "nick",
"model": "simba-english",
"audio_format": "mp3",
"options": {
"text_normalization": false,
"loudness_normalization": true
}
},
"options": {}
},
"name": "Generate TTS",
"type": "n8n-nodes-base.httpRequest",
"position": [
1650,
400
],
"typeVersion": 1
},
{
"parameters": {
"method": "POST",
"url": "https://render-service-production-3b75.up.railway.app/fetch-visual",
"body": {
"type": "={{ $json.visualType === 'stock_video' ? 'pexels' : $json.visualType === 'web_image' ? 'web' : 'pexels' }}",
"query": "={{ $json.visualQuery }}",
"output": "=/files/video/{{ $json.videoId }}_{{ $json.segmentIndex }}.mp4"
},
"options": {}
},
"name": "Fetch Visual",
"type": "n8n-nodes-base.httpRequest",
"position": [
1850,
400
],
"typeVersion": 1
},
{
"parameters": {
"method": "POST",
"url": "https://render-service-production-3b75.up.railway.app/generate-seedance",
"body": {
"prompt": "={{ $json.visualQuery }}",
"output": "=/files/video/{{ $json.videoId }}_{{ $json.segmentIndex }}_seedance.mp4",
"duration": 8,
"width": 1280,
"height": 720
},
"options": {}
},
"name": "Generate Seedance",
"type": "n8n-nodes-base.httpRequest",
"position": [
1850,
600
],
"typeVersion": 1
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "c1",
"leftValue": "={{ $json.visualType }}",
"rightValue": "seedance",
"operator": {
"type": "string",
"operation": "equals"
}
}
]
}
},
"name": "Is Seedance?",
"type": "n8n-nodes-base.if",
"position": [
1650,
550
],
"typeVersion": 2
},
{
"parameters": {
"jsCode": "// Aggregate all segment results\nconst allSegments = $input.all();\nconst videoId = allSegments[0].json.videoId;\n\n// Build render manifest\nconst manifest = {\n output: `/files/output/${videoId}.mp4`,\n segments: allSegments.map(item => ({\n type: item.json.type || 'segment',\n audio: `/files/audio/${videoId}_${item.json.segmentIndex}.mp3`,\n visual: item.json.visualPath || `/files/video/${videoId}_${item.json.segmentIndex}.mp4`,\n lowerThird: item.json.lowerThird,\n title: item.json.type === 'intro' ? item.json.youtubeTitle : undefined\n })),\n music: '/files/audio/background_music_1.mp3',\n musicVolume: 0.15,\n thumbnail: {\n output: `/files/images/${videoId}_thumb.jpg`,\n title: allSegments[0].json.youtubeTitle,\n image: `/files/images/${videoId}_0.jpg`,\n style: 'viral-news'\n }\n};\n\nreturn {\n ...manifest,\n youtubeTitle: allSegments[0].json.youtubeTitle,\n description: allSegments[0].json.description,\n tags: allSegments[0].json.tags,\n videoId\n};"
},
"name": "Build Manifest",
"type": "n8n-nodes-base.code",
"position": [
2050,
400
],
"typeVersion": 2
},
{
"parameters": {
"method": "POST",
"url": "https://render-service-production-3b75.up.railway.app/render",
"body": {
"output": "={{ $json.output }}",
"segments": "={{ $json.segments }}",
"music": "={{ $json.music }}",
"musicVolume": "={{ $json.musicVolume }}",
"thumbnail": "={{ $json.thumbnail }}"
},
"options": {}
},
"name": "Render Video",
"type": "n8n-nodes-base.httpRequest",
"position": [
2250,
400
],
"typeVersion": 1
},
{
"parameters": {
"method": "GET",
"url": "https://render-service-production-3b75.up.railway.app/status/{{ $json.jobId }}",
"options": {}
},
"name": "Poll Render Status",
"type": "n8n-nodes-base.httpRequest",
"position": [
2450,
400
],
"typeVersion": 1
},
{
"parameters": {
"amount": 10,
"unit": "seconds"
},
"name": "Wait",
"type": "n8n-nodes-base.wait",
"position": [
2650,
400
],
"typeVersion": 1
},
{
"parameters": {
"workflowId": "=03 - YouTube Publisher",
"mode": "trigger"
},
"name": "Publish to YouTube",
"type": "n8n-nodes-base.executeWorkflow",
"position": [
2850,
400
],
"typeVersion": 1.1
}
],
"connections": {
"Execute Workflow Trigger": {
"main": [
[
{
"node": "Fetch Article",
"type": "main",
"index": 0
}
]
]
},
"Fetch Article": {
"main": [
[
{
"node": "HTML to Text",
"type": "main",
"index": 0
}
]
]
},
"HTML to Text": {
"main": [
[
{
"node": "Generate Script",
"type": "main",
"index": 0
}
]
]
},
"Generate Script": {
"main": [
[
{
"node": "Parse Script",
"type": "main",
"index": 0
}
]
]
},
"Parse Script": {
"main": [
[
{
"node": "Generate Thumbnail",
"type": "main",
"index": 0
},
{
"node": "Split Segments",
"type": "main",
"index": 0
}
]
]
},
"Split Segments": {
"main": [
[
{
"node": "Generate TTS",
"type": "main",
"index": 0
},
{
"node": "Is Seedance?",
"type": "main",
"index": 0
}
]
]
},
"Generate TTS": {
"main": [
[
{
"node": "Fetch Visual",
"type": "main",
"index": 0
}
]
]
},
"Fetch Visual": {
"main": [
[
{
"node": "Build Manifest",
"type": "main",
"index": 0
}
]
]
},
"Generate Seedance": {
"main": [
[
{
"node": "Build Manifest",
"type": "main",
"index": 0
}
]
]
},
"Is Seedance?": {
"main": [
[
{
"node": "Generate Seedance",
"type": "main",
"index": 0
}
],
[
{
"node": "Fetch Visual",
"type": "main",
"index": 0
}
]
]
},
"Build Manifest": {
"main": [
[
{
"node": "Render Video",
"type": "main",
"index": 0
}
]
]
},
"Render Video": {
"main": [
[
{
"node": "Poll Render Status",
"type": "main",
"index": 0
}
]
]
},
"Poll Render Status": {
"main": [
[
{
"node": "Wait",
"type": "main",
"index": 0
}
]
]
},
"Wait": {
"main": [
[
{
"node": "Publish to YouTube",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1"
},
"staticData": null,
"tags": []
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
02 - Video Pipeline. Uses executeWorkflowTrigger, httpRequest. Event-driven trigger; 16 nodes.
Source: https://github.com/nickaisbitt/vidomator/blob/154414693c2f673f3222778ffdb821493f9130e0/n8n-workflows/02-video-pipeline.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
02_LLM_Pipeline v1.0. Uses executeWorkflowTrigger, httpRequest, seaTable. Event-driven trigger; 65 nodes.
This template is a powerful, reusable utility for managing stateful, long-running processes. It allows a main workflow to be paused indefinitely at "checkpoints" and then be resumed by external, async
Upload files from any source to your account Kommo or AmoCRM with a simple and reusable workflow. It can split a large file into small ones and upload chunks. Works for Kommo and amoCRM There are 3 re
Remixed Backup your workflows to GitHub from Solomon's work. Check out his templates.
Remixed Backup your workflows to GitHub from Solomon's work. Check out his templates.