This workflow corresponds to n8n.io template #11594 — we link there as the canonical source.
This workflow follows the Blotaton8N Nodes Blotato → HTTP Request recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"nodes": [
{
"id": "33296347-01d3-4f7b-a29c-6463a74b5390",
"name": "Code1",
"type": "n8n-nodes-base.code",
"position": [
-64,
448
],
"parameters": {
"jsCode": "// n8n Function node\nreturn items.map(item => {\n const data = JSON.parse(item.json.text);\n\n return {\n json: {\n first_frame: data.first_frame,\n last_frame: data.last_frame,\n video_prompt: data.video_prompt,\n dress: data.dress,\n },\n };\n});\n"
},
"retryOnFail": true,
"typeVersion": 2
},
{
"id": "fa521fde-0284-4606-8a56-a17d4b5adedb",
"name": "Story Creator Agent",
"type": "@n8n/n8n-nodes-langchain.chainLlm",
"position": [
288,
144
],
"parameters": {
"text": "=",
"batching": {},
"messages": {
"messageValues": [
{
"message": "=You are an AI system that generates photorealistic, cinematic portrait prompts.\n\nYour task is to generate **TWO cinematic image prompts** representing the **first frame and the last frame**, plus a **dedicated cinematic video motion prompt** for a video featuring the **same girl from the provided reference image**.\nYou must use the **location, mood, outfit, and poses** supplied by the incoming JSON data.\n\n--------------------------------------------\n### REFERENCE IMAGE RULES\nYou MUST base the girl\u2019s identity on the provided image:\n- identical face structure\n- identical eye color and shape\n- identical skin tone\n- identical hairstyle and texture\n- identical overall appearance\n\nNever describe her generically (\u201ca young woman\u201d). \nAlways force the identity to match the **same girl from the reference image**.\n\n--------------------------------------------\n### LOCATION / OUTFIT / MOOD \nUse exactly the values provided:\n\n- **Location (ID {{ $json.location.id }}):** {{ $json.location.name }}\n- **Outfit mapping:** {{ $json.location.outfit }}\n- **Mood:** {{ $json.location.mood }}\n\n--------------------------------------------\n### POSES \nUse ONLY these two poses:\n\n1. **First Frame Pose:** {{ $json.poses[0].label }} \u2014 {{ $json.poses[0].guidance }}\n2. **Last Frame Pose:** {{ $json.poses[1].label }} \u2014 {{ $json.poses[1].guidance }}\n\nDo NOT randomize or replace any pose.\n\n--------------------------------------------\n### VERY IMPORTANT RULES\n\n\u2714 The **same girl** must appear in BOTH frames \n\u2714 The **same location environment** must appear in BOTH frames \n\u2714 The **same mood and atmosphere** must appear in BOTH frames \n\u2714 The **same lighting style** must appear in BOTH frames \n\u2714 The **same outfit** must appear in BOTH frames (but do NOT mention the clothing in the frames) \n\u2714 ONLY her **pose, angle, or expression** may change \n\nDo NOT mention clothing in any frame description. \nPlace the outfit ONLY in the `\"dress\"` field.\n\n--------------------------------------------\n### CINEMATIC STYLE REQUIREMENTS\nEach frame must be:\n- photorealistic \n- editorial \n- cinematic \n- identical lighting, tone, and environment \n- portrait-focused framing \n\n--------------------------------------------\n### VIDEO PROMPT REQUIREMENTS (DYNAMIC CAMERA SYSTEM)\n\nThe video prompt MUST:\n\n- Describe a **smooth physical transition** from the first pose to the last pose \n- Include **natural facial expression interpolation**\n- Include **micro body movement, breathing, and hair motion**\n- Keep **lighting, mood, environment, and outfit fully locked**\n- Include a **cinematic camera movement**\n- The **camera movement MUST be different every time** and may include (but is not limited to):\n - 180\u00b0 arc shot\n - Slow dolly push-in\n - Subtle orbit with parallax\n - Crane rise\n - Lateral tracking shot\n - Tilt + push combination\n - Over-the-shoulder reveal\n- MUST be:\n - Continuous\n - No cuts\n - No scene changes\n - No outfit changes\n- MUST remain:\n - Photorealistic\n - Editorial\n - Cinematic\n\n--------------------------------------------\n### OUTPUT FORMAT (VERY IMPORTANT)\nReturn ONLY valid JSON in this format:\n\n{\n \"first_frame\": \"...\",\n \"last_frame\": \"...\",\n \"video_prompt\": \"...\",\n \"dress\": \"...\"\n}\n\n--------------------------------------------\n### WHAT TO GENERATE\n\n- **First Frame** must contain full cinematic description.\n- **Last Frame** must ONLY change the pose and expression.\n- **Video Prompt** must:\n - Describe the physical transition\n - Describe emotional interpolation\n - Describe realistic micro-movements\n - Describe a **UNIQUE cinematic camera movement each time**\n- Do NOT introduce new lighting, new mood, or new environment in the last frame or video prompt.\n\n--------------------------------------------\n### NOW GENERATE THE FINAL JSON:\n\n{\n \"first_frame\": \"A cinematic portrait of the same girl from the reference image, preserving her exact facial identity \u2014 same facial structure, eye shape, hair texture, skin tone, and natural features. She appears in the '{{ $json.location.name }}' environment with the consistent '{{ $json.location.mood }}' atmosphere. She performs the pose '{{ $json.poses[0].label }}' ({{ $json.poses[0].guidance }}). Photorealistic, editorial, cinematic lighting and composition with portrait-focused framing.\",\n \n \"last_frame\": \"Same girl, same environment, same lighting. She now performs the pose '{{ $json.poses[1].label }}' ({{ $json.poses[1].guidance }}).\",\n \n \"video_prompt\": \"A continuous cinematic shot where the same girl transitions smoothly from the first pose into the final pose with realistic body mechanics, expressive facial interpolation, subtle breathing motion, and natural micro-movements in hair and posture. The camera executes a UNIQUE cinematic movement for this shot \u2014 such as a smooth 180-degree arc, a slow dolly push-in with parallax shift, a controlled lateral track, or an elegant crane rise \u2014 dynamically revealing new perspective while preserving consistent lighting, mood, and environment. No cuts, no scene changes, no outfit changes, maintaining uninterrupted editorial photorealism.\",\n \n \"dress\": \"Detailed outfit description \u2014 {{ $json.location.outfit }} \u2014 matching the mood '{{ $json.location.mood }}'.\"\n}\n"
}
]
},
"promptType": "define",
"hasOutputParser": true
},
"retryOnFail": true,
"typeVersion": 1.7
},
{
"id": "e91cf16f-95ce-4786-b197-1a1509291a1a",
"name": "Sticky Note7",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1616,
80
],
"parameters": {
"color": 5,
"width": 528,
"height": 640,
"content": "## Muhammad Farooq Iqbal - Automation Expert & n8n Creator\n\nI am a passionate automation expert and recognized n8n Creator specializing in intelligent workflow automation. With extensive experience in n8n, AI automation, Zapier, and Make.com, I have created innovative workflow templates with 500+ downloads across the global automation community\n\n### Expertise\n- **Workflow Automation**: n8n, Zapier, Make.com, AI automation\n- **AI Integration**: Gemini AI, API integration, data processing\n- **Platform Mastery**: Google Sheets, Google Drive, custom scripts\n\n## Need Help with This Workflow?\n\nIf you face any issues with this workflow or need customization support, feel free to reach out:\n\n**\ud83d\udce7 Email**: mfarooqiqbal143@gmail.com \n**\ud83d\udcf1 Phone**: +923036991118 \n**\ud83d\udcbc LinkedIn**: [Connect with me](https://linkedin.com/in/muhammadfarooqiqbal) \n**\ud83c\udf10 Portfolio**: [View my work](https://mfarooqone.github.io/n8n/)\n**UpWork**: [Upwork Profile](https://www.upwork.com/freelancers/~011aeba159896e2eba)\n\n*I'm always excited to help with automation challenges and workflow optimization!*\n"
},
"typeVersion": 1
},
{
"id": "3a6b749a-69e0-42ec-8665-d77d26c55d07",
"name": "OpenAI Chat Model1",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
288,
352
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4.1-mini"
},
"options": {}
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "52821147-ec8f-435f-b4b8-53e404ad8c56",
"name": "Schedule Trigger",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-64,
144
],
"parameters": {
"rule": {
"interval": [
{
"field": "hours",
"hoursInterval": 6
}
]
}
},
"typeVersion": 1.2
},
{
"id": "1438296b-26b8-4844-9212-7d822386f075",
"name": "Json parser",
"type": "@n8n/n8n-nodes-langchain.outputParserStructured",
"position": [
1328,
1344
],
"parameters": {
"jsonSchemaExample": "{\n \"title\": \"title\",\n \"description\": \"description\",\n \"hashTags\":\"hashTags\"\n }\n"
},
"typeVersion": 1.3
},
{
"id": "8702591a-f85b-43d4-8e9b-d1232bab0349",
"name": "OpenAI Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
1184,
1344
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4.1-mini"
},
"options": {}
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "1d0462bd-3075-48f8-a925-67990278e8ca",
"name": "Title Description",
"type": "@n8n/n8n-nodes-langchain.chainLlm",
"position": [
1184,
1504
],
"parameters": {
"text": "=",
"batching": {},
"messages": {
"messageValues": [
{
"message": "=*\"You are writing social media content as a lifestyle/fashion influencer. Based on the following visual description, create:\n\nA catchy, stylish title (max 8 words, influencer tone, cinematic vibe).\n\nA short, engaging description (1\u20132 sentences, written in first-person or influencer style, inviting followers into the mood/scene).\n\n5 strong hashtags (blend of aesthetic, fashion, cinematic, and lifestyle trends).\n\n"
}
]
},
"promptType": "define",
"hasOutputParser": true
},
"retryOnFail": true,
"typeVersion": 1.7
},
{
"id": "0fd74fc5-05c7-4187-816b-2a540389d86f",
"name": "Instagram",
"type": "@blotato/n8n-nodes-blotato.blotato",
"position": [
1632,
1504
],
"parameters": {
"options": {},
"accountId": {
"__rl": true,
"mode": "list",
"value": "14052",
"cachedResultUrl": "https://backend.blotato.com/v2/accounts/14052",
"cachedResultName": "lumarose11"
},
"postContentText": "={{ $('Title Description').item.json.output.title }} {{ $('Title Description').item.json.output.hashTags }}",
"postContentMediaUrls": "={{ $('Get Url veo 3.1').item.json.url }}"
},
"credentials": {
"blotatoApi": {
"name": "<your credential>"
}
},
"typeVersion": 2
},
{
"id": "a4e5130b-294c-4853-9612-97afb37ef8b8",
"name": "Tiktok1",
"type": "@blotato/n8n-nodes-blotato.blotato",
"position": [
1488,
1504
],
"parameters": {
"options": {},
"platform": "tiktok",
"accountId": {
"__rl": true,
"mode": "list",
"value": "14980",
"cachedResultUrl": "https://backend.blotato.com/v2/accounts/14980",
"cachedResultName": "lumarose11"
},
"postContentText": "={{ $json.output.title }} {{ $json.output.hashTags }}",
"postContentMediaUrls": "={{ $('Get Url veo 3.1').item.json.url }}",
"postCreateTiktokOptionIsAiGenerated": true
},
"credentials": {
"blotatoApi": {
"name": "<your credential>"
}
},
"typeVersion": 2
},
{
"id": "66a9678c-98b6-4a9b-8e07-18637792912e",
"name": "Code in JavaScript",
"type": "n8n-nodes-base.code",
"position": [
112,
144
],
"parameters": {
"jsCode": "// n8n Function node: Random Location (1\u2013100) + 3 Unique Poses (1\u201315)\n// Includes readable labels for both, and a 5% cap on cafe/library/office-like IDs\n\n// ---- Config: restricted location IDs (caf\u00e9s, libraries, offices & variants)\nconst RESTRICTED = new Set([4, 5, 23, 43, 53, 96]); // \u22645% chance overall\n\n// ---- Pose pool (IDs 1..15)\nconst POSES = [\n { id: 1, label: \"Facing the camera\", guidance: \"natural, expressive look, direct connection\" },\n { id: 2, label: \"Side profile\", guidance: \"elegant, dynamic profile with emotion\" },\n { id: 3, label: \"Back pose\", guidance: \"storytelling, looking over shoulder or natural walk\" },\n { id: 4, label: \"Sitting casually\", guidance: \"relaxed, candid moment with subtle expression\" },\n { id: 5, label: \"Leaning against structure\", guidance: \"editorial calm confidence\" },\n { id: 6, label: \"Walking mid-step\", guidance: \"motion-filled cinematic realism\" },\n { id: 7, label: \"Looking down thoughtfully\", guidance: \"introspective softness\" },\n { id: 8, label: \"Laughing or smiling naturally\", guidance: \"expressive authenticity\" },\n { id: 9, label: \"Hair in motion\", guidance: \"dynamic energy, natural movement\" },\n { id: 10, label: \"Sitting on ground or ledge\", guidance: \"grounded emotional tone\" },\n { id: 11, label: \"Looking into distance\", guidance: \"cinematic depth and reflection\" },\n { id: 12, label: \"Turning halfway\", guidance: \"natural transition moment, in motion\" },\n { id: 13, label: \"Seated with crossed legs\", guidance: \"poised, composed aesthetic\" },\n { id: 14, label: \"Hands in pockets\", guidance: \"casual composure, modern attitude\" },\n { id: 15, label: \"Looking up at light\", guidance: \"ethereal, hopeful expression\" },\n];\n\n// ---- Location mapping (IDs 1..100)\nconst LOCATIONS = [\n { id: 1, name: \"Beach\", outfit: \"bikini/swimsuit (pastel or bold)\", mood: \"carefree, relaxed by waves\" },\n { id: 2, name: \"Airport\", outfit: \"trousers + light jacket (neutral)\", mood: \"thoughtful, waiting calmly\" },\n { id: 3, name: \"City street at night\", outfit: \"leather jacket + jeans\", mood: \"confident under neon lights\" },\n { id: 4, name: \"Luxury caf\u00e9\", outfit: \"chic dress (earthy/pastel)\", mood: \"reflective, sipping coffee\" },\n { id: 5, name: \"Library\", outfit: \"cozy sweater + skirt\", mood: \"focused, gentle concentration\" },\n { id: 6, name: \"Runway backstage\", outfit: \"sleek fashion black\", mood: \"stylish intensity\" },\n { id: 7, name: \"Mountain trail\", outfit: \"sportswear/leggings\", mood: \"fresh, energized mid-step\" },\n { id: 8, name: \"High-rise rooftop\", outfit: \"blazer + jeans\", mood: \"contemplative skyline gaze\" },\n { id: 9, name: \"Subway station\", outfit: \"hoodie/streetwear\", mood: \"calm, listening to music\" },\n { id: 10, name: \"Rainy street\", outfit: \"trench coat + umbrella\", mood: \"soft cinematic romance\" },\n { id: 11, name: \"Desert dunes\", outfit: \"flowing maxi dress\", mood: \"poetic, wind-swept\" },\n { id: 12, name: \"Art gallery\", outfit: \"blouse + tailored pants\", mood: \"cultured admiration\" },\n { id: 13, name: \"Modern kitchen\", outfit: \"casual homewear\", mood: \"cozy, warm tone\" },\n { id: 14, name: \"Luxury hotel lobby\", outfit: \"formal dress\", mood: \"poised elegance\" },\n { id: 15, name: \"Festival grounds\", outfit: \"bohemian outfit\", mood: \"joyful, free spirit\" },\n { id: 16, name: \"Countryside field\", outfit: \"floral sundress\", mood: \"carefree laughter\" },\n { id: 17, name: \"Fitness studio\", outfit: \"sporty outfit\", mood: \"powerful determination\" },\n { id: 18, name: \"Concert lights\", outfit: \"rocker style\", mood: \"edgy, bold\" },\n { id: 19, name: \"Snowy street\", outfit: \"winter coat + scarf\", mood: \"warmth in cold\" },\n { id: 20, name: \"Rooftop bar\", outfit: \"evening gown\", mood: \"cinematic glamour\" },\n { id: 21, name: \"Street market\", outfit: \"casual chic (denim + top)\", mood: \"curious browsing\" },\n { id: 22, name: \"European alley\", outfit: \"vintage look\", mood: \"dreamy nostalgia\" },\n { id: 23, name: \"Office interior\", outfit: \"business attire\", mood: \"confident poise\" },\n { id: 24, name: \"Art studio\", outfit: \"casual + paint stains\", mood: \"creative passion\" },\n { id: 25, name: \"Luxury car interior\", outfit: \"elegant eveningwear\", mood: \"sophistication\" },\n { id: 26, name: \"Seaside cliffs\", outfit: \"flowing dress (white/blue)\", mood: \"serene freedom\" },\n { id: 27, name: \"Minimalist bedroom\", outfit: \"pajamas\", mood: \"intimate softness\" },\n { id: 28, name: \"Rainforest trail\", outfit: \"cargo pants + boots\", mood: \"curious adventure\" },\n { id: 29, name: \"Boutique store\", outfit: \"trendy modern fashion\", mood: \"stylish curiosity\" },\n { id: 30, name: \"Skyline bridge at night\", outfit: \"long coat\", mood: \"cinematic reflection\" },\n { id: 31, name: \"Amusement park\", outfit: \"casual streetwear\", mood: \"joyful laughter\" },\n { id: 32, name: \"Luxury yacht\", outfit: \"elegant summer dress\", mood: \"relaxed, glamorous\" },\n { id: 33, name: \"Skatepark\", outfit: \"urban sporty outfit\", mood: \"playful energy\" },\n { id: 34, name: \"Greenhouse garden\", outfit: \"light floral dress\", mood: \"dreamy wonder\" },\n { id: 35, name: \"Countryside barn\", outfit: \"denim overalls\", mood: \"rustic charm\" },\n { id: 36, name: \"Swimming poolside\", outfit: \"swimsuit + cover-up\", mood: \"refreshing calm\" },\n { id: 37, name: \"Ice rink\", outfit: \"winter coat + skates\", mood: \"playful excitement\" },\n { id: 38, name: \"Luxury spa\", outfit: \"silk robe\", mood: \"serene relaxation\" },\n { id: 39, name: \"Flower field\", outfit: \"pastel sundress\", mood: \"romantic whimsy\" },\n { id: 40, name: \"Underground club\", outfit: \"edgy leather\", mood: \"powerful intensity\" },\n { id: 41, name: \"Train platform\", outfit: \"trench coat\", mood: \"patient waiting\" },\n { id: 42, name: \"Luxury jewelry store\", outfit: \"cocktail dress\", mood: \"poised elegance\" },\n { id: 43, name: \"Street caf\u00e9 terrace\", outfit: \"chic casual\", mood: \"warm smile\" },\n { id: 44, name: \"Bridge over river\", outfit: \"long flowy dress\", mood: \"reflective gaze\" },\n { id: 45, name: \"Sunny park\", outfit: \"shorts + tank\", mood: \"lighthearted play\" },\n { id: 46, name: \"Boat dock\", outfit: \"nautical stripes\", mood: \"casual calm\" },\n { id: 47, name: \"Desert highway\", outfit: \"denim jacket + boots\", mood: \"cinematic road mood\" },\n { id: 48, name: \"University campus\", outfit: \"backpack + casual wear\", mood: \"studious focus\" },\n { id: 49, name: \"Carnival night lights\", outfit: \"bold fun outfit\", mood: \"playful thrill\" },\n { id: 50, name: \"Luxury penthouse\", outfit: \"silk gown\", mood: \"refined elegance\" },\n { id: 51, name: \"Street art wall\", outfit: \"grunge outfit\", mood: \"rebellious energy\" },\n { id: 52, name: \"Farm meadow\", outfit: \"plaid shirt + jeans\", mood: \"country charm\" },\n { id: 53, name: \"Luxury bookshop\", outfit: \"smart casual dress\", mood: \"thoughtful charm\" },\n { id: 54, name: \"Forest clearing\", outfit: \"natural-toned dress\", mood: \"peaceful presence\" },\n { id: 55, name: \"Bridge at golden hour\", outfit: \"trench + scarf\", mood: \"nostalgic vibe\" },\n { id: 56, name: \"Tropical jungle waterfall\", outfit: \"summer adventure outfit\", mood: \"adventurous awe\" },\n { id: 57, name: \"Modern rooftop pool\", outfit: \"bikini + sarong\", mood: \"relaxed, chic\" },\n { id: 58, name: \"Luxury train cabin\", outfit: \"elegant travel attire\", mood: \"poised curiosity\" },\n { id: 59, name: \"Historic palace courtyard\", outfit: \"regal dress\", mood: \"graceful poise\" },\n { id: 60, name: \"Candle-lit restaurant\", outfit: \"cocktail dress\", mood: \"romantic warmth\" },\n { id: 61, name: \"Urban rooftop garden\", outfit: \"modern summer outfit\", mood: \"fresh calm\" },\n { id: 62, name: \"Open desert salt flats\", outfit: \"white flowy outfit\", mood: \"minimalist serenity\" },\n { id: 63, name: \"Rustic cabin\", outfit: \"knit sweater + boots\", mood: \"cozy solitude\" },\n { id: 64, name: \"Fireplace lounge\", outfit: \"evening sweater dress\", mood: \"intimate warmth\" },\n { id: 65, name: \"Old theater\", outfit: \"vintage gown\", mood: \"dramatic elegance\" },\n { id: 66, name: \"Street crossing at rush hour\", outfit: \"modern business look\", mood: \"focused energy\" },\n { id: 67, name: \"Bridge with lanterns\", outfit: \"boho outfit\", mood: \"dreamy night\" },\n { id: 68, name: \"Sunny vineyard\", outfit: \"sundress + hat\", mood: \"relaxed joy\" },\n { id: 69, name: \"Museum interior\", outfit: \"chic modern dress\", mood: \"cultured awe\" },\n { id: 70, name: \"Abandoned warehouse\", outfit: \"edgy streetwear\", mood: \"raw intensity\" },\n { id: 71, name: \"Luxury spa pool\", outfit: \"silk robe + swimwear\", mood: \"calm grace\" },\n { id: 72, name: \"Hot air balloon deck\", outfit: \"flowy travel outfit\", mood: \"adventurous thrill\" },\n { id: 73, name: \"Open meadow with mountains\", outfit: \"sundress\", mood: \"serene content\" },\n { id: 74, name: \"Urban stairwell\", outfit: \"edgy casual\", mood: \"thoughtful pause\" },\n { id: 75, name: \"Skyscraper balcony\", outfit: \"cocktail dress\", mood: \"dramatic power\" },\n { id: 76, name: \"Sunset pier\", outfit: \"maxi dress\", mood: \"calm reflection\" },\n { id: 77, name: \"Luxury shopping mall\", outfit: \"chic outfit\", mood: \"stylish exploration\" },\n { id: 78, name: \"Foggy forest trail\", outfit: \"layered outdoor gear\", mood: \"mysterious calm\" },\n { id: 79, name: \"Old castle ruins\", outfit: \"medieval-inspired dress\", mood: \"ethereal tone\" },\n { id: 80, name: \"Lakeside dock\", outfit: \"denim shorts + tank\", mood: \"peaceful gaze\" },\n { id: 81, name: \"Helipad rooftop\", outfit: \"power suit\", mood: \"commanding mood\" },\n { id: 82, name: \"Street with bicycles\", outfit: \"casual sporty\", mood: \"cheerful everyday mood\" },\n { id: 83, name: \"Opera house steps\", outfit: \"gown + clutch\", mood: \"elegant prestige\" },\n { id: 84, name: \"Industrial bridge\", outfit: \"leather jacket\", mood: \"urban cinematic mood\" },\n { id: 85, name: \"Flower shop\", outfit: \"light spring dress\", mood: \"sweet charm\" },\n { id: 86, name: \"Bus stop at night\", outfit: \"streetwear\", mood: \"reflective solitude\" },\n { id: 87, name: \"Tropical beach bar\", outfit: \"summer outfit\", mood: \"vibrant joy\" },\n { id: 88, name: \"Cultural temple courtyard\", outfit: \"modest chic outfit\", mood: \"respectful calm\" },\n { id: 89, name: \"Street food festival\", outfit: \"casual fun outfit\", mood: \"lively curiosity\" },\n { id: 90, name: \"Outdoor cinema night\", outfit: \"casual blanket outfit\", mood: \"cozy joy\" },\n { id: 91, name: \"Luxury rooftop infinity pool\", outfit: \"bikini + robe\", mood: \"chic elegance\" },\n { id: 92, name: \"Foggy seaside rocks\", outfit: \"wool coat\", mood: \"melancholic tone\" },\n { id: 93, name: \"Train interior\", outfit: \"travel attire\", mood: \"reflective gaze\" },\n { id: 94, name: \"Desert canyon\", outfit: \"explorer outfit\", mood: \"powerful presence\" },\n { id: 95, name: \"Luxury music lounge\", outfit: \"cocktail dress\", mood: \"sophisticated charm\" },\n { id: 96, name: \"Historic library hall\", outfit: \"classic smart outfit\", mood: \"intellectual poise\" },\n { id: 97, name: \"Bridge over waterfall\", outfit: \"flowing summer dress\", mood: \"dramatic awe\" },\n { id: 98, name: \"Urban skate alley\", outfit: \"sporty casual\", mood: \"energetic vibe\" },\n { id: 99, name: \"Sunny sunflower field\", outfit: \"yellow sundress\", mood: \"radiant joy\" },\n { id: 100, name: \"Candlelit rooftop dinner\", outfit: \"elegant evening dress\", mood: \"intimate romance\" },\n];\n\n// ---- Helpers\nfunction pickLocationId() {\n while (true) {\n const id = Math.floor(Math.random() * 100) + 1; // 1..100\n if (RESTRICTED.has(id)) {\n if (Math.random() < 0.05) return id; // allow \u22645%\n continue; // re-roll\n }\n return id;\n }\n}\n\nfunction pickUniquePoseIds(n = 3, maxId = 15) {\n const pool = Array.from({ length: maxId }, (_, i) => i + 1);\n for (let i = pool.length - 1; i > 0; i--) {\n const j = Math.floor(Math.random() * (i + 1));\n [pool[i], pool[j]] = [pool[j], pool[i]];\n }\n return pool.slice(0, n).sort((a, b) => a - b);\n}\n\n// ---- Draw randoms\nconst locationId = pickLocationId();\nconst poseIds = pickUniquePoseIds(3, 15);\n\n// ---- Resolve data objects\nconst location = LOCATIONS.find(l => l.id === locationId);\nconst poses = poseIds.map(id => POSES.find(p => p.id === id));\n\n// ---- Return for next node usage\nreturn [{\n locationId,\n location, // { id, name, outfit, mood }\n poseIds, // e.g. [2, 9, 15]\n poses, // [{id,label,guidance}, ...]\n}];\n"
},
"typeVersion": 2
},
{
"id": "ff903309-3ec8-4254-b079-5a9892d87e6f",
"name": "Veo 3.1",
"type": "n8n-nodes-base.httpRequest",
"position": [
-144,
1280
],
"parameters": {
"url": "https://api.kie.ai/api/v1/veo/generate",
"method": "POST",
"options": {},
"jsonBody": "={\n \"prompt\": \"{{ $('Code1').item.json.video_prompt }}\",\n \"imageUrls\": [\n \"{{ $('Start Frame Image Url').item.json.resultUrls[0] }}\",\n \"{{ $('End Frame Image Url').item.json.resultUrls[0] }}\"\n ],\n \"model\": \"veo3_fast\",\n \"watermark\": \"Luma Rose\",\n \"callBackUrl\": \"http://your-callback-url.com/complete\",\n \"aspectRatio\": \"9:16\",\n \"seeds\": 12345,\n \"enableFallback\": false,\n \"enableTranslation\": true,\n \"generationType\": \"FIRST_AND_LAST_FRAMES_2_VIDEO\"\n}",
"sendBody": true,
"specifyBody": "json",
"authentication": "genericCredentialType",
"genericAuthType": "httpBearerAuth"
},
"credentials": {
"httpBearerAuth": {
"name": "<your credential>"
}
},
"typeVersion": 4.2
},
{
"id": "cdb9f9b0-c8d0-42e9-84b6-094885644527",
"name": "Wait Start Frame",
"type": "n8n-nodes-base.wait",
"position": [
48,
704
],
"parameters": {
"unit": "seconds",
"amount": 5
},
"retryOnFail": true,
"typeVersion": 1
},
{
"id": "3b6233a1-f186-49ab-81de-75d07e1b04fc",
"name": "Get Start Frame",
"type": "n8n-nodes-base.httpRequest",
"position": [
208,
704
],
"parameters": {
"url": "https://api.kie.ai/api/v1/jobs/recordInfo",
"options": {},
"sendQuery": true,
"authentication": "genericCredentialType",
"genericAuthType": "httpBearerAuth",
"queryParameters": {
"parameters": [
{
"name": "taskId",
"value": "={{ $json.data.taskId }}"
}
]
}
},
"credentials": {
"httpBearerAuth": {
"name": "<your credential>"
}
},
"retryOnFail": true,
"typeVersion": 4.2
},
{
"id": "2cb7a99e-e7ba-48b3-b254-00ad169469d1",
"name": "Switch Start Frame",
"type": "n8n-nodes-base.switch",
"onError": "continueRegularOutput",
"position": [
416,
656
],
"parameters": {
"rules": {
"values": [
{
"outputKey": "fail",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "fail-state-condition",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.data.state }}",
"rightValue": "fail"
}
]
},
"renameOutput": true
},
{
"outputKey": "success",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "success-state-condition",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.data.state }}",
"rightValue": "success"
}
]
},
"renameOutput": true
},
{
"outputKey": "generating",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "generating-state-condition",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.data.state }}",
"rightValue": "generating"
}
]
},
"renameOutput": true
},
{
"outputKey": "queuing",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "queuing-state-condition",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.data.state }}",
"rightValue": "queuing"
}
]
},
"renameOutput": true
},
{
"outputKey": "waiting",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "waiting-state-condition",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.data.state }}",
"rightValue": "waiting"
}
]
},
"renameOutput": true
}
]
},
"options": {}
},
"retryOnFail": true,
"typeVersion": 3.2
},
{
"id": "4596abd7-d68f-4720-b5fd-a636d37fd63a",
"name": "Start Frame Image Url",
"type": "n8n-nodes-base.code",
"position": [
432,
992
],
"parameters": {
"jsCode": "// n8n Function node\nconst items = $input.all();\nconst out = [];\n\nfor (const item of items) {\n // Your HTTP node sometimes returns an array at top-level\n const payload = item.json;\n const first = Array.isArray(payload) ? payload[0] : payload;\n\n // Get the stringified resultJson safely\n const resultJsonStr = first?.data?.resultJson ?? '';\n\n // Parse and extract\n let resultUrls = [];\n try {\n const parsed = JSON.parse(resultJsonStr);\n resultUrls = parsed?.resultUrls ?? [];\n } catch (e) {\n // leave resultUrls as []\n }\n\n out.push({ json: { resultUrls } });\n}\n\nreturn out;\n"
},
"retryOnFail": true,
"typeVersion": 2
},
{
"id": "06128ca2-5b03-4fc7-9711-4cb555db88ea",
"name": "Create End Frame",
"type": "n8n-nodes-base.httpRequest",
"position": [
1008,
992
],
"parameters": {
"url": "https://api.kie.ai/api/v1/jobs/createTask",
"method": "POST",
"options": {},
"jsonBody": "={\n \"model\": \"google/nano-banana-edit\",\n \"input\": {\n \"prompt\": \"{{ $('Code1').item.json.last_frame }}\",\n \"image_urls\": [\n \"{{ $json.resultUrls[0] }}\"\n ],\n \"output_format\": \"jpeg\",\n \"image_size\": \"9:16\"\n }\n}",
"sendBody": true,
"specifyBody": "json",
"authentication": "genericCredentialType",
"genericAuthType": "httpBearerAuth"
},
"credentials": {
"httpBearerAuth": {
"name": "<your credential>"
}
},
"retryOnFail": true,
"typeVersion": 4.2
},
{
"id": "71072d50-8137-43b6-8c24-a1642ec39366",
"name": "Wait End Frame",
"type": "n8n-nodes-base.wait",
"position": [
1264,
912
],
"parameters": {
"unit": "seconds",
"amount": 5
},
"retryOnFail": true,
"typeVersion": 1
},
{
"id": "888de9c0-178e-44e5-b567-02f38fb61a66",
"name": "Get End Frame",
"type": "n8n-nodes-base.httpRequest",
"position": [
1424,
912
],
"parameters": {
"url": "https://api.kie.ai/api/v1/jobs/recordInfo",
"options": {},
"sendQuery": true,
"authentication": "genericCredentialType",
"genericAuthType": "httpBearerAuth",
"queryParameters": {
"parameters": [
{
"name": "taskId",
"value": "={{ $json.data.taskId }}"
}
]
}
},
"credentials": {
"httpBearerAuth": {
"name": "<your credential>"
}
},
"retryOnFail": true,
"typeVersion": 4.2
},
{
"id": "f4ef273e-31ce-41b9-998c-55ea56514468",
"name": "Switch End Frame",
"type": "n8n-nodes-base.switch",
"onError": "continueRegularOutput",
"position": [
1632,
864
],
"parameters": {
"rules": {
"values": [
{
"outputKey": "fail",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "fail-state-condition",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.data.state }}",
"rightValue": "fail"
}
]
},
"renameOutput": true
},
{
"outputKey": "success",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "success-state-condition",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.data.state }}",
"rightValue": "success"
}
]
},
"renameOutput": true
},
{
"outputKey": "generating",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "generating-state-condition",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.data.state }}",
"rightValue": "generating"
}
]
},
"renameOutput": true
},
{
"outputKey": "queuing",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "queuing-state-condition",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.data.state }}",
"rightValue": "queuing"
}
]
},
"renameOutput": true
},
{
"outputKey": "waiting",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "waiting-state-condition",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.data.state }}",
"rightValue": "waiting"
}
]
},
"renameOutput": true
}
]
},
"options": {}
},
"retryOnFail": true,
"typeVersion": 3.2
},
{
"id": "3615418c-561e-48e2-9718-d9d6ddff1250",
"name": "Get Start Frame Binary",
"type": "n8n-nodes-base.httpRequest",
"position": [
-144,
976
],
"parameters": {
"url": "={{ $json.resultUrls[0] }}",
"options": {}
},
"retryOnFail": true,
"typeVersion": 4.2
},
{
"id": "5f85a7a7-d100-4ae7-84f3-9c30017e5629",
"name": "Get End Frame Binary",
"type": "n8n-nodes-base.httpRequest",
"position": [
1456,
720
],
"parameters": {
"url": "={{ $json.resultUrls[0] }}",
"options": {}
},
"retryOnFail": true,
"typeVersion": 4.2
},
{
"id": "5974648b-2b81-4dd0-89ed-75fe4ff47d50",
"name": "wait veo 3.1",
"type": "n8n-nodes-base.wait",
"position": [
80,
1280
],
"parameters": {},
"typeVersion": 1.1
},
{
"id": "665940a5-cda8-4316-8d78-bf7636f3c6d8",
"name": "Get veo 3.1",
"type": "n8n-nodes-base.httpRequest",
"position": [
272,
1280
],
"parameters": {
"url": "https://api.kie.ai/api/v1/veo/record-info",
"options": {},
"sendQuery": true,
"authentication": "genericCredentialType",
"genericAuthType": "httpBearerAuth",
"queryParameters": {
"parameters": [
{
"name": "taskId",
"value": "={{ $json.data.taskId }}"
}
]
}
},
"credentials": {
"httpBearerAuth": {
"name": "<your credential>"
}
},
"retryOnFail": true,
"typeVersion": 4.2
},
{
"id": "58f67cb8-4a90-4e0d-9f75-715c64308a0b",
"name": "Switch veo 3.1",
"type": "n8n-nodes-base.switch",
"position": [
480,
1280
],
"parameters": {
"rules": {
"values": [
{
"outputKey": "empty",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "0d625163-62c4-45d9-963b-e98044326ca9",
"operator": {
"type": "string",
"operation": "notExists",
"singleValue": true
},
"leftValue": "={{ $json.data.response.taskId }}",
"rightValue": ""
}
]
},
"renameOutput": true
},
{
"outputKey": "success",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "336b2e80-f57c-430a-8df8-f900b6a8755b",
"operator": {
"type": "string",
"operation": "notEmpty",
"singleValue": true
},
"leftValue": "={{ $json.data.response.taskId }}",
"rightValue": ""
}
]
},
"renameOutput": true
}
]
},
"options": {}
},
"typeVersion": 3.3
},
{
"id": "dbbeaad0-17d7-410c-b335-794c1b83f948",
"name": "Get Url veo 3.1",
"type": "n8n-nodes-base.code",
"position": [
-144,
1504
],
"parameters": {
"jsCode": "// n8n Function node\nreturn items.map(item => {\n const resultUrl = item.json?.data?.response?.resultUrls?.[0] || null;\n\n return {\n json: {\n url: resultUrl\n },\n };\n});\n"
},
"retryOnFail": true,
"typeVersion": 2
},
{
"id": "e39064bc-4d04-4903-a01c-e2c6b1004ab8",
"name": "Get veo 3.1 Binary",
"type": "n8n-nodes-base.httpRequest",
"position": [
32,
1504
],
"parameters": {
"url": "={{ $json.url }}",
"options": {}
},
"retryOnFail": true,
"typeVersion": 4.2
},
{
"id": "1143d5ab-cee2-4588-946a-fd67252537fd",
"name": "Send Start Frame",
"type": "n8n-nodes-base.telegram",
"position": [
48,
976
],
"parameters": {
"file": "={{ $json.resultUrls[0] }}",
"chatId": "123456789",
"operation": "sendPhoto",
"additionalFields": {}
},
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "e20ce9e7-c3dc-4973-ae7f-e9a9500ed2b5",
"name": "Send End Frame",
"type": "n8n-nodes-base.telegram",
"position": [
1648,
720
],
"parameters": {
"file": "={{ $json.resultUrls[0] }}",
"chatId": "123456789",
"operation": "sendPhoto",
"additionalFields": {}
},
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "5426f7a9-5c3b-4822-a0f7-1e589282f5dd",
"name": "Send Video",
"type": "n8n-nodes-base.telegram",
"position": [
224,
1504
],
"parameters": {
"file": "={{ $json.url }}",
"chatId": "123456789",
"operation": "sendVideo",
"additionalFields": {}
},
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "241f7473-c024-4814-9e14-e826cd50fa13",
"name": "End Frame Image Url",
"type": "n8n-nodes-base.code",
"position": [
1264,
720
],
"parameters": {
"jsCode": "// n8n Function node\nconst items = $input.all();\nconst out = [];\n\nfor (const item of items) {\n // Your HTTP node sometimes returns an array at top-level\n const payload = item.json;\n const first = Array.isArray(payload) ? payload[0] : payload;\n\n // Get the stringified resultJson safely\n const resultJsonStr = first?.data?.resultJson ?? '';\n\n // Parse and extract\n let resultUrls = [];\n try {\n const parsed = JSON.parse(resultJsonStr);\n resultUrls = parsed?.resultUrls ?? [];\n } catch (e) {\n // leave resultUrls as []\n }\n\n out.push({ json: { resultUrls } });\n}\n\nreturn out;\n"
},
"retryOnFail": true,
"typeVersion": 2
},
{
"id": "f3a7e31b-c0cb-4f15-be7f-0381c1d36716",
"name": "Create Start Frame",
"type": "n8n-nodes-base.httpRequest",
"position": [
-144,
704
],
"parameters": {
"url": "https://api.kie.ai/api/v1/jobs/createTask",
"method": "POST",
"options": {},
"jsonBody": "={\n \"model\": \"google/nano-banana-edit\",\n \"input\": {\n \"prompt\": \"{{ $json.first_frame }} Dress: {{ $json.dress }}\",\n \"image_urls\": [\n \"https://i.ibb.co/q332LXHf/Whats-App-Image-2025-09-11-at-15-54-09.jpg\",\n \"https://i.ibb.co/rPRzBdK/Whats-App-Image-2025-09-11-at-15-54-11-1.jpg\",\n \"https://i.ibb.co/Zz9HPfZ9/Whats-App-Image-2025-09-11-at-15-54-12-1.jpg\",\n \"https://i.ibb.co/tp7rhyK7/Whats-App-Image-2025-09-11-at-15-54-12-2.jpg\",\n \"https://i.ibb.co/N2wDdJpJ/Whats-App-Image-2025-09-11-at-15-54-12-3.jpg\"\n ],\n \"output_format\": \"jpeg\",\n \"image_size\": \"9:16\"\n }\n}",
"sendBody": true,
"specifyBody": "json",
"authentication": "genericCredentialType",
"genericAuthType": "httpBearerAuth"
},
"credentials": {
"httpBearerAuth": {
"name": "<your credential>"
}
},
"retryOnFail": true,
"typeVersion": 4.2
},
{
"id": "9d848ace-c3a8-4165-be50-fedf8b20619e",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1072,
80
],
"parameters": {
"width": 450,
"height": 802,
"content": "## \ud83d\udd27 Setup & Integration Guide\n\n**\ud83d\udccb Required API Keys & Services:**\n\n1. **OpenAI API**\n \u2022 Get from: https://platform.openai.com/api-keys\n \u2022 Used for: GPT-4o prompt generation\n \u2022 Add to: OpenAI Chat Model nodes\n\n2. **KIE.AI API**\n \u2022 Get from: https://kie.ai/\n \u2022 Used for: Veo 3.1 video & Nano Banana Edit images\n \u2022 Replace 'YOUR_KIE_AI_API_KEY' in HTTP Request nodes\n \u2022 Or use HTTP Bearer YOUR_TOKEN_HERE credentials\n\n3. **Blotato API**\n \u2022 Get from: https://blotato.com/\n \u2022 Used for: TikTok & Instagram posting\n \u2022 Add to: Blotato nodes\n\n4. **Telegram Bot Token**\n \u2022 Create via @BotFather\n \u2022 Used for: Preview delivery\n \u2022 Add to: Telegram nodes\n\n**\u26a1 Quick Setup:**\n1. Replace all API key placeholders\n2. Configure reference images (5 images for character)\n3. Set Telegram chat ID for delivery\n4. Configure Blotato accounts (TikTok & Instagram)\n5. Test with schedule trigger\n\n**\ud83d\udcf8 Reference Images:**\nUpdate the 5 image URLs in 'Create Start Frame' node with your character reference images."
},
"typeVersion": 1
},
{
"id": "8179c4d8-c6c3-4495-ac67-5170e3dc6d7b",
"name": "Sticky Note10",
"type": "n8n-nodes-base.stickyNote",
"position": [
-608,
80
],
"parameters": {
"color": 4,
"width": 1248,
"height": 488,
"content": "## \ud83d\udcd6 Story Creation Section\n\n**What it does:**\n\u2022 Randomly selects location (1-100) and 3 unique poses (1-15)\n\u2022 GPT-4o generates cinematic prompts for first/last frames\n\u2022 Creates consistent character identity across frames\n\u2022 Generates video motion prompts with dynamic camera movements\n\n**Key Features:**\n\u2022 100 unique locations (beaches, cities, cafes, etc.)\n\u2022 15 different poses (facing camera, side profile, walking, etc.)\n\u2022 Maintains character consistency (same face, hair, features)\n\u2022 Cinematic style with photorealistic quality\n\u2022 Dynamic camera movements (arc shots, dolly, crane, etc.)"
},
"typeVersion": 1
},
{
"id": "db9c9ec4-c15c-475e-a8f4-1b6303a5d67a",
"name": "Sticky Note11",
"type": "n8n-nodes-base.stickyNote",
"position": [
-608,
592
],
"parameters": {
"color": 4,
"width": 1248,
"height": 584,
"content": "## \ud83d\uddbc\ufe0f Start Frame Image Generation\n\n**What it does:**\n\u2022 Uses Google Nano Banana Edit model via KIE.AI\n\u2022 Generates first frame with character in initial pose\n\u2022 Applies outfit and location from story creation\n\u2022 Waits for AI processing completion (polling)\n\n**Process:**\n1. Create task with prompt + reference images\n2. Wait 5 seconds\n3. Poll status until 'success'\n4. Extract image URL from result\n\n**Output:** 9:16 aspect ratio JPEG image"
},
"typeVersion": 1
},
{
"id": "5d2a623d-8a48-4438-895f-356753138776",
"name": "Sticky Note13",
"type": "n8n-nodes-base.stickyNote",
"position": [
-608,
1200
],
"parameters": {
"color": 4,
"width": 1248,
"height": 464,
"content": "## \ud83c\udfac Veo 3.1 Video Generation\n\n**What it does:**\n\u2022 Uses Google Veo 3.1 Fast model via KIE.AI\n\u2022 Creates smooth video transition between frames\n\u2022 Generates cinematic motion with natural character movement\n\u2022 Maintains character consistency throughout video\n\n**Input:**\n\u2022 Start frame image URL\n\u2022 End frame image URL\n\u2022 Video motion prompt (from story creation)\n\n**Process:**\n1. Submit video generation task\n2. Wait for processing (webhook-based)\n3. Poll until completion\n4. Extract video URL\n\n**Output:** 9:16 aspect ratio video with watermark"
},
"typeVersion": 1
},
{
"id": "3fe8782c-5d7f-4f2c-b3ce-33f4a809ca63",
"name": "Sticky Note14",
"type": "n8n-nodes-base.stickyNote",
"position": [
656,
1200
],
"parameters": {
"color": 4,
"width": 1248,
"height": 464,
"content": "## \ud83d\udcf1 Social Media Publishing\n\n**What it does:**\n\u2022 Generates title, description, and hashtags using GPT-4o\n\u2022 Posts to TikTok with AI-generated content label\n\u2022 Posts to Instagram with same content\n\u2022 Sends previews via Telegram\n\n**Content Generation:**\n\u2022 Catchy title (max 8 words)\n\u2022 Engaging description (1-2 sentences)\n\u2022 5 relevant hashtags (aesthetic, fashion, cinematic)\n\n**Platforms:**\n\u2022 TikTok (with AI disclosure)\n\u2022 Instagram\n\u2022 Telegram (preview delivery)"
},
"typeVersion": 1
},
{
"id": "6be7f32f-d53c-4b50-b9fc-9b1460ece451",
"name": "Sticky Note15",
"type": "n8n-nodes-base.stickyNote",
"position": [
656,
592
],
"parameters": {
"color": 4,
"width": 1248,
"height": 584,
"content": "## \ud83d\uddbc\ufe0f End Frame Image Generation\n\n**What it does:**\n\u2022 Uses Google Nano Banana Edit to create final frame\n\u2022 Uses start frame as reference for consistency\n\u2022 Changes only pose/expression (same character, location, outfit)\n\u2022 Maintains identical lighting and mood\n\n**Process:**\n1. Create task with last_frame prompt\n2. Use start frame as reference image\n3. Poll status until completion\n4. Extract final image URL\n\n**Output:** Matching 9:16 JPEG with pose change"
},
"typeVersion": 1
}
],
"connections": {
"Code1": {
"main": [
[
{
"node": "Create Start Frame",
"type": "main",
"index": 0
}
]
]
},
"Tiktok1": {
"main": [
[
{
"node": "Instagram",
"type": "main",
"index": 0
}
]
]
},
"Veo 3.1": {
"main": [
[
{
"node": "wait veo 3.1",
"type": "main",
"index": 0
}
]
]
},
"Json parser": {
"ai_outputParser": [
[
{
"node": "Title Description",
"type": "ai_outputParser",
"index": 0
}
]
]
},
"Get veo 3.1": {
"main": [
[
{
"node": "Switch veo 3.1",
"type": "main",
"index": 0
}
]
]
},
"wait veo 3.1": {
"main": [
[
{
"node": "Get veo 3.1",
"type": "main",
"index": 0
}
]
]
},
"Get End Frame": {
"main": [
[
{
"node": "Switch End Frame",
"type": "main",
"index": 0
}
]
]
},
"Switch veo 3.1": {
"main": [
[
{
"node": "wait veo 3.1",
"type": "main",
"index": 0
}
],
[
{
"node": "Get Url veo 3.1",
"type": "main",
"index": 0
}
]
]
},
"Wait End Frame": {
"main": [
[
{
"node": "Get End Frame",
"type": "main",
"index": 0
}
]
]
},
"Get Start Frame": {
"main": [
[
{
"node": "Switch Start Frame",
"type": "main",
"index": 0
}
]
]
},
"Get Url veo 3.1": {
"main": [
[
{
"node": "Get veo 3.1 Binary",
"type": "main",
"index": 0
},
{
"node": "Title Description",
"type": "main",
"index": 0
}
]
]
},
"Create End Frame": {
"main": [
[
{
"node": "Wait End Frame",
"type": "main",
"index": 0
}
]
]
},
"Schedule Trigger": {
"main": [
[
{
"node": "Code in JavaScript",
"type": "main",
"index": 0
}
]
]
},
"Switch End Frame": {
"main": [
[],
[
{
"node": "End Frame Image Url",
"type": "main",
"index": 0
}
],
[
{
"node": "Wait End Frame",
"type": "main",
"index": 0
}
],
[
{
"node": "Wait End Frame",
"type": "main",
"index": 0
}
],
[
{
"node": "Wait End Frame",
"type": "main",
"index": 0
}
]
]
},
"Wait Start Frame": {
"main": [
[
{
"node": "Get Start Frame",
"type": "main",
"index": 0
}
]
]
},
"OpenAI Chat Model": {
"ai_languageModel": [
[
{
"node": "Title Description",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Title Description": {
"main": [
[
{
"node": "Tiktok1",
"type": "main",
"index": 0
}
]
]
},
"Code in JavaScript": {
"main": [
[
{
"node": "Story Creator Agent",
"type": "main",
"index": 0
}
]
]
},
"Create Start Frame": {
"main": [
[
{
"node": "Wait Start Frame",
"type": "main",
"index": 0
}
]
]
},
"Get veo 3.1 Binary": {
"main": [
[
{
"node": "Send Video",
"type": "main",
"index": 0
}
]
]
},
"OpenAI Chat Model1": {
"ai_languageModel": [
[
{
"node": "Story Creator Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Switch Start Frame": {
"main": [
[],
[
{
"node": "Start Frame Image Url",
"type": "main",
"index": 0
}
],
[
{
"node": "Wait Start Frame",
"type": "main",
"index": 0
}
],
[
{
"node": "Wait Start Frame",
"type": "main",
"index": 0
}
],
[
{
"node": "Wait Start Frame",
"type": "main",
"index": 0
}
]
]
},
"End Frame Image Url": {
"main": [
[
{
"node": "Get End Frame Binary",
"type": "main",
"index": 0
},
{
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.
blotatoApihttpBearerAuthopenAiApitelegramApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This n8n template demonstrates how to create consistent character videos using AI image and video generation. The workflow generates photorealistic videos featuring the same character across different poses, locations, and outfits, maintaining perfect character consistency…
Source: https://n8n.io/workflows/11594/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
This n8n workflow automates the creation of viral CCTV-style animal videos using AI, perfect for TikTok content creators looking to capitalize on the popular security camera animal footage trend. The
Automate Blog Creation and Publishing with Ultra-Low Cost AI
Complete PostgreSQL-backed system: Keyword scoring → AI research → Multi-part content generation → fal.ai Nano Banana image generation → WordPress publishing
Generate AI viral videos with NanoBanana & VEO3, shared on socials via Blotato 2. Uses @blotato/n8n-nodes-blotato, googleSheets, lmChatOpenAi, toolThink. Event-driven trigger; 94 nodes.
This workflow is designed for: Content creators and marketers E-commerce and product-based businesses Agencies producing social media visuals and videos Automation builders looking for AI-powered crea