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": "Video Story Generator",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "gen-video",
"responseMode": "responseNode",
"options": {}
},
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [
200,
460
],
"id": "webhook-node",
"name": "Webhook"
},
{
"parameters": {
"method": "POST",
"url": "https://api.groq.com/openai/v1/chat/completions",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "Bearer {{ $vars.GROQ_API_KEY }}"
}
]
},
"sendBody": true,
"contentType": "json",
"body": "{\n \"model\": \"llama-3.3-70b-versatile\",\n \"response_format\": { \"type\": \"json_object\" },\n \"messages\": [\n {\n \"role\": \"system\",\n \"content\": \"You are a creative storyteller. Always respond with valid JSON only. No markdown, no explanation.\"\n },\n {\n \"role\": \"user\",\n \"content\": \"Create a story based on the theme: '{{ $json.body.theme }}'. Divide the story into exactly 12 scenes, each suitable for a 5-second video clip. Each scene should have a vivid, visual description that can be used as a text-to-video prompt. Return a JSON object with a 'scenes' array containing exactly 12 strings, where each string is a detailed visual description of that scene (50-80 words, cinematic style).\"\n }\n ]\n}"
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
320,
460
],
"id": "groq-node",
"name": "HTTP Request"
},
{
"parameters": {
"jsCode": "const content = $input.first().json.choices[0].message.content;\nconst cleanContent = content.replace(/```json\\n?/g, '').replace(/```\\n?/g, '').trim();\nconst parsed = JSON.parse(cleanContent);\nconst scenes = parsed.scenes || parsed;\nreturn scenes.map((scene, i) => ({ json: { scene: typeof scene === 'string' ? scene : scene.description || scene.prompt || JSON.stringify(scene), sceneIndex: i, index: i } }));"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
460,
460
],
"id": "parse-scenes-node",
"name": "Code in JavaScript"
},
{
"parameters": {
"options": {}
},
"type": "n8n-nodes-base.splitInBatches",
"typeVersion": 3,
"position": [
600,
460
],
"id": "loop-node",
"name": "Loop Over Items"
},
{
"parameters": {
"method": "POST",
"url": "https://queue.fal.run/fal-ai/wan/v2.1/t2v",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "Key {{ $vars.FAL_API_KEY }}"
}
]
},
"sendBody": true,
"contentType": "json",
"body": "{\n \"prompt\": \"{{ $json.scene }}\",\n \"duration\": \"5\",\n \"aspect_ratio\": \"16:9\",\n \"enable_safety_checker\": false\n}"
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
740,
420
],
"id": "fal-submit-node",
"name": "HTTP Request1"
},
{
"parameters": {
"amount": 15,
"unit": "seconds"
},
"type": "n8n-nodes-base.wait",
"typeVersion": 1.1,
"position": [
880,
420
],
"id": "wait-node",
"name": "Wait"
},
{
"parameters": {
"method": "GET",
"url": "https://queue.fal.run/fal-ai/wan/v2.1/t2v/requests/{{ $('HTTP Request1').item.json.request_id }}/status",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "Key {{ $vars.FAL_API_KEY }}"
}
]
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1020,
420
],
"id": "fal-status-node",
"name": "HTTP Request2"
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "status-check",
"leftValue": "={{ $json.status }}",
"rightValue": "COMPLETED",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
1160,
420
],
"id": "if-node",
"name": "If"
},
{
"parameters": {
"method": "GET",
"url": "={{ $json.response_url }}",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "Key {{ $vars.FAL_API_KEY }}"
}
]
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1300,
380
],
"id": "fal-result-node",
"name": "HTTP Request3"
},
{
"parameters": {
"jsCode": "const items = $input.all();\nreturn items.map(item => ({\n json: {\n videoUrl: item.json.video?.url || item.json.output?.video?.url || item.json.output?.url || '',\n sceneIndex: item.json.sceneIndex ?? item.json.index ?? 0,\n scene: item.json.scene || ''\n }\n}));"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1440,
380
],
"id": "extract-url-node",
"name": "Code in JavaScript1"
},
{
"parameters": {
"aggregate": "aggregateAllItemData",
"destinationFieldName": "videoUrls",
"include": "allFields",
"options": {}
},
"type": "n8n-nodes-base.aggregate",
"typeVersion": 1,
"position": [
740,
530
],
"id": "aggregate-node",
"name": "Aggregate"
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ JSON.stringify({ success: true, videoUrls: $json.videoUrls.map(v => v.videoUrl).filter(u => u) }) }}",
"options": {}
},
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.1,
"position": [
880,
530
],
"id": "respond-node",
"name": "Respond to Webhook"
}
],
"connections": {
"Webhook": {
"main": [
[
{
"node": "HTTP Request",
"type": "main",
"index": 0
}
]
]
},
"HTTP Request": {
"main": [
[
{
"node": "Code in JavaScript",
"type": "main",
"index": 0
}
]
]
},
"Code in JavaScript": {
"main": [
[
{
"node": "Loop Over Items",
"type": "main",
"index": 0
}
]
]
},
"Loop Over Items": {
"main": [
[
{
"node": "HTTP Request1",
"type": "main",
"index": 0
}
],
[
{
"node": "Aggregate",
"type": "main",
"index": 0
}
]
]
},
"HTTP Request1": {
"main": [
[
{
"node": "Wait",
"type": "main",
"index": 0
}
]
]
},
"Wait": {
"main": [
[
{
"node": "HTTP Request2",
"type": "main",
"index": 0
}
]
]
},
"HTTP Request2": {
"main": [
[
{
"node": "If",
"type": "main",
"index": 0
}
]
]
},
"If": {
"main": [
[
{
"node": "HTTP Request3",
"type": "main",
"index": 0
}
],
[
{
"node": "Wait",
"type": "main",
"index": 0
}
]
]
},
"HTTP Request3": {
"main": [
[
{
"node": "Code in JavaScript1",
"type": "main",
"index": 0
}
]
]
},
"Code in JavaScript1": {
"main": [
[
{
"node": "Loop Over Items",
"type": "main",
"index": 0
}
]
]
},
"Aggregate": {
"main": [
[
{
"node": "Respond to Webhook",
"type": "main",
"index": 0
}
]
]
},
"Respond to Webhook": {
"main": [
[]
]
}
},
"settings": {
"executionOrder": "v1"
},
"staticData": null,
"meta": {
"templateCredsSetupCompleted": true
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Video Story Generator. Uses httpRequest. Webhook trigger; 12 nodes.
Source: https://gist.github.com/venkat1609/7285615a20ad3a407a91b985df7c8e4c — 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.
This n8n template provides enterprise-level version control for your workflows using GitHub integration. Stop losing hours to broken workflows and manual exports – get proper commit history, visual di
This flow creates dummy files for every item added in your *Arrs (Radarr/Sonarr) with the tag .
This workflow acts as a central API gateway for all technical indicator agents in the Binance Spot Market Quant AI system. It listens for incoming webhook requests and dynamically routes them to the c
Sign PDF documents with legally-compliant digital signatures using X.509 certificates. Supports multiple PAdES signature levels (B, T, LT, LTA) with optional visible stamps.
📡 This workflow serves as the central Alpha Vantage API fetcher for Tesla trading indicators, delivering cleaned 20-point JSON outputs for three timeframes: , , and . It is required by the following a