{
  "id": "EeljfIPekdQsI7c1",
  "meta": {
    "builderVariant": "mcp",
    "aiBuilderAssisted": true
  },
  "name": "Generate CCTV-style animal videos with Seedance and post to TikTok",
  "tags": [],
  "nodes": [
    {
      "id": "715e25f4-a090-4f28-86f8-53a4ce49c04e",
      "name": "Run every 4 hours",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        32,
        -528
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "hours",
              "hoursInterval": 4
            }
          ]
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "041d7283-7405-4a03-90ee-3a369dea9355",
      "name": "Configuration",
      "type": "n8n-nodes-base.set",
      "position": [
        192,
        -528
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "a1",
              "name": "atlas_model",
              "type": "string",
              "value": "bytedance/seedance-2.0/text-to-video"
            },
            {
              "id": "a2",
              "name": "video_duration",
              "type": "number",
              "value": 8
            },
            {
              "id": "a3",
              "name": "aspect_ratio",
              "type": "string",
              "value": "9:16"
            },
            {
              "id": "a4",
              "name": "generate_audio",
              "type": "boolean",
              "value": true
            },
            {
              "id": "a5",
              "name": "poll_wait_seconds",
              "type": "number",
              "value": 20
            },
            {
              "id": "a6",
              "name": "prompt_model",
              "type": "string",
              "value": "gpt-5-mini"
            },
            {
              "id": "a7",
              "name": "caption_model",
              "type": "string",
              "value": "gpt-5-mini"
            },
            {
              "id": "a8",
              "name": "tiktok_privacy_level",
              "type": "string",
              "value": "PUBLIC_TO_EVERYONE"
            },
            {
              "id": "a9",
              "name": "telegram_chat_id",
              "type": "string",
              "value": ""
            },
            {
              "id": "a10",
              "name": "animal_override",
              "type": "string",
              "value": ""
            },
            {
              "id": "a11",
              "name": "location_override",
              "type": "string",
              "value": ""
            },
            {
              "id": "a12",
              "name": "action_override",
              "type": "string",
              "value": ""
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "29c06002-b8f9-4a03-944a-19c58806db7f",
      "name": "Generate CCTV prompt",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        400,
        -528
      ],
      "parameters": {
        "text": "=TASK: Create a hyper-realistic CCTV / security-camera style prompt for a short, funny viral animal video.\n\nANIMAL: {{ ($('Configuration').item.json.animal_override && $('Configuration').item.json.animal_override.trim()) || (() => { const a = ['cat','dog','rabbit','hamster','raccoon','squirrel','fox','duck','goose','goat','alpaca','piglet','hedgehog','ferret','opossum','deer','rooster','peacock','crow','seagull','chinchilla','skunk','turkey','gerbil']; return a[Math.floor(Math.random()*a.length)]; })() }}\n\nLOCATION: {{ ($('Configuration').item.json.location_override && $('Configuration').item.json.location_override.trim()) || (() => { const l = ['backyard','front porch','driveway','garden','side yard','alley near trash bins','garage entrance','balcony','apartment hallway','stairwell','kitchen window','patio furniture area','barbecue grill area','mailbox area','front gate','street sidewalk','swimming pool deck','trampoline','chicken coop','rooftop terrace','garden pond edge','carport','tool shed','courtyard']; return l[Math.floor(Math.random()*l.length)]; })() }}\n\nACTION: {{ ($('Configuration').item.json.action_override && $('Configuration').item.json.action_override.trim()) || (() => { const c = ['accidentally ringing the doorbell and freaking out','sneezing loudly and startling itself','tiptoeing off with a stolen slice of pizza','wobbling along the fence like a tightrope walker','battling a garden hose that seems alive','dragging a shoe across the lawn like a trophy','attempting a parkour jump and adorably missing','peeking into the camera, nose smudging the lens','carefully carrying a slice of bread like a briefcase','doing a dramatic slow-motion slip on wet tiles','stealing the doormat and sprinting off','riding a robot vacuum like a tiny cowboy','doing zoomies around the sprinkler','posing like a statue every time the light comes on','sneaking under a parked car like a ninja','ringing a wind chime and looking confused','staring down a lawn flamingo in a duel','pulling a pizza box that is way too big','peeking from the mailbox like a spy','parading with a garden glove as a prize','playing peekaboo behind a flowerpot','rolling on the grass like a fuzzy tumbleweed','poking the camera with a curious paw','misjudging a leap and landing in a bush']; return c[Math.floor(Math.random()*c.length)]; })() }}\n\nTIMESTAMP TO OVERLAY (exact): {{ $now.toFormat('yyyy-LL-dd HH:mm:ss') }}\n\nPROMPT REQUIREMENTS:\n- CCTV / security-camera aesthetic: grainy, black and white, night-vision style\n- Timestamp overlay in a corner using the exact timestamp above\n- Slightly blurry / low-res surveillance quality, motion blur, infrared lighting\n- The animal is the clear main focus, doing the funny ACTION\n- Outdoor residential setting (unless the LOCATION is clearly indoor)\n- Fence, grass, house elements in the background, wide-angle surveillance perspective\n- Authentic \"caught on camera\" feel\n\nSTYLE KEYWORDS TO INCLUDE: \"security camera footage, CCTV style\", \"black and white, grainy, low resolution\", \"timestamp overlay, night vision\", \"wide angle lens, surveillance perspective\", \"motion blur, infrared lighting\".\n\nReturn TWO prompts: image_prompt (a still CCTV frame) and video_prompt (animating the scene with natural, believable animal movement). Keep each prompt vivid but under 120 words.",
        "batching": {},
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 1.9
    },
    {
      "id": "25895762-d993-44a4-8178-188db35491d7",
      "name": "OpenAI model (scene prompt)",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        400,
        -336
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "={{ $('Configuration').item.json.prompt_model }}",
          "cachedResultName": "gpt-5-mini"
        },
        "options": {},
        "builtInTools": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "b1a5b894-041a-4e4f-98e1-e17cd39e1e8b",
      "name": "Scene prompt parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        544,
        -336
      ],
      "parameters": {
        "jsonSchemaExample": "{ \"image_prompt\": \"CCTV still-frame image prompt\", \"video_prompt\": \"video animation prompt with natural animal movement\" }"
      },
      "typeVersion": 1.3
    },
    {
      "id": "4719848e-a0fc-4c27-8c8e-43c2b419cc46",
      "name": "Start Seedance video",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        832,
        -528
      ],
      "parameters": {
        "url": "https://api.atlascloud.ai/api/v1/model/generateVideo",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"model\": {{ JSON.stringify($('Configuration').item.json.atlas_model) }},\n  \"prompt\": {{ JSON.stringify($('Generate CCTV prompt').item.json.output.video_prompt) }},\n  \"duration\": {{ $('Configuration').item.json.video_duration }},\n  \"aspect_ratio\": {{ JSON.stringify($('Configuration').item.json.aspect_ratio) }},\n  \"generate_audio\": {{ $('Configuration').item.json.generate_audio }}\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "a2c783eb-949f-4d47-aac8-2fbe6c440f25",
      "name": "Wait for rendering",
      "type": "n8n-nodes-base.wait",
      "position": [
        1008,
        -528
      ],
      "parameters": {
        "amount": "={{ $('Configuration').item.json.poll_wait_seconds }}"
      },
      "typeVersion": 1.1
    },
    {
      "id": "643197cb-a302-40e5-b823-0dc7eb9e5c80",
      "name": "Check render status",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1200,
        -528
      ],
      "parameters": {
        "url": "=https://api.atlascloud.ai/api/v1/model/prediction/{{ $('Start Seedance video').item.json.data.id }}",
        "options": {},
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "01c4456b-36f9-4d92-a4b4-6bf5924cc841",
      "name": "Is video ready?",
      "type": "n8n-nodes-base.if",
      "position": [
        1360,
        -528
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": false,
            "typeValidation": "loose"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "c1",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.data.status }}",
              "rightValue": "completed"
            },
            {
              "id": "c2",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.data.status }}",
              "rightValue": "succeeded"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "bd5712a5-3201-48bb-960a-32641b788dd0",
      "name": "Generate title and hashtags",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        1600,
        -528
      ],
      "parameters": {
        "text": "={{ $('Generate CCTV prompt').item.json.output.video_prompt }}",
        "batching": {},
        "messages": {
          "messageValues": [
            {
              "message": "You are a world-class short-form social media strategist specialized in viral TikTok and Reels content.\n\nFrom the provided video concept, produce:\n1. A hook-oriented, curiosity-driven TITLE (under 150 characters, no emojis, includes 1-2 searchable keywords).\n2. Exactly FIVE hashtags: 3 broad high-traffic tags (e.g. #fyp #viral #trending) + 2 niche tags describing the animal/CCTV theme. Return them as a single space-separated string.\n\nKeep the title honest about what the clip shows. Do not add commentary or markdown, only the requested fields."
            }
          ]
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 1.9
    },
    {
      "id": "bfb6a454-8c95-4c52-8319-cbe5878db05d",
      "name": "OpenAI model (caption)",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        1600,
        -352
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "={{ $('Configuration').item.json.caption_model }}",
          "cachedResultName": "gpt-5-mini"
        },
        "options": {},
        "builtInTools": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "8a5bce98-9f9b-4285-9fa3-2533401e1e1f",
      "name": "Caption parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        1744,
        -336
      ],
      "parameters": {
        "jsonSchemaExample": "{ \"title\": \"A catchy, curiosity-driven TikTok title without emojis\", \"hashtags\": \"#tag1 #tag2 #tag3 #tag4 #tag5\" }"
      },
      "typeVersion": 1.3
    },
    {
      "id": "824a0ce8-31d0-4752-ab7c-67800c087fa7",
      "name": "Publish to TikTok",
      "type": "@blotato/n8n-nodes-blotato.blotato",
      "position": [
        1920,
        -528
      ],
      "parameters": {
        "options": {},
        "platform": "tiktok",
        "accountId": {
          "__rl": true,
          "mode": "list",
          "value": "9332",
          "cachedResultUrl": "https://backend.blotato.com/v2/accounts/9332",
          "cachedResultName": "docteur.firas"
        },
        "postContentText": "={{ $('Generate title and hashtags').item.json.output.title }} {{ $('Generate title and hashtags').item.json.output.hashtags }}",
        "postContentMediaUrls": "={{ $('Check render status').item.json.data.outputs[0] }}",
        "postCreateTiktokOptionPrivacyLevel": "={{ $('Configuration').item.json.tiktok_privacy_level }}",
        "postCreateTiktokOptionIsAiGenerated": true
      },
      "credentials": {
        "blotatoApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "290e2e59-68c0-4b8e-acc6-72760fef5a0b",
      "name": "Send preview to Telegram",
      "type": "n8n-nodes-base.telegram",
      "position": [
        2112,
        -528
      ],
      "parameters": {
        "file": "={{ $('Check render status').item.json.data.outputs[0] }}",
        "chatId": "={{ $('Configuration').item.json.telegram_chat_id }}",
        "operation": "sendVideo",
        "additionalFields": {
          "caption": "={{ $('Generate title and hashtags').item.json.output.title }}"
        }
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "831b00ba-4d41-4063-ba39-c4cd29cef6ed",
      "name": "Sticky Note 6a468bdc",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -992,
        -880
      ],
      "parameters": {
        "color": 3,
        "width": 900,
        "height": 1804,
        "content": "# Generate CCTV-style animal videos with Seedance and post to TikTok\n# \ud83d\udce5  [Open full documentation on Notion](https://automatisation.notion.site/Course-Generate-CCTV-style-animal-videos-with-Seedance-and-post-to-TikTok-39a3d6550fd98153bb40c3e1a89b194b)\n\n## How it works\nOn a schedule, GPT writes a hyper-realistic \"security camera\" scene prompt (random animal + location + funny action). [AtlasCloud](https://www.atlascloud.ai/?ref=8QKPJE) Seedance 2.0 renders a vertical black-and-white CCTV-style clip. A second GPT step writes a viral title + 5 hashtags. The clip is published to TikTok via [Blotato](https://blotato.com/?ref=firas) (flagged as AI-generated) and a preview is sent to Telegram.\n\n## Setup\n1. Open the **Configuration** node and set your models, video duration, aspect ratio and **telegram_chat_id**.\n2. On both **Start Seedance video** and **Check render status** (HTTP nodes), select the **AtlasCloud API** credential (Header Auth: Authorization = Bearer YOUR_KEY). Get a key on [AtlasCloud](https://www.atlascloud.ai/?ref=8QKPJE).\n3. In **Publish to TikTok**, pick your TikTok account from the dropdown.\n4. Select your OpenAI, Telegram and Blotato credentials on the matching nodes.\n\n## Requirements\n- n8n **self-hosted** (or Cloud with Verified Community Nodes) \u2014 this template uses the [Blotato](https://blotato.com/?ref=firas) community node.\n- OpenAI API key, [AtlasCloud](https://www.atlascloud.ai/?ref=8QKPJE) API key, a [Blotato](https://blotato.com/?ref=firas) account, a Telegram bot.\n- Seedance 2.0 pricing \u2248 $0.10 / second (Fast variant \u2248 $0.022 / s).\n\n## Customization\n- Force a specific animal/location/action via the override fields in **Configuration**.\n- Change the schedule, aspect ratio, or swap **atlas_model** for `bytedance/seedance-2.0-fast/text-to-video` to cut cost.\n- Add more platforms in Blotato (YouTube Shorts, Instagram Reels).\n\n---\nNeed help customizing?\nContact me for consulting and support : [Linkedin](https://www.linkedin.com/in/doctor-firass/)\n\n# MY NEW YOUTUBE CHANNEL\n\ud83d\udc49 [Subscribe to my new YouTube channel](https://www.youtube.com/@DrFiras_AI). Here I'll share videos and Shorts with practical tutorials and FREE templates for n8n.\n\n[![The AI Doctor](https://www.dr-firas.com/the-ai-doctor.png)](https://www.youtube.com/@DrFiras_AI)"
      },
      "typeVersion": 1
    },
    {
      "id": "17154cc8-8104-4497-a9c6-222ab2e2ed22",
      "name": "Sticky Note c694fcec",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        784,
        -832
      ],
      "parameters": {
        "color": 7,
        "width": 740,
        "height": 472,
        "content": "## 2. Render the video with Seedance (AtlasCloud)\nSubmit the prompt to Seedance 2.0, then poll every few seconds until the render is ready. Select the AtlasCloud API credential on both HTTP nodes."
      },
      "typeVersion": 1
    },
    {
      "id": "4475d9b1-4e6f-4f1d-8ae6-32c2618c83d2",
      "name": "Sticky Note c12c9fa8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1568,
        -832
      ],
      "parameters": {
        "color": 7,
        "width": 820,
        "height": 470,
        "content": "## 3. Caption & publish\nWrite a viral title + hashtags, publish to TikTok (flagged AI-generated) and send a preview to Telegram."
      },
      "typeVersion": 1
    },
    {
      "id": "10f40439-0029-42ae-b8f5-f42da465ce65",
      "name": "Sticky Note - Generate",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        16,
        -832
      ],
      "parameters": {
        "color": 7,
        "width": 720,
        "height": 470,
        "content": "## 1. Configure & write the scene\nSet every adjustable variable in **Configuration** (models, duration, aspect ratio, telegram_chat_id, optional overrides). GPT then writes a random CCTV \"caught on camera\" scene prompt."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": true,
    "executionOrder": "v1"
  },
  "versionId": "bf1b64a1-6d22-4085-afdd-7f5f3b82a276",
  "nodeGroups": [],
  "connections": {
    "Configuration": {
      "main": [
        [
          {
            "node": "Generate CCTV prompt",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Caption parser": {
      "ai_outputParser": [
        [
          {
            "node": "Generate title and hashtags",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Is video ready?": {
      "main": [
        [
          {
            "node": "Generate title and hashtags",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Wait for rendering",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Publish to TikTok": {
      "main": [
        [
          {
            "node": "Send preview to Telegram",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Run every 4 hours": {
      "main": [
        [
          {
            "node": "Configuration",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait for rendering": {
      "main": [
        [
          {
            "node": "Check render status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check render status": {
      "main": [
        [
          {
            "node": "Is video ready?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Scene prompt parser": {
      "ai_outputParser": [
        [
          {
            "node": "Generate CCTV prompt",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Generate CCTV prompt": {
      "main": [
        [
          {
            "node": "Start Seedance video",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Start Seedance video": {
      "main": [
        [
          {
            "node": "Wait for rendering",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI model (caption)": {
      "ai_languageModel": [
        [
          {
            "node": "Generate title and hashtags",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Generate title and hashtags": {
      "main": [
        [
          {
            "node": "Publish to TikTok",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI model (scene prompt)": {
      "ai_languageModel": [
        [
          {
            "node": "Generate CCTV prompt",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    }
  }
}