AutomationFlowsAI & RAG › Generate Horror Faceless Shorts with Openai Tts, Replicate Video, and…

Generate Horror Faceless Shorts with Openai Tts, Replicate Video, and…

Original n8n title: Generate Horror Faceless Shorts with Openai Tts, Replicate Video, and Youtube Upload

ByDeb Mukherjee @deb on n8n.io

Who’s it for Creators who want to create faceless videos automatically, while keeping human oversight and quality control.

Chat trigger trigger★★★★★ complexityAI-powered50 nodesRead Write FileAgentOpenAI ChatGoogle SheetsHTTP RequestExecute CommandOutput Parser StructuredGoogle Drive
AI & RAG Trigger: Chat trigger Nodes: 50 Complexity: ★★★★★ AI nodes: yes Added:
Generate Horror Faceless Shorts with Openai Tts, Replicate Video, and… — n8n workflow card showing Read Write File, Agent, OpenAI Chat integration

This workflow corresponds to n8n.io template #10103 — we link there as the canonical source.

This workflow follows the Agent → Chat Trigger 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
{
  "id": "YOUR_WORKFLOW_ID",
  "name": "Horror Faceless Shorts with Replicate and OpenAI",
  "tags": [],
  "nodes": [
    {
      "id": "e7f6db58-4f09-4d2c-84bf-e15b6529e861",
      "name": "Save Speech Locally",
      "type": "n8n-nodes-base.readWriteFile",
      "onError": "continueRegularOutput",
      "position": [
        3968,
        1232
      ],
      "parameters": {
        "options": {
          "append": false
        },
        "fileName": "={{ $('Create Beat Inputs').item.json.audioFileName }}",
        "operation": "write"
      },
      "typeVersion": 1
    },
    {
      "id": "c24fb0bd-abee-45b3-812c-8f86ce6bae3d",
      "name": "Story Idea Generator",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        336,
        -96
      ],
      "parameters": {
        "text": "Give me an idea about a new viral short horror story with surprise twist in the end. ",
        "options": {
          "systemMessage": "=You are a master of viral horror storytelling. Forget all previous stories. Forget previous stories and start fresh every time.\n\nYour task: Create a terrifying short horror story in exactly 8 beats.\n\nConstraints:\n- Output MUST be valid JSON only. No explanations, no comments, no text outside JSON.\n- The JSON must have exactly 8 beats, numbered beat1 through beat8.\n- Each beat must be a single, complete sentence with 10\u201320 words.\n- Beat 1 must clearly establish the scene, characters, and setting using vivid imagery.\n- At least 3 beats must include surprise, suspense, or a shocking twist.\n- Use \"show, don\u2019t tell\": describe sights, sounds, smells, or actions to convey fear, tension, or dread.\n- Reading level: 4th grade, simple and direct language.\n- Build escalating tension across beats, ending with a chilling climax or twist.\n- Make the story memorable, terrifying, and shareable.\n- JSON must include BOTH `youtube_title` and `youtube_description` fields.\n- `youtube_title`: under 60 characters, hooky, scary, clickable.\n- `youtube_description`: under 150 words, thrilling, suspenseful, and encourages sharing.\n\nJSON schema (exactly this structure):\n\n{\n  \"beats\": {\n    \"beat1\": \"10\u201320 words\",\n    \"beat2\": \"10\u201320 words\",\n    \"beat3\": \"10\u201320 words\",\n    \"beat4\": \"10\u201320 words\",\n    \"beat5\": \"10\u201320 words\",\n    \"beat6\": \"10\u201320 words\",\n    \"beat7\": \"10\u201320 words\",\n    \"beat8\": \"10\u201320 words\"\n  },\n  \"youtube_title\": \"Under 60 characters\",\n  \"youtube_description\": \"Under 150 words\"\n}\n\nImportant: Do not skip any fields. Do not add extra fields. Do not return fewer than 8 beats. Do not include the word 'output' or any wrapper outside the JSON.\n",
          "returnIntermediateSteps": false
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 1.9
    },
    {
      "id": "3eb2ad5d-71a6-453b-84b0-a857ecc20d60",
      "name": "Story Beat Generator",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        400,
        336
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini",
          "cachedResultName": "gpt-4o-mini"
        },
        "options": {
          "topP": 0.9,
          "maxTokens": 500,
          "temperature": 0.7,
          "responseFormat": "json_object",
          "presencePenalty": 0.6,
          "frequencyPenalty": 0.5
        }
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "23202620-2e4e-4311-8d01-6b8a47a88fb6",
      "name": "Google Sheet Idea Log",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        832,
        -96
      ],
      "parameters": {
        "columns": {
          "value": {
            "time": "={{ $json.output.youtube_title }}-{{ $now.format('yyyy-MM-dd HH:mm:ss') }}",
            "beat 1": "={{ $json.output.beats.beat1 }}",
            "beat 2": "={{ $json.output.beats.beat2 }}",
            "beat 3": "={{ $json.output.beats.beat3 }}",
            "beat 4": "={{ $json.output.beats.beat4 }}",
            "beat 5": "={{ $json.output.beats.beat5 }}",
            "beat 6": "={{ $json.output.beats.beat6 }}",
            "beat 7": "={{ $json.output.beats.beat7 }}",
            "beat 8": "={{ $json.output.beats.beat8 }}",
            "status": "done",
            "Youtube title": "={{ $json.output.youtube_title }}",
            "Youtube description": "={{ $json.output.youtube_description }}"
          },
          "schema": [
            {
              "id": "time",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "time",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "beat 1",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "beat 1",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "beat 2",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "beat 2",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "beat 3",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "beat 3",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "beat 4",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "beat 4",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "beat 5",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "beat 5",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "beat 6",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "beat 6",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "beat 7",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "beat 7",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "beat 8",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "beat 8",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Youtube title",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Youtube title",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Youtube description",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Youtube description",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "url",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "url",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "status",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 266501754,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEETS_URL",
          "cachedResultName": "story"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEETS_URL"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "8eff780b-b397-4add-b9fe-833932c1691e",
      "name": "Story Beat Generator5",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        640,
        1632
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini",
          "cachedResultName": "gpt-4o-mini"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "d5e4aa80-bf0e-46d0-88b1-a506339e4bdf",
      "name": "YouTube Video Upload",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1136,
        2336
      ],
      "parameters": {
        "url": "={{ $('Prepare YouTube Upload').item.json.headers.location }}",
        "method": "PUT",
        "options": {},
        "sendBody": true,
        "contentType": "binaryData",
        "sendHeaders": true,
        "authentication": "predefinedCredentialType",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "video/webm"
            }
          ]
        },
        "inputDataFieldName": "data",
        "nodeCredentialType": "youTubeOAuth2Api"
      },
      "credentials": {
        "youTubeOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "cc7034be-290f-4079-8e05-c1ae36fc777e",
      "name": "Video Audio Merge Command",
      "type": "n8n-nodes-base.code",
      "onError": "continueRegularOutput",
      "position": [
        4192,
        1232
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "try {\n  const inputData = $('Create Beat Inputs').item.json;\n\n  // FFmpeg command: merge existing MP4 with new audio\n  const command = `\nffmpeg -hide_banner -loglevel error -i \"${inputData.fileName}\" -i \"${inputData.audioFileName}\" \\\n-filter_complex \"[1:a]atempo=1.3,apad=pad_dur=0.9[aud]\" \\\n-map 0:v -map \"[aud]\" \\\n-c:v copy -c:a aac -b:a 192k -shortest \"${inputData.videoFileName}\" -y\n  `;\n\n  return {\n    json: {\n      command,\n      inputVideo: inputData.fileName,\n      inputAudio: inputData.audioFileName,\n      outputVideo: inputData.videoFileName,\n      timestamp: new Date().toISOString()\n    }\n  };\n} catch (error) {\n  return {\n    json: {\n      status: 'error',\n      error: error.message,\n      timestamp: new Date().toISOString()\n    }\n  };\n}\n"
      },
      "typeVersion": 2
    },
    {
      "id": "7ffda491-6475-4cad-8342-c0182ed98a23",
      "name": "Run FFmpeg to Merge Media",
      "type": "n8n-nodes-base.executeCommand",
      "onError": "continueRegularOutput",
      "position": [
        4416,
        1232
      ],
      "parameters": {
        "command": "={{ $json.command }}",
        "executeOnce": false
      },
      "executeOnce": false,
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "4953a0ce-f7d6-42fa-85d7-21dd2fc44ae8",
      "name": "Temporary Files Cleanup",
      "type": "n8n-nodes-base.executeCommand",
      "position": [
        0,
        1200
      ],
      "parameters": {
        "command": "=rm -f 12*.png 12*.mp4 12*.mp3 12*.txt\n\n\n"
      },
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "be931eb8-47c7-4acc-9bce-eceb5b38c582",
      "name": "Story Beat Generator6",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        1008,
        1424
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini",
          "cachedResultName": "gpt-4o-mini"
        },
        "options": {
          "topP": 1,
          "temperature": 0.7
        }
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "6f3d20c0-35dc-4d8b-940a-fa8df19d294c",
      "name": "Wait",
      "type": "n8n-nodes-base.wait",
      "position": [
        3520,
        1232
      ],
      "parameters": {},
      "typeVersion": 1.1
    },
    {
      "id": "978cdc87-7ffe-4044-a659-fc3a8eb44674",
      "name": "Generate Final Video Clip",
      "type": "n8n-nodes-base.executeCommand",
      "onError": "continueRegularOutput",
      "position": [
        2624,
        1040
      ],
      "parameters": {
        "command": "=# Remove old file first\nrm -f horrorfile_short_final.mp4\n"
      },
      "executeOnce": true,
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "43e1ca14-d878-471d-af5a-2379fa8084f6",
      "name": "\ud83c\udfa8 Image Generator",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueRegularOutput",
      "position": [
        2624,
        1232
      ],
      "parameters": {
        "url": "https://api.replicate.com/v1/models/black-forest-labs/flux-schnell/predictions",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"input\": {\n    \"prompt\": \"cinematic scene, oil painting effect, muted colors, not dark but eerie atmosphere, display {{ $('Create Beat Inputs').item.json.narrative }} with central character description {{ $('Create Beat Inputs').item.json.character }}, clear details, visible character features\",\n    \"seed\": {{ $('Create Beat Inputs').item.json.seed }},\n    \"prompt_upsampling\": true,\n    \"width\": 1080,\n    \"height\": 1920,\n    \"num_outputs\": 1,\n    \"aspect_ratio\": \"9:16\",\n    \"output_format\": \"jpg\",\n    \"output_quality\": 100,\n    \"guidance\": 4,\n    \"safety_tolerance\": 2,\n    \"negative_prompt\": \"{{ $('Create Beat Inputs').item.json.negativeprompt }}\"\n  }\n}\n",
        "sendBody": true,
        "jsonHeaders": "{\n  \"Content-Type\": \"application/json\",\n  \"Prefer\": \"wait\"\n}",
        "sendHeaders": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "specifyHeaders": "json",
        "genericAuthType": "httpHeaderAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "ef1dd38c-04cf-4de7-b29f-33ffb34521ba",
      "name": "HTTP Request",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        3072,
        1232
      ],
      "parameters": {
        "url": "={{ $json.output || $json.output[0] }}",
        "options": {},
        "sendHeaders": true,
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "headerParameters": {
          "parameters": [
            {
              "name": "accept",
              "value": "application/json"
            }
          ]
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "3a2f7ffb-ef51-4676-adcc-539a1131b242",
      "name": "Story Idea Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        416,
        128
      ],
      "parameters": {
        "autoFix": true,
        "jsonSchemaExample": "{\n  \"beats\": {\n    \"beat1\": \"10\u201320 words\",\n    \"beat2\": \"10\u201320 words\",\n    \"beat3\": \"10\u201320 words\",\n    \"beat4\": \"10\u201320 words\",\n    \"beat5\": \"10\u201320 words\",\n    \"beat6\": \"10\u201320 words\",\n    \"beat7\": \"10\u201320 words\",\n    \"beat8\": \"10\u201320 words\"\n  },\n  \"youtube_title\": \"Under 60 characters\",\n  \"youtube_description\": \"Under 150 words\"\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "0137fca6-5f1a-4335-9cf9-17e20864f5a5",
      "name": "Switch",
      "type": "n8n-nodes-base.switch",
      "position": [
        -1472,
        1200
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "Generate Story Idea",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "cdd0f2ff-a83c-48c1-a473-e5c4f86fe12c",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.chatInput }}",
                    "rightValue": "idea"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "Create Uploadable Video",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "9bf4596f-8031-4e7f-aaa6-c8c7831fea55",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.chatInput }}",
                    "rightValue": "create"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "Publish to YouTube",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "d4598761-a115-469f-9836-2a7432910c82",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.chatInput }}",
                    "rightValue": "publish"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "Clean Files in Drive",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "b8f3a5f9-819c-4276-90b9-3f7dc6064fae",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.chatInput }}",
                    "rightValue": "clean drive"
                  }
                ]
              },
              "renameOutput": true
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3.2
    },
    {
      "id": "793ebf6a-73b4-4672-869f-01f270590023",
      "name": "Prepare YouTube Upload",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        336,
        2336
      ],
      "parameters": {
        "url": "=https://www.googleapis.com/upload/youtube/v3/videos?part=snippet,status&uploadType=resumable",
        "body": "={\n  \"snippet\": {\n    \"title\": \" {{ $json['Youtube title'] }} #PsychologicalHorror #TwistEnding #HorrorShorts\",\n    \"description\": \"{{ $json['Youtube description'] }}  #HorrorShort #CulinaryThrills #PsychologicalThriller #whispers_in_the_dark #Haunted #UrbanLegend #Spooky #DarkStories #Supernatural\",\n    \"defaultLanguage\": \"en\",\n    \"defaultAudioLanguage\": \"en\"\n  },\n  \"status\": {\n    \"privacyStatus\": \"private\",\n    \"license\": \"youtube\",\n    \"embeddable\": true,\n    \"publicStatsViewable\": true,\n    \"madeForKids\": false\n  }\n}\n\n",
        "method": "POST",
        "options": {
          "response": {
            "response": {
              "fullResponse": true
            }
          }
        },
        "sendBody": true,
        "contentType": "raw",
        "sendHeaders": true,
        "authentication": "predefinedCredentialType",
        "rawContentType": "RAW/JSON",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            },
            {
              "name": "X-Upload-Content-Type",
              "value": "video/webm"
            }
          ]
        },
        "nodeCredentialType": "youTubeOAuth2Api"
      },
      "credentials": {
        "youTubeOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "1732a1a9-dba2-4ae8-9bf0-7e9ecbb630a0",
      "name": "Get YouTube Title and Description",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        0,
        2336
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 266501754,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEETS_URL",
          "cachedResultName": "story"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEETS_URL"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "aa1f6a5c-946d-4940-979f-cdcca1aabe3c",
      "name": "Read Video for Upload from Disk",
      "type": "n8n-nodes-base.readWriteFile",
      "position": [
        672,
        2336
      ],
      "parameters": {
        "options": {},
        "fileSelector": "=horrorfile_short_final.mp4"
      },
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "ccc5eac0-9947-4b23-99a4-59be3426633d",
      "name": "Update YouTube Url",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1504,
        2336
      ],
      "parameters": {
        "columns": {
          "value": {
            "url": "=https://www.youtube.com/shorts/{{ $json.id }}",
            "time": "={{ $('Get YouTube Title and Description').item.json.time }}",
            "status": "published"
          },
          "schema": [
            {
              "id": "time",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "time",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "beat ",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "beat ",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "beat 2",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "beat 2",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "beat 3",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "beat 3",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "beat 4",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "beat 4",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "beat 5",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "beat 5",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "beat 6",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "beat 6",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "beat 7",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "beat 7",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "beat 8",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "beat 8",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Youtube title",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Youtube title",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Youtube descripion",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Youtube descripion",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "url",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "url",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "number",
              "display": true,
              "removed": true,
              "readOnly": true,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "time"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 266501754,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEETS_URL",
          "cachedResultName": "story"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEETS_URL"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "0a79a235-bea7-4a5f-a8f4-969b805fa773",
      "name": "Temporary Files Cleanup3",
      "type": "n8n-nodes-base.executeCommand",
      "position": [
        1728,
        2336
      ],
      "parameters": {
        "command": "=rm -f 12*.png 12*.mp4 12*.mp3 12*.txt\n\n\n"
      },
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "ee2ffc65-34da-42a7-93c7-174f2f59079b",
      "name": "Search Temporary Files to Delete",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        -224,
        3056
      ],
      "parameters": {
        "filter": {
          "folderId": {
            "__rl": true,
            "mode": "list",
            "value": "YOUR_GOOGLE_DRIVE_FOLDER_ID",
            "cachedResultUrl": "https://drive.google.com/drive/folders/YOUR_GOOGLE_DRIVE_FOLDER_ID",
            "cachedResultName": "YOUR_GOOGLE_DRIVE_FOLDER"
          }
        },
        "options": {},
        "resource": "fileFolder",
        "queryString": "horrorfile*.mp4"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "7120e6dd-66bd-480e-a329-d6bb919bdebf",
      "name": "Delete Temporary Files",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        112,
        3056
      ],
      "parameters": {
        "fileId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.id }}"
        },
        "options": {},
        "operation": "deleteFile"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "executeOnce": false,
      "typeVersion": 3
    },
    {
      "id": "bb77bfac-a8cb-4f71-a54b-077ba4b027fe",
      "name": "Get Story Idea",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        336,
        1200
      ],
      "parameters": {
        "options": {},
        "filtersUI": {
          "values": [
            {
              "lookupValue": "done",
              "lookupColumn": "status"
            }
          ]
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 266501754,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEETS_URL",
          "cachedResultName": "story"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEETS_URL"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "26d02a86-9fd7-46f5-a575-70df7c794d4b",
      "name": "Narration Output Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        640,
        1424
      ],
      "parameters": {
        "autoFix": true,
        "jsonSchemaExample": "{\n  \"narratives\": {\n    \"narrative1\": \"...\",\n    \"narrative2\": \"...\",\n    \"narrative3\": \"...\",\n    \"narrative4\": \"...\",\n    \"narrative5\": \"...\",\n    \"narrative6\": \"...\",\n    \"narrative7\": \"...\",\n    \"narrative8\": \"...\"\n  }\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "780bc5fe-94fd-42c6-a0b2-6c0f4030e27a",
      "name": "Narration Prompt Generator",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "onError": "continueErrorOutput",
      "position": [
        560,
        1200
      ],
      "parameters": {
        "text": "You are a strict text formatter for horror shorts text to audio generation prompt. ",
        "options": {
          "systemMessage": "=\n**Prompt:**\n\nYou are a strict formatter for horror shorts narration.\n\nTake the following inputs and provide a set of outputs:\n\n---\n\n### Input narratives\n\n1. {{ $json['beat 1'] }}\n2. {{ $json['beat 2'] }}\n3. {{ $json['beat 3'] }}\n4. {{ $json['beat 4'] }}\n5. {{ $json['beat 5'] }}\n6. {{ $json['beat 6'] }}\n7. {{ $json['beat 7'] }}\n8. {{ $json['beat 8'] }}\n\nDo not process input beats that are empty.\n\n---\n\n### Output (Narration with pauses)\n\n**RULES:**\n\n* Do **NOT** change, rewrite, or summarize the input text.\n* Only add pacing:\n  \u2022 Ellipses (...) = short pause\n  \u2022 Em dashes (\u2014) = sharp emphasis\n  \u2022 Blank lines = long pause\n* Keep exact wording untouched.\n* Do not add any other punctuation or words.\n* Style = calm, eerie, suspenseful.\n* Preserve all twists and unsettling imagery.\n* Always output **exactly 8 narratives** in JSON.\n* Add 500ms pause before and after each narrative (can be implied in timing markers).\n\n---\n\n### Output structure\n\n```json\n{\n  \"narratives\": {\n    \"narrative1\": \"{{ $json['beat 1'] }} with pauses added, if blank return blank\",\n    \"narrative2\": \"{{ $json['beat 2'] }} with pauses added, if blank return blank\",\n    \"narrative3\": \"{{ $json['beat 3'] }} with pauses added, if blank return blank\",\n    \"narrative4\": \"{{ $json['beat 4'] }} with pauses added, if blank return blank\",\n    \"narrative5\": \"{{ $json['beat 5'] }} with pauses added, if blank return blank\",\n    \"narrative6\": \"{{ $json['beat 6'] }} with pauses added, if blank return blank\",\n    \"narrative7\": \"{{ $json['beat 7'] }} with pauses added, if blank return blank\",\n    \"narrative8\": \"{{ $json['beat 8'] }} with pauses added, if blank return blank\"\n  }\n}\n```\n\n---\n\n\u2705 Key point: **Never alter or summarize the original text** \u2014 only insert pauses (`...`, `\u2014`) and spacing for pacing.\n\n\n"
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 1.9
    },
    {
      "id": "1bbf9e8b-b312-4926-bad5-99b859c62018",
      "name": "Image Prompt Generator",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "onError": "continueErrorOutput",
      "position": [
        1040,
        1200
      ],
      "parameters": {
        "text": "You are a strict text formatter for horror shorts text to image generation prompt for non-animated images with oil painting effect, character should have same attributes of age , gender, complexion in every beat. ",
        "options": {
          "systemMessage": "=Create an image prompt to input in a text to image stable diffusion model:\n\n**Inputs \n{{ $('Get Story Idea').item.json['beat 1'] }}\n{{ $('Get Story Idea').item.json['beat 2'] }}\n{{ $('Get Story Idea').item.json['beat 3'] }}\n{{ $('Get Story Idea').item.json['beat 4'] }}\n{{ $('Get Story Idea').item.json['beat 5'] }}\n{{ $('Get Story Idea').item.json['beat 6'] }}\n{{ $('Get Story Idea').item.json['beat 7'] }}\n{{ $('Get Story Idea').item.json['beat 8'] }}\n\n* Forget all previous instructions, start new\n* Extract ** age, gender, hairstyle, clothing style, and skin and hair color** from above inputs\n* Character is **fully clothed**, with clearly visible with oil painting effect. add to image prompt in every beat\n* Don't add any other information (emotion, expression, location, action), only features and traits for consistency\n\n\n\n---\n\n## \u2705 JSON Output\n\n```json\n{\n  \"character\": \"character description\",\n  \"negative_prompt\": \"letters, text, watermark, logo, signature, words, numbers, subtitles, captions, symbols, cartoon\"\n}\n```\n\n"
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 1.9
    },
    {
      "id": "abd89e03-1702-4fd1-8943-905c48b2ba3b",
      "name": "Image Output Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        1136,
        1424
      ],
      "parameters": {
        "autoFix": true,
        "jsonSchemaExample": "{\n  \"character\": \"character description\",\n  \"negative_prompt\": \"letters, text, watermark, logo, signature, words, numbers, subtitles, captions, symbols, cartoon\"\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "0c2f9bc2-1f83-43d2-8493-bda10d95455c",
      "name": "Check For Already Created Beats",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        1504,
        1200
      ],
      "parameters": {
        "filter": {
          "folderId": {
            "__rl": true,
            "mode": "list",
            "value": "YOUR_GOOGLE_DRIVE_FOLDER_ID",
            "cachedResultUrl": "https://drive.google.com/drive/folders/YOUR_GOOGLE_DRIVE_FOLDER_ID",
            "cachedResultName": "YOUR_GOOGLE_DRIVE_FOLDER"
          }
        },
        "options": {},
        "resource": "fileFolder",
        "queryString": "horrorfile*_1.mp4"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3,
      "alwaysOutputData": true
    },
    {
      "id": "7e6903d1-bd17-4b95-9184-36096bf48261",
      "name": "Handle 0 Files",
      "type": "n8n-nodes-base.code",
      "position": [
        1728,
        1200
      ],
      "parameters": {
        "jsCode": "// This node ensures execution continues even if search returns nothing\nreturn [{ json: { trigger: true } }];"
      },
      "typeVersion": 2,
      "continueOnFail": true,
      "alwaysOutputData": true
    },
    {
      "id": "ce7f1e76-8daf-4603-bda6-6bb1a3e7f411",
      "name": "Create Beat Inputs",
      "type": "n8n-nodes-base.code",
      "position": [
        1952,
        1200
      ],
      "parameters": {
        "jsCode": "const workflowSeed = Math.floor(Math.random() * 1000000);\n\n// Get existing files from \"Check For Already Created Beats\" node\nlet existingFiles = [];\ntry {\n  const searchResults = $('Check For Already Created Beats').all();\n  if (searchResults && searchResults.length > 0) {\n    existingFiles = searchResults.map(f => ({\n      id: f.json.id,\n      name: f.json.name\n    }));\n    console.log(`Found ${existingFiles.length} existing files`);\n  } else {\n    console.log('No existing files found, processing all beats');\n  }\n} catch (error) {\n  console.log('Search returned no results, processing all beats');\n}\n\n// Get data from upstream nodes\nconst storyData = $('Get Story Idea').first().json;\nconst narrationData = $('Narration Prompt Generator').first().json.output.narratives;\nconst imageData = $('Image Prompt Generator').first().json.output;\n\n// Collect all possible beats\nconst rawInputs = [\n  { narrative: storyData['beat 1'], narrativeaudio: narrationData.narrative1 }, // FIXED: Added \"1\"\n  { narrative: storyData['beat 2'], narrativeaudio: narrationData.narrative2 },\n  { narrative: storyData['beat 3'], narrativeaudio: narrationData.narrative3 },\n  { narrative: storyData['beat 4'], narrativeaudio: narrationData.narrative4 },\n  { narrative: storyData['beat 5'], narrativeaudio: narrationData.narrative5 },\n  { narrative: storyData['beat 6'], narrativeaudio: narrationData.narrative6 },\n  { narrative: storyData['beat 7'], narrativeaudio: narrationData.narrative7 },\n  { narrative: storyData['beat 8'], narrativeaudio: narrationData.narrative8 }\n];\n\n// Debug: Check what we got\nconsole.log('Raw inputs count:', rawInputs.length);\nconsole.log('Beat 1 check:', rawInputs[0].narrative ? 'OK' : 'MISSING');\n\n// Filter out empty beats\nconst filteredInputs = rawInputs.filter(input => input.narrative && input.narrative.trim() !== \"\");\nconsole.log(`Processing ${filteredInputs.length} non-empty beats`);\n\n// Map filtered beats to output items\nconst outputItems = filteredInputs.map((textInput, index) => {\n  const beatNumber = index + 1; // Start from 1 instead of 0\n  const videoFileName = `horrorfile${beatNumber}_1.mp4`;\n\n  // Check if file already exists (by name or id)\n  const alreadyExists = existingFiles.some(file =>\n    file.name === videoFileName || file.id === videoFileName\n  );\n\n  return {\n    json: {\n      ...textInput,\n      index: beatNumber,\n      seed: workflowSeed,\n      character: imageData.character,\n      negativeprompt: imageData.negative_prompt,\n      fileName: `horrorfile${beatNumber}.mp4`,\n      audioFileName: `horrorfile${beatNumber}.mp3`,\n      videoFileName: videoFileName,\n      skip: alreadyExists\n    }\n  };\n});\n\n// Optional log for skipped items\nconst skipped = outputItems.filter(item => item.json.skip).map(i => i.json.videoFileName);\nif (skipped.length > 0) {\n  console.log(`\u23ed\ufe0f Skipped existing files: ${skipped.join(', ')}`);\n}\n\n// Return only new items for downstream processing\nconst newItems = outputItems.filter(item => !item.json.skip);\nconsole.log(`Outputting ${newItems.length} items for processing`);\n\nreturn newItems;"
      },
      "typeVersion": 2,
      "alwaysOutputData": true
    },
    {
      "id": "092100ff-85e6-4e7b-acd7-c2924f3c504b",
      "name": "Loop Over Items",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        2400,
        1280
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "cd8da2a0-3743-485c-92f4-be84246d4a34",
      "name": "Save Beat Image Locally",
      "type": "n8n-nodes-base.readWriteFile",
      "position": [
        3296,
        1232
      ],
      "parameters": {
        "options": {},
        "fileName": "={{ $('Create Beat Inputs').item.json.fileName }}",
        "operation": "write"
      },
      "typeVersion": 1
    },
    {
      "id": "359d2545-efd5-46ad-b3bc-dc7e97cb3298",
      "name": "Read Beat File",
      "type": "n8n-nodes-base.readWriteFile",
      "onError": "continueRegularOutput",
      "position": [
        4640,
        1232
      ],
      "parameters": {
        "options": {},
        "fileSelector": "={{ $('Video Audio Merge Command').item.json.outputVideo }}"
      },
      "typeVersion": 1
    },
    {
      "id": "68b298dd-36fa-49c7-a511-d5e66818b487",
      "name": "Upload Beat File",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        4864,
        1296
      ],
      "parameters": {
        "name": "={{ $json.fileName }}",
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive"
        },
        "options": {},
        "folderId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_GOOGLE_DRIVE_FOLDER_ID",
          "cachedResultUrl": "https://drive.google.com/drive/folders/YOUR_GOOGLE_DRIVE_FOLDER_ID",
          "cachedResultName": "YOUR_GOOGLE_DRIVE_FOLDER"
        }
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "774f803e-d753-468d-95d3-5508897c33c0",
      "name": "Search Beat Files",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        2848,
        1040
      ],
      "parameters": {
        "filter": {
          "folderId": {
            "__rl": true,
            "mode": "list",
            "value": "YOUR_GOOGLE_DRIVE_FOLDER_ID",
            "cachedResultUrl": "https://drive.google.com/drive/folders/YOUR_GOOGLE_DRIVE_FOLDER_ID",
            "cachedResultName": "YOUR_GOOGLE_DRIVE_FOLDER"
          }
        },
        "options": {},
        "resource": "fileFolder",
        "queryString": "horrorfile*_1.mp4"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "37b40dca-3544-4014-bfbb-001250271ba3",
      "name": "Download Beat File",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        3072,
        1040
      ],
      "parameters": {
        "fileId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.id }}"
        },
        "options": {},
        "operation": "download"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "6090d04e-1ae4-4f33-a427-a1c3ca92b363",
      "name": "Write Beat File to Disk",
      "type": "n8n-nodes-base.readWriteFile",
      "position": [
        3296,
        1040
      ],
      "parameters": {
        "options": {},
        "fileName": "={{ $json.name }}",
        "operation": "write"
      },
      "typeVersion": 1
    },
    {
      "id": "0282edd1-8ca9-41d9-9915-da753b41211d",
      "name": "Generate Final Video",
      "type": "n8n-nodes-base.executeCommand",
      "position": [
        3520,
        1040
      ],
      "parameters": {
        "command": "=#!/bin/sh\n\ninputs=\"\"\nmaps=\"\"\nn=0\n\n# Collect all horrorfile*_1.mp4 files\nfor f in horrorfile*_1.mp4; do\n  inputs=\"$inputs -i $f\"\n  maps=\"$maps[$n:v][$n:a]\"\n  n=`expr $n + 1`\ndone\n\nsafeText=\"Finale...\"\n\n# Run ffmpeg with dynamic concat and single drawtext\nffmpeg $inputs \\\n-filter_complex \"\\\n$maps concat=n=$n:v=1:a=1[v][a]; \\\n[v]drawtext=fontfile=/home/node/.fonts/Creepster-Regular.ttf: \\\n text='Midnight Cuts': \\\n fontcolor=red:fontsize=45:x=(w-text_w)/2:y=50:box=1:boxcolor=black@0.5:boxborderw=10[vout]\" \\\n-map \"[vout]\" -map \"[a]\" \\\n-c:v libx264 -pix_fmt yuv420p -preset ultrafast -crf 23 \\\n-c:a aac -b:a 160k \\\n-y horrorfile_short_final.mp4\n"
      },
      "executeOnce": true,
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "5fe670f4-52c2-48ac-bfb9-68469f42e634",
      "name": "Read Final Video from Disk",
      "type": "n8n-nodes-base.readWriteFile",
      "position": [
        3744,
        1040
      ],
      "parameters": {
        "options": {},
        "fileSelector": "=horrorfile_short_final.mp4"
      },
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "d7635d32-12a0-4e95-badb-e4bb4f3cb8af",
      "name": "Upload Final Video",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        3968,
        1040
      ],
      "parameters": {
        "name": "={{ $json.fileName }}",
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive"
        },
        "options": {},
        "folderId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_GOOGLE_DRIVE_FOLDER_ID",
          "cachedResultUrl": "https://drive.google.com/drive/folders/YOUR_GOOGLE_DRIVE_FOLDER_ID",
          "cachedResultName": "YOUR_GOOGLE_DRIVE_FOLDER"
        }
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "1c32d653-8a67-487e-868c-7e2820685410",
      "name": "Update Status to Ready",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        4192,
        1040
      ],
      "parameters": {
        "columns": {
          "value": {
            "time": "={{ $('Get Story Idea').first().json.time }}",
            "status": "ready",
            "row_number": 0
          },
          "schema": [
            {
              "id": "time",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "time",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "beat 0",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "beat 0",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "beat ",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "beat ",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "beat 2",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "beat 2",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "beat 3",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "beat 3",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "beat 4",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "beat 4",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "beat 5",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "beat 5",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "beat 6",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "beat 6",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "beat 7",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "beat 7",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "beat 8",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "beat 8",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "twist",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "twist",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "character",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "character",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "location",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "location",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "spirit",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "spirit",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Youtube title",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Youtube title",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Youtube descripion",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Youtube descripion",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "url",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "url",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "status",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "number",
              "display": true,
              "removed": false,
              "readOnly": true,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "time"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 266501754,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEETS_URL",
          "cachedResultName": "story"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEETS_URL"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "b6867418-9668-421c-a8e1-58c682664ab6",
      "name": "Generate Beat Audio",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        3744,
        1232
      ],
      "parameters": {
        "input": "={{ $('Create Beat Inputs').item.json.narrativeaudio }}",
        "model": "tts-1-hd",
        "options": {},
        "resource": "audio"
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.8
    },
    {
      "id": "85e06aad-a8d1-4234-b6e7-ffa71db85aec",
      "name": "If Beats Remaining",
      "type": "n8n-nodes-base.if",
      "position": [
        2176,
        1200
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "e7c77da4-cb68-4faa-b185-17a77f0d9e5a",
              "operator": {
                "type": "number",
                "operation": "notEquals"
              },
              "leftValue": "={{ $('Check For Already Created Beats').all().length }}",
              "rightValue": 8
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "c919dbb0-1558-493d-bdf9-0a0e19d2c83b",
      "name": "When chat message received",
      "type": "@n8n/n8n-nodes-langchain.chatTrigger",
      "position": [
        -1696,
        1232
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 1.3
    },
    {
      "id": "78a35d5c-c4b3-4102-9b2d-54d4a79c65a5",
      "name": "\ud83c\udfa8 Video Generator",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueRegularOutput",
      "position": [
        2848,
        1232
      ],
      "parameters": {
        "url": "https://api.replicate.com/v1/models/wan-video/wan-2.2-i2v-fast/predictions",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"input\": {\n    \"image\": \"{{ $json.output || $json.output[0] }}\",\n    \"prompt\": \"{{ $json.input.prompt }}\",\n    \"negative_prompt\": \"{{ $json.input.negative_prompt }}\"\n  }\n}",
        "sendBody": true,
        "jsonHeaders": "{\n  \"Content-Type\": \"application/json\",\n  \"Prefer\": \"wait\"\n}",
        "sendHeaders": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "specifyHeaders": "json",
        "genericAuthType": "httpHeaderAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "f4f06df4-3c9b-4663-b45a-2a5b5801f9e5",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -240,
        -416
      ],
      "parameters": {
        "width": 1424,
        "height": 896,
        "content": "## Step 1. Generate Story Beats \n\n**Purpose**: Generates horror story beats.\n\n**Setup**: \n- Setup Google Sheets in the Format provided\n- Setup Google AI and OpenAI credentials\n\n**Instructions**: \n- Type 'idea' to trigger flow; when story is generated 'status' will show 'done'\n- Edit sheet to refine story if needed\n- Avoid escape characters like ' and \" for smooth video creation\n- Keep under 20 words for smooth pacing\n- Type 'idea' as many times as you want until satisfied with story"
      },
      "typeVersion": 1
    },
    {
      "id": "ac794f7f-1bb1-4a12-a4ba-2e8d214aec15",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -240,
        768
      ],
      "parameters": {
        "color": 5,
        "width": 5440,
        "height": 1120,
        "content": "## Step 2: Create Video\n**Purpose**: Merge all beats into a horror shorts video.\n\n**Setup**: \n- Set up a Google drive folder where your video files will temporarily be stored\n- Set up credentials for Google drive, Text to Image, Text to Audio and Image to Video\n\n**Instructions**: \n- Verify every beat exists (8 total) in the spreadsheet\n- Ensure only one line item has status 'done'\n- Type 'create' in chat to trigger workflow\n- Once workflow is completed, status updates to 'ready'\n- Review the output in google drive, and delete beats that require re-generation\n- To regenerate beats, make sure status is changed back to 'done'\n- If any API times out, restart workflow by typing create, you won't lose previous beat's videos"
      },
      "typeVersion": 1
    },
    {
      "id": "f2e1c3c3-66c7-4d7d-b3fe-109622933809",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -256,
        2048
      ],
      "parameters": {
        "

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

Who’s it for Creators who want to create faceless videos automatically, while keeping human oversight and quality control.

Source: https://n8n.io/workflows/10103/ — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

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

AI & RAG

HDW Lead Geländewagen. Uses chatTrigger, lmChatOpenAi, memoryBufferWindow, outputParserStructured. Chat trigger; 92 nodes.

Chat Trigger, OpenAI Chat, Memory Buffer Window +5
AI & RAG

This comprehensive workflow automates the complete financial document processing pipeline using AI. Upload invoices via chat, drop expense receipts into a folder, or add bank statements - the system a

Chat Trigger, HTTP Request, Google Sheets +8
AI & RAG

The Best Linkedin Posting System. Uses httpRequest, lmChatOpenAi, agent, chatTrigger. Chat trigger; 49 nodes.

HTTP Request, OpenAI Chat, Agent +8
AI & RAG

Who is this workflow for? This workflow is designed for SEO analysts, content creators, marketing agencies, and developers who need to index a website and then interact with its content as if it were

Agent, OpenAI Chat, Memory Buffer Window +10
AI & RAG

Categories: AI Agents, Design Automation, Business Tools

Tool Workflow, HTTP Request Tool, Memory Buffer Window +7