{
  "name": "Generic Flux + Runway Video Factory",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "video-factory",
        "options": {}
      },
      "id": "1",
      "name": "Webhook Trigger",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 1,
      "position": [150, 400]
    },
    {
      "parameters": {
        "model": "gpt-4o",
        "messages": {
          "messageValues": [
            {
              "role": "system",
              "message": "You are an elite creative video director and prompt engineer. Your job is to take a video topic and generate a high-converting 3-scene video storyboard.\n\nFor each of the 3 scenes, generate:\n1. A powerful narration script (roughly 15-20 seconds long).\n2. A highly descriptive image prompt optimized for Flux image generation (oil painting, detailed, high contrast, cinematic lighting, 16:9 aspect ratio).\n3. A motion direction prompt for Runway ML image-to-video (e.g., \"slow camera pan, subtle character head turn, embers floating, highly realistic motion\").\n\nOutput ONLY a valid JSON object matching this structure:\n{\n  \"scenes\": [\n    {\n      \"sceneNumber\": 1,\n      \"narration\": \"string\",\n      \"fluxPrompt\": \"string\",\n      \"runwayMotion\": \"string\"\n    }\n  ]\n}"
            },
            {
              "role": "user",
              "message": "={{ $json.body?.topic || \"The Fall of Rome\" }}"
            }
          ]
        },
        "options": {
          "responseFormat": "json_object"
        }
      },
      "id": "2",
      "name": "AI Storyboard Director",
      "type": "n8n-nodes-base.openAi",
      "typeVersion": 1,
      "position": [350, 400]
    },
    {
      "parameters": {
        "jsCode": "const storyboard = JSON.parse($input.first().json.choices[0].message.content);\nreturn storyboard.scenes;"
      },
      "id": "3",
      "name": "Parse Storyboard",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [550, 400]
    },
    {
      "parameters": {
        "fieldToSplitOut": "scenes",
        "options": {}
      },
      "id": "4",
      "name": "Split Scenes",
      "type": "n8n-nodes-base.splitOut",
      "typeVersion": 1,
      "position": [750, 400]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.replicate.com/v1/predictions",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendHeaders": true,
        "headersUi": {
          "parameter": [
            {
              "name": "Authorization",
              "value": "Bearer your_replicate_api_token_here"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"version\": \"db21e45d3f7023e141f108d85a15b17c3202934affd88b9a326e56a47b4d13c7\",\n  \"input\": {\n    \"prompt\": \"{{ $json.fluxPrompt }}\",\n    \"aspect_ratio\": \"16:9\",\n    \"output_format\": \"webp\"\n  }\n}",
        "options": {}
      },
      "id": "5",
      "name": "Flux Image Generator",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [950, 250]
    },
    {
      "parameters": {
        "method": "GET",
        "url": "=https://api.replicate.com/v1/predictions/{{ $json.id }}",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendHeaders": true,
        "headersUi": {
          "parameter": [
            {
              "name": "Authorization",
              "value": "Bearer your_replicate_api_token_here"
            }
          ]
        },
        "options": {}
      },
      "id": "6",
      "name": "Poll Flux Status",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [1150, 250]
    },
    {
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{ $json.status }}",
              "operation": "equal",
              "value2": "succeeded"
            }
          ]
        }
      },
      "id": "7",
      "name": "Flux Ready?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [1350, 250]
    },
    {
      "parameters": {
        "amount": 3,
        "unit": "seconds"
      },
      "id": "8",
      "name": "Wait 3s",
      "type": "n8n-nodes-base.wait",
      "typeVersion": 1,
      "position": [1350, 100]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://api.elevenlabs.io/v1/text-to-speech/your_voice_id_here",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendHeaders": true,
        "headersUi": {
          "parameter": [
            {
              "name": "xi-api-key",
              "value": "your_elevenlabs_api_key_here"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"text\": \"{{ $node[\"Split Scenes\"].json.narration }}\",\n  \"model_id\": \"eleven_monolingual_v1\",\n  \"voice_settings\": {\n    \"stability\": 0.5,\n    \"similarity_boost\": 0.75\n  }\n}",
        "options": {}
      },
      "id": "9",
      "name": "ElevenLabs Voiceover",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [950, 450]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.runwayml.com/v1/image_to_video",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendHeaders": true,
        "headersUi": {
          "parameter": [
            {
              "name": "Authorization",
              "value": "Bearer your_runway_api_key_here"
            },
            {
              "name": "X-Runway-Version": "2026-05"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"imageUrl\": \"{{ $node[\"Poll Flux Status\"].json.output[0] }}\",\n  \"prompt\": \"{{ $node[\"Split Scenes\"].json.runwayMotion }}\",\n  \"duration\": 4\n}",
        "options": {}
      },
      "id": "11",
      "name": "Runway Video Gen",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [1550, 250]
    },
    {
      "parameters": {
        "method": "GET",
        "url": "=https://api.runwayml.com/v1/tasks/{{ $json.id }}",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendHeaders": true,
        "headersUi": {
          "parameter": [
            {
              "name": "Authorization",
              "value": "Bearer your_runway_api_key_here"
            }
          ]
        },
        "options": {}
      },
      "id": "12",
      "name": "Poll Runway Status",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [1750, 250]
    },
    {
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{ $json.status }}",
              "operation": "equal",
              "value2": "succeeded"
            }
          ]
        }
      },
      "id": "13",
      "name": "Runway Ready?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [1950, 250]
    },
    {
      "parameters": {
        "amount": 5,
        "unit": "seconds"
      },
      "id": "14",
      "name": "Wait 5s",
      "type": "n8n-nodes-base.wait",
      "typeVersion": 1,
      "position": [1950, 100]
    },
    {
      "parameters": {
        "aggregateBy": "all",
        "options": {}
      },
      "id": "15",
      "name": "Aggregate Storyboard",
      "type": "n8n-nodes-base.aggregate",
      "typeVersion": 1,
      "position": [2150, 350]
    },
    {
      "parameters": {
        "operation": "append",
        "base": "your_airtable_base_id",
        "table": "VideoDashboard",
        "columns": {
          "mappingMode": "defineEverything",
          "value": {
            "Topic": "={{ $node[\"AI Storyboard Director\"].json.choices[0].message.content }}",
            "Scene 1 Video": "={{ $json[0].outputUrl }}",
            "Scene 1 Audio": "={{ $json[0].audioUrl }}",
            "Scene 2 Video": "={{ $json[1].outputUrl }}",
            "Scene 2 Audio": "={{ $json[1].audioUrl }}",
            "Scene 3 Video": "={{ $json[2].outputUrl }}",
            "Scene 3 Audio": "={{ $json[2].audioUrl }}"
          }
        }
      },
      "id": "16",
      "name": "Save to Airtable",
      "type": "n8n-nodes-base.airtable",
      "typeVersion": 1,
      "position": [2350, 350]
    },
    {
      "parameters": {
        "channel": "general",
        "text": "🎬 *Flux + Runway Video Assembly Complete!*\n\n*Topic:* {{ $node[\"Webhook Trigger\"].json.body?.topic || 'B2B Automation Trends' }}\n*Outcome:* High-fidelity media elements (Flux frames, Runway animations, ElevenLabs narration) fully synthesized and cataloged.\n\nAccess your editing workspace dashboard here: https://airtable.com/your_table_link"
      },
      "id": "17",
      "name": "Slack Alert",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2,
      "position": [2550, 300]
    },
    {
      "parameters": {
        "chatId": "your_telegram_chat_id_here",
        "text": "🎬 *Video Factory Assets Ready!*\n\n*Topic:* {{ $node[\"Webhook Trigger\"].json.body?.topic || 'B2B Automation Trends' }}\n\nAll Flux frames, Runway image-to-video scenes, and ElevenLabs voiceovers have been successfully uploaded to your Airtable production workspace.\n\nOpen Workspace: https://airtable.com/your_table_link",
        "additionalFields": {
          "parse_mode": "Markdown"
        }
      },
      "id": "18",
      "name": "Telegram Alert",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.1,
      "position": [2550, 450]
    }
  ],
  "connections": {
    "Webhook Trigger": {
      "main": [
        [
          {
            "node": "AI Storyboard Director",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Storyboard Director": {
      "main": [
        [
          {
            "node": "Parse Storyboard",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Storyboard": {
      "main": [
        [
          {
            "node": "Split Scenes",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Scenes": {
      "main": [
        [
          {
            "node": "Flux Image Generator",
            "type": "main",
            "index": 0
          },
          {
            "node": "ElevenLabs Voiceover",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Flux Image Generator": {
      "main": [
        [
          {
            "node": "Poll Flux Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Poll Flux Status": {
      "main": [
        [
          {
            "node": "Flux Ready?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Flux Ready?": {
      "main": [
        [
          {
            "node": "Runway Video Gen",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Wait 3s",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait 3s": {
      "main": [
        [
          {
            "node": "Poll Flux Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "ElevenLabs Voiceover": {
      "main": [
        [
          {
            "node": "Aggregate Storyboard",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Runway Video Gen": {
      "main": [
        [
          {
            "node": "Poll Runway Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Poll Runway Status": {
      "main": [
        [
          {
            "node": "Runway Ready?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Runway Ready?": {
      "main": [
        [
          {
            "node": "Aggregate Storyboard",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Wait 5s",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait 5s": {
      "main": [
        [
          {
            "node": "Poll Runway Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate Storyboard": {
      "main": [
        [
          {
            "node": "Save to Airtable",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Save to Airtable": {
      "main": [
        [
          {
            "node": "Slack Alert",
            "type": "main",
            "index": 0
          },
          {
            "node": "Telegram Alert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
