AutomationFlows β€Ί AI & RAG β€Ί Create AI Viral Videos Using Nanobanana 2 Pro & Veo3.1 and Publish via…

Create AI Viral Videos Using Nanobanana 2 Pro & Veo3.1 and Publish via…

Original n8n title: πŸ’₯ Create AI Viral Videos Using Nanobanana 2 Pro & Veo3.1 and Publish via Blotato -vide

πŸ’₯ Create AI Viral Videos using NanoBanana 2 PRO & VEO3.1 and Publish via Blotato -vide. Uses lmChatOpenAi, toolThink, outputParserStructured, telegramTrigger. Event-driven trigger; 35 nodes.

Event triggerβ˜…β˜…β˜…β˜…β˜… complexityAI-powered35 nodesOpenAI ChatTool ThinkOutput Parser StructuredTelegram TriggerAgentHTTP RequestOpenAITelegram
AI & RAG Trigger: Event Nodes: 35 Complexity: β˜…β˜…β˜…β˜…β˜… AI nodes: yes Added:

This workflow follows the Agent β†’ 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 β†’

Download .json
{
  "id": "c1RYY5JDniAWe4Lm",
  "meta": {
    "site": "https://github.com/zengfr/n8n-workflow-all-templates",
    "name": "Create AI Viral Videos using NanoBanana 2 PRO & VEO3.1 and Publish via Blotato",
    "wechat": "youandme10086",
    "id": 11204,
    "update_time": "2025-12-06"
  },
  "name": "\ud83d\udca5 Create AI Viral Videos using NanoBanana 2 PRO & VEO3.1 and Publish via Blotato -vide",
  "tags": [],
  "nodes": [
    {
      "id": "7c727b4c-0395-4262-85f9-b00fa9d5aa9e",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        928,
        832
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "913750ef-1d67-4a69-ab6d-8219b44a54ec",
      "name": "Think",
      "type": "@n8n/n8n-nodes-langchain.toolThink",
      "position": [
        1072,
        832
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "0f440371-db4d-4847-a104-5bd02f5ec495",
      "name": "Structured Output Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        1200,
        832
      ],
      "parameters": {
        "jsonSchemaExample": "{\n  \"prompt\": \"string\",\n  \"caption\": \"string\",\n  \"title\": \"string\", \n  \"hashtags\": \"string\"\n}\n"
      },
      "typeVersion": 1.3
    },
    {
      "id": "b5174475-5425-49de-97fa-381e573f260f",
      "name": "Telegram Trigger: Receive Video Idea",
      "type": "n8n-nodes-base.telegramTrigger",
      "position": [
        784,
        192
      ],
      "parameters": {
        "updates": [
          "message"
        ],
        "additionalFields": {}
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "c52b61fe-df02-4c7f-9b1d-c8763d081c0f",
      "name": "Set Master Prompt",
      "type": "n8n-nodes-base.set",
      "position": [
        800,
        640
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "cc2e0500-57b1-4615-82cb-1c950e5f2ec4",
              "name": "json_master",
              "type": "string",
              "value": "={\n  \"description\": \"Brief narrative description of the scene, focusing on key visual storytelling and product transformation.\",\n  \"style\": \"cinematic | photorealistic | stylized | gritty | elegant\",\n  \"camera\": {\n    \"type\": \"fixed | dolly | Steadicam | crane combo\",\n    \"movement\": \"describe any camera moves like slow push-in, pan, orbit\",\n    \"lens\": \"optional lens type or focal length for cinematic effect\"\n  },\n  \"lighting\": {\n    \"type\": \"natural | dramatic | high-contrast\",\n    \"sources\": \"key lighting sources (sunset, halogen, ambient glow...)\",\n    \"FX\": \"optional VFX elements like fog, reflections, flares\"\n  },\n  \"environment\": {\n    \"location\": \"describe location or room (kitchen, desert, basketball court...)\",\n    \"set_pieces\": [\n      \"list of key background or prop elements\",\n      \"e.g. hardwood floors, chain-link fence, velvet surface\"\n    ],\n    \"mood\": \"describe the ambient atmosphere (moody, clean, epic...)\"\n  },\n  \"elements\": [\n    \"main physical items involved (product box, accessories, vehicles...)\",\n    \"include brand visibility (logos, packaging, texture...)\"\n  ],\n  \"subject\": {\n    \"character\": {\n      \"description\": \"optional \u2013 physical description, outfit\",\n      \"pose\": \"optional \u2013 position or gesture\",\n      \"lip_sync_line\": \"optional \u2013 spoken line if there\u2019s a voiceover\"\n    },\n    \"product\": {\n      \"brand\": \"Brand name\",\n      \"model\": \"Product model or name\",\n      \"action\": \"description of product transformation or assembly\"\n    }\n  },\n  \"motion\": {\n    \"type\": \"e.g. transformation, explosion, vortex\",\n    \"details\": \"step-by-step visual flow of how elements move or evolve\"\n  },\n  \"VFX\": {\n    \"transformation\": \"optional \u2013 describe style (neon trails, motion blur...)\",\n    \"impact\": \"optional \u2013 e.g. shockwave, glow, distortion\",\n    \"particles\": \"optional \u2013 embers, sparks, thread strands...\",\n    \"environment\": \"optional \u2013 VFX affecting the scene (ripples, wind...)\"\n  },\n  \"audio\": {\n    \"music\": \"optional \u2013 cinematic score, trap beat, ambient tone\",\n    \"sfx\": [\n      \"list of sound effects (zip, pop, woosh...)\"\n    ],\n    \"ambience\": \"optional \u2013 background soundscape (traffic, wind...)\",\n    \"voiceover\": {\n      \"delivery\": \"tone and style (confident, whisper, deep...)\",\n      \"line\": \"text spoken if applicable\"\n    }\n  },\n  \"ending\": \"Final shot description \u2013 what is seen or felt at the end (freeze frame, logo pulse, glow...)\",\n  \"text\": \"none | overlay | tagline | logo pulse at end only\",\n  \"format\": \"16:9 | 4k | vertical\",\n  \"keywords\": [\n    \"brand\",\n    \"scene style\",\n    \"motion type\",\n    \"camera style\",\n    \"sound mood\",\n    \"target theme\"\n  ]\n}\n"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "8d368aed-2dd7-47c2-90e8-bd9d8163ab4a",
      "name": "AI Agent: Generate Video Script",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1008,
        640
      ],
      "parameters": {
        "text": "=Create a UGC-style video prompt using both the reference image and the user description.  \n\n**Inputs**  \n- User description (optional):  \n  `{{ $('Telegram Trigger: Receive Video Idea').item.json.message.caption }}`  \n- Reference image analysis (stay strictly faithful to what\u2019s visible):  \n  `{{ $('OpenAI Vision: Analyze Reference Image').item.json.content }}`  \n\n**Rules**  \n- Keep the style casual, authentic, and realistic. Avoid studio-like or cinematic language.  \n- Default model: `veo3.1` (unless otherwise specified).  \n- Output only **one JSON object** with the key: `video_prompt`.  \n",
        "options": {
          "systemMessage": "=system_prompt:\n  ## SYSTEM PROMPT: Structured Video Ad Prompt Generator\n  A - Ask:\n    Generate a structured video ad prompt for cinematic generation, strictly based on the master schema provided in: {{ $json.json_master }}.\n    The final result must be a JSON object with exactly 3 top-level keys: `prompt`, `caption`, `title` and `hashtags`.\n\n  G - Guidance:\n    role: Creative Director\n    output_count: 1\n    character_limit: None\n    constraints:\n      - The output must be valid JSON.\n      - The `prompt` field must contain a **single-line JSON string** that follows the exact structure of {{ $json.json_master }} with all fields preserved.\n      - The `hashtags` field must contain array of 8-10 tags.\n      - The `caption` field should contain a short, descriptive and unique title (max 15 words).\n      - The `title` field should contain a short title.\n      - Do not include any explanations, markdown, or extra text \u2014 only the JSON object.\n      - Escape all inner quotes in the `prompt` string so it is valid as a stringified JSON inside another JSON.\n    tool_usage:\n      - Ensure consistent alignment across all fields (camera, lighting, motion, etc.).\n      - Maintain full structure even for optional fields (use \"none\", \"\", or [] as needed).\n\n  N - Notation:\n    format: JSON\n    expected_output:\n      {\n        \"prompt\": \"{...stringified JSON of the full prompt...}\",\n        \"caption\": \"A unique short descriptive\",\n        \"title\": \"A unique short title\",\n        \"hashtags\": \"tags\"\n      }\n\n    Return JSON with: prompt (150-200 word cinematic Veo 3.1 description), caption (50-100 word social media text with emojis), hashtags (array of 8-10 tags)"
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 2
    },
    {
      "id": "508e2f17-37eb-455d-b69a-19e773705e75",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "disabled": true,
      "position": [
        720,
        544
      ],
      "parameters": {
        "color": 7,
        "width": 1852,
        "height": 428,
        "content": "# \ud83d\udcd1 STEP 2 \u2014 Generate Video with VEO3.1"
      },
      "typeVersion": 1
    },
    {
      "id": "3d5fe2a9-6fee-4f29-a7b0-ff1628d1d96a",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        720,
        96
      ],
      "parameters": {
        "color": 7,
        "width": 1856,
        "height": 432,
        "content": "# \ud83d\udcd1 STEP 1 \u2014 Create Image with NanoBanana 2 PRO\n"
      },
      "typeVersion": 1
    },
    {
      "id": "3028553a-e742-49fd-b68c-6f5a9c6e0f9e",
      "name": "Set: Bot Token (Placeholder)",
      "type": "n8n-nodes-base.set",
      "position": [
        992,
        192
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "af62651a-3fc8-419d-908b-6514f6f4bcb3",
              "name": "YOUR_BOT_TOKEN",
              "type": "string",
              "value": "YOUR_BOT_TOKEN"
            },
            {
              "id": "588b2c82-50af-41f1-bce2-0f7e627162b0",
              "name": "fal_api_key",
              "type": "string",
              "value": "YOUR_fal_api_key"
            },
            {
              "id": "bdb28513-38da-4a61-bffd-aa0f8a165579",
              "name": "CAPTION",
              "type": "string",
              "value": "={{ $('Telegram Trigger: Receive Video Idea').item.json.message.caption }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "ac849dab-7a31-4eed-82c6-210f312c53d0",
      "name": "Telegram API: Get File URL",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1216,
        192
      ],
      "parameters": {
        "url": "=https://api.telegram.org/bot{{ $json.YOUR_BOT_TOKEN }}/getFile?file_id={{ $('Telegram Trigger: Receive Video Idea').item.json.message.photo[ $('Telegram Trigger: Receive Video Idea').item.json.message.photo.length - 1].file_id }}",
        "options": {}
      },
      "typeVersion": 4.2
    },
    {
      "id": "0fb7dee2-9d26-4488-b123-a68d374da7e2",
      "name": "OpenAI Vision: Analyze Reference Image",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        1424,
        192
      ],
      "parameters": {
        "text": "=You are an image analysis assistant.\n\nYour task is to analyze the given image and output results **only in YAML format**. Do not add explanations, comments, or extra text outside YAML.\n\nRules:\n\n- If the image depicts a **product**, return:\n    \n    ```yaml\n    brand_name: (brand if visible or inferable)\n    color_scheme:\n      - hex: (hex code of each prominent color)\n        name: (descriptive name of the color)\n    font_style: (serif/sans-serif, bold/thin, etc.)\n    visual_description: (1\u20132 sentences summarizing what is seen, ignoring the background)\n    \n    ```\n    \n- If the image depicts a **character**, return:\n    \n    ```yaml\n    character_name: (name if visible or inferable, else \"unknown\")\n    color_scheme:\n      - hex: (hex code of each prominent color on the character)\n        name: (descriptive name of the color)\n    outfit_style: (clothing style, accessories, or notable features)\n    visual_description: (1\u20132 sentences summarizing what the character looks like, ignoring the background)\n    \n    ```\n    \n- If the image depicts **both**, return **both sections** in YAML.\n\nOnly output valid YAML. No explanations.",
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "chatgpt-4o-latest",
          "cachedResultName": "CHATGPT-4O-LATEST"
        },
        "options": {},
        "resource": "image",
        "imageUrls": "=https://api.telegram.org/file/bot{{ $('Set: Bot Token (Placeholder)').first().json.YOUR_BOT_TOKEN }}/{{ $json.result.file_path }}",
        "operation": "analyze"
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.8
    },
    {
      "id": "b197982b-4a3d-4a9a-9a04-06ad04f8ef9b",
      "name": "LLM: Structured Output Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        1824,
        384
      ],
      "parameters": {
        "jsonSchemaExample": "{\n\t\"image_prompt\": \"string\"\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "03caf7c5-c03e-4ef7-b104-e7e5a23d0e02",
      "name": "LLM: OpenAI Chat",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        1600,
        384
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "eaa418ce-bbcd-42d0-ac2a-f7dcda99fdb1",
      "name": "Generate Image Prompt",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1648,
        192
      ],
      "parameters": {
        "text": "=Your task is to create an image prompt following the system guidelines.  \nEnsure that the reference image is represented as **accurately as possible**, including all text elements.  \n\nUse the following inputs:  \n\n- **User\u2019s description:**  \n{{ $('Set: Bot Token (Placeholder)').first().json.CAPTION }}\n\n- **Reference image description:**  \n{{ $json.content }}\n",
        "options": {
          "systemMessage": "=ROLE: UGC Image Prompt Builder  \n\nGOAL:  \nGenerate one concise, natural, and realistic image prompt (\u2264120 words) from a given product or reference image. The prompt must simulate authentic UGC (user-generated content) photography.  \n\nRULES:  \n- Always output **one JSON object only** with the key:  \n  - `image_prompt`: (string with full description)  \n- Do **not** add commentary, metadata, or extra keys. JSON only.  \n\nSTYLE GUIDELINES:  \n- Tone: casual, unstaged, lifelike, handheld snapshot.  \n- Camera cues: include at least 2\u20133 (e.g., phone snapshot, handheld framing, off-center composition, natural indoor light, soft shadows, slight motion blur, auto exposure, unpolished look, mild grain).  \n- Realism: embrace imperfections (wrinkles, stray hairs, skin texture, clutter, smudges).  \n- Packaging/Text: preserve exactly as visible. Never invent claims, numbers, or badges.  \n- Diversity: if people appear but are unspecified, vary gender/ethnicity naturally; default age range = 21\u201338.  \n- Setting: default to real-world everyday spaces (home, street, store, gym, office).  \n\nSAFETY:  \n- No copyrighted character names.  \n- No dialogue or scripts. Only describe scenes.  \n\nOUTPUT CONTRACT:  \n- JSON only, no prose outside.  \n- Max 120 words in `image_prompt`.  \n- Must cover: subject, action, mood, setting, style/camera, colors, and text accuracy.  \n\nCHECKLIST BEFORE OUTPUT:  \n- Natural handheld tone?  \n- At least 2 camera cues included?  \n- Product text preserved exactly?  \n- Only JSON returned?  \n\n---  \n\n### Example  \n\nGood Example :  \n```json\n{ \"image_prompt\": \"a young adult casually holding a skincare tube near a bathroom mirror; action: dabs small amount on the back of the hand; mood: easy morning; setting: small apartment bathroom with towel on rack and toothbrush cup; style/camera: phone snapshot, handheld framing, off-center composition, natural window light, slight motion blur, mild grain; colors: soft whites and mint label; text accuracy: keep every word on the tube exactly as visible, no added claims\" }\n"
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 2.2
    },
    {
      "id": "04938906-9aa0-49cb-8073-52030f2c7f91",
      "name": "NanoBanana: Create Image",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1984,
        192
      ],
      "parameters": {
        "url": "https://queue.fal.run/fal-ai/nano-banana-pro/edit",
        "method": "POST",
        "options": {
          "response": {
            "response": {
              "responseFormat": "json"
            }
          }
        },
        "jsonBody": "={\n  \"prompt\": \"{{ $json.output.image_prompt.replace(/\\\"/g, '\\\\\\\"').replace(/\\n/g, '\\\\n') }}\",\n  \"image_urls\": [\n     \"https://api.telegram.org/file/bot{{ $('Set: Bot Token (Placeholder)').first().json.YOUR_BOT_TOKEN }}/{{ $('Telegram API: Get File URL').first().json.result.file_path }}\"\n  ],\n  \"resolution\": \"1K\",\n  \"aspect_ratio\": \"9:16\",\n  \"output_format\": \"png\"\n}\n",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            },
            {
              "name": "Authorization",
              "value": "={{ 'Key ' + $('Set: Bot Token (Placeholder)').first().json.fal_api_key }}"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "526eedfe-fbbd-4aff-bba1-9fbb990a74e4",
      "name": "Wait for Image Edit",
      "type": "n8n-nodes-base.wait",
      "position": [
        2192,
        192
      ],
      "parameters": {
        "amount": 2
      },
      "typeVersion": 1.1
    },
    {
      "id": "51985580-f325-49d3-bfff-83b0de4db6ca",
      "name": "Download Edited Image",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2400,
        192
      ],
      "parameters": {
        "url": "={{ $json.response_url }}",
        "options": {}
      },
      "typeVersion": 4.2
    },
    {
      "id": "4534025f-dd17-4225-aaa6-b0343dca4864",
      "name": "Parse GPT Response",
      "type": "n8n-nodes-base.code",
      "position": [
        1360,
        640
      ],
      "parameters": {
        "jsCode": "// Parse responses into { title, prompt, caption, hashtags[], hashtags_string }\nreturn $input.all().map(item => {\n  const data = item.json || {};\n\n  let title = \"\";\n  let prompt = \"\";\n  let caption = \"\";\n  let hashtagsArr = [];\n\n  // 1) NOUVEAU FORMAT : { output: { title, prompt, caption, hashtags } }\n  if (data.output) {\n    const o = data.output || {};\n    title = o.title ?? \"\";\n    prompt = o.prompt ?? \"\";\n    caption = o.caption ?? \"\";\n\n    const rawHashtags = o.hashtags ?? [];\n    if (Array.isArray(rawHashtags)) {\n      hashtagsArr = rawHashtags;\n    } else if (typeof rawHashtags === \"string\") {\n      try {\n        const parsedTags = JSON.parse(rawHashtags);\n        if (Array.isArray(parsedTags)) {\n          hashtagsArr = parsedTags;\n        } else {\n          hashtagsArr = rawHashtags.split(/[,\\s]+/).filter(Boolean);\n        }\n      } catch {\n        hashtagsArr = rawHashtags.split(/[,\\s]+/).filter(Boolean);\n      }\n    }\n  }\n\n  // 2) ANCIEN FORMAT OpenAI (fallback)\n  if (!title && !prompt && !caption && hashtagsArr.length === 0) {\n    let content =\n      data?.choices?.[0]?.message?.content ??\n      data?.message?.content ??\n      data?.content ??\n      null;\n\n    if (content && typeof content === \"object\") {\n      title = content.title ?? \"\";\n      prompt = content.prompt ?? \"\";\n      caption = content.caption ?? \"\";\n\n      if (Array.isArray(content.hashtags)) {\n        hashtagsArr = content.hashtags;\n      } else if (typeof content.hashtags === \"string\") {\n        hashtagsArr = content.hashtags.split(/[,\\s]+/).filter(Boolean);\n      }\n    }\n    else if (typeof content === \"string\" && content.trim()) {\n      try {\n        const parsed = JSON.parse(content);\n        title = parsed.title ?? \"\";\n        prompt = parsed.prompt ?? \"\";\n        caption = parsed.caption ?? \"\";\n\n        if (Array.isArray(parsed.hashtags)) {\n          hashtagsArr = parsed.hashtags;\n        } else if (typeof parsed.hashtags === \"string\") {\n          hashtagsArr = parsed.hashtags.split(/[,\\s]+/).filter(Boolean);\n        }\n      } catch {\n        title = \"\";\n        prompt = \"\";\n        caption = \"\";\n        hashtagsArr = [];\n      }\n    }\n  }\n\n  // 3) Normalisation des hashtags\n  const norm = Array.from(\n    new Set(\n      (hashtagsArr || [])\n        .map(h => (h ?? \"\").toString().trim())\n        .filter(Boolean)\n        .map(h => (h.startsWith(\"#\") ? h : `#${h}`))\n    )\n  );\n\n  const hashtags_string = norm.join(\" \");\n\n  return {\n    json: {\n      title,\n      prompt,\n      caption,\n      hashtags: norm,\n      hashtags_string\n    }\n  };\n});\n"
      },
      "typeVersion": 2
    },
    {
      "id": "1a6f333e-8aa0-4285-bdfb-64b7ca0b6267",
      "name": "Optimize Prompt for Veo",
      "type": "n8n-nodes-base.set",
      "position": [
        1568,
        640
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "id-1",
              "name": "veo_prompt",
              "type": "string",
              "value": "={{ $json.prompt }} consistent character throughout, photorealistic quality, professional cinematography, 8 seconds duration, 9:16 aspect ratio, 24fps"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "cfc41241-f73d-4bfc-aa3a-e7d65281bf82",
      "name": "Download Video",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2400,
        640
      ],
      "parameters": {
        "url": "={{ $json.video.url }}",
        "options": {
          "response": {
            "response": {
              "responseFormat": "file"
            }
          }
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "ae4420cd-7088-45a8-942d-c7b96455e685",
      "name": "Prepare Veo Request Body",
      "type": "n8n-nodes-base.code",
      "position": [
        1776,
        640
      ],
      "parameters": {
        "jsCode": "const prompt = $input.item.json.veo_prompt || $input.item.json.prompt;\n\n// Nouvelle source d'image : sortie de \"Download Edited Image\"\nconst imageUrl = $('Download Edited Image').first().json.images[0].url;\n\nif (!prompt || prompt.length < 10) {\n  throw new Error('Prompt required');\n}\n\nif (!imageUrl || typeof imageUrl !== 'string' || !imageUrl.startsWith('http')) {\n  throw new Error('A valid image URL from Download Edited Image is required');\n}\n\n// VEO attend un tableau d'URLs, m\u00eame si on n'en a qu'une\nconst imageUrls = [imageUrl];\n\nreturn {\n  json: {\n    veo_request_body: {\n      prompt: prompt,\n      image_urls: imageUrls,\n      duration: 8,\n      aspect_ratio: \"9:16\"\n    },\n    ...($input.item.json)\n  }\n};\n"
      },
      "typeVersion": 2
    },
    {
      "id": "50dedf01-6b48-464b-ab9f-3608e499f3cc",
      "name": "Veo Generation",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1984,
        640
      ],
      "parameters": {
        "url": "https://fal.run/fal-ai/veo3.1/reference-to-video",
        "method": "POST",
        "options": {
          "timeout": 600000,
          "response": {
            "response": {
              "responseFormat": "json"
            }
          }
        },
        "jsonBody": "={{ JSON.stringify($json.veo_request_body) }}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "={{ 'Key ' + $('Set: Bot Token (Placeholder)').first().json.fal_api_key }}"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "c135569a-c630-4b25-8f6e-2f42b00fb58e",
      "name": "Wait",
      "type": "n8n-nodes-base.wait",
      "position": [
        2192,
        640
      ],
      "parameters": {
        "amount": 2
      },
      "typeVersion": 1.1
    },
    {
      "id": "2a1bc1b1-57d6-483c-a51c-a97675d463c8",
      "name": "Send Video to Telegram",
      "type": "n8n-nodes-base.telegram",
      "position": [
        800,
        1152
      ],
      "parameters": {
        "chatId": "={{ $('Telegram Trigger: Receive Video Idea').first().json.message.chat.id }}",
        "operation": "sendVideo",
        "binaryData": true,
        "additionalFields": {
          "caption": "=Your video is ready! \ud83c\udfa5  {{ $json.video.url }}"
        }
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "6dd2b073-71c5-4d5b-82b2-0383a7e680b7",
      "name": "Step 5 - Publishing",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        720,
        992
      ],
      "parameters": {
        "color": 5,
        "width": 1852,
        "height": 404,
        "content": "# \ud83d\udcd1 STEP 3  \u2014  Publish with Blotato"
      },
      "typeVersion": 1
    },
    {
      "id": "a984be16-6697-4cfc-bb1c-a8f7463be5a1",
      "name": "Upload Video to BLOTATO",
      "type": "@blotato/n8n-nodes-blotato.blotato",
      "position": [
        1136,
        1152
      ],
      "parameters": {
        "mediaUrl": "={{ $('Download Video').item.json.video.url }}",
        "resource": "media"
      },
      "credentials": {
        "blotatoApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "c3b8258b-5ee7-47fa-9d7e-4e3c59928f9e",
      "name": "Youtube",
      "type": "@blotato/n8n-nodes-blotato.blotato",
      "position": [
        1872,
        1216
      ],
      "parameters": {
        "options": {},
        "platform": "youtube",
        "accountId": {
          "__rl": true,
          "mode": "list",
          "value": "8047",
          "cachedResultUrl": "https://backend.blotato.com/v2/accounts/8047",
          "cachedResultName": "DR FIRASS (Dr. Firas)"
        },
        "postContentText": "={{ $('Parse GPT Response').first().json.caption }}",
        "postContentMediaUrls": "={{ $json.url }}",
        "postCreateYoutubeOptionTitle": "={{ $('Parse GPT Response').first().json.title }}",
        "postCreateYoutubeOptionPrivacyStatus": "private",
        "postCreateYoutubeOptionShouldNotifySubscribers": false
      },
      "credentials": {
        "blotatoApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "981fa66f-f01c-418e-8b02-24865cfb341f",
      "name": "Tiktok",
      "type": "@blotato/n8n-nodes-blotato.blotato",
      "position": [
        1552,
        1056
      ],
      "parameters": {
        "options": {},
        "platform": "tiktok",
        "accountId": {
          "__rl": true,
          "mode": "list",
          "value": "2079",
          "cachedResultUrl": "https://backend.blotato.com/v2/accounts/2079",
          "cachedResultName": "elitecybzcs"
        },
        "postContentText": "={{ $('Parse GPT Response').first().json.caption }}",
        "postContentMediaUrls": "={{ $json.url }}"
      },
      "credentials": {
        "blotatoApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "fa93e28f-6e93-479f-95f3-8d949090fc1c",
      "name": "Linkedin",
      "type": "@blotato/n8n-nodes-blotato.blotato",
      "position": [
        1712,
        1056
      ],
      "parameters": {
        "options": {},
        "platform": "linkedin",
        "accountId": {
          "__rl": true,
          "mode": "list",
          "value": "1446",
          "cachedResultUrl": "https://backend.blotato.com/v2/accounts/1446",
          "cachedResultName": "Samuel Amalric"
        },
        "postContentText": "={{ $('Parse GPT Response').first().json.caption }}",
        "postContentMediaUrls": "={{ $json.url }}"
      },
      "credentials": {
        "blotatoApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "77026e85-e28f-44ff-9ad1-2191565bd8a4",
      "name": "Facebook",
      "type": "@blotato/n8n-nodes-blotato.blotato",
      "position": [
        1872,
        1056
      ],
      "parameters": {
        "options": {},
        "platform": "facebook",
        "accountId": {
          "__rl": true,
          "mode": "list",
          "value": "1759",
          "cachedResultUrl": "https://backend.blotato.com/v2/accounts/1759",
          "cachedResultName": "Firass Ben"
        },
        "facebookPageId": {
          "__rl": true,
          "mode": "list",
          "value": "101603614680195",
          "cachedResultUrl": "https://backend.blotato.com/v2/accounts/1759/subaccounts/101603614680195",
          "cachedResultName": "Dr. Firas"
        },
        "postContentText": "={{ $('Parse GPT Response').first().json.caption }}",
        "postContentMediaUrls": "={{ $json.url }}"
      },
      "credentials": {
        "blotatoApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "87ce0af6-a9e9-47e2-a958-824cb8c52f07",
      "name": "Instagram",
      "type": "@blotato/n8n-nodes-blotato.blotato",
      "position": [
        1552,
        1216
      ],
      "parameters": {
        "options": {},
        "accountId": {
          "__rl": true,
          "mode": "list",
          "value": "1687",
          "cachedResultUrl": "https://backend.blotato.com/v2/accounts/1687",
          "cachedResultName": "acces.a.vie"
        },
        "postContentText": "={{ $('Parse GPT Response').first().json.caption }}",
        "postContentMediaUrls": "={{ $json.url }}"
      },
      "credentials": {
        "blotatoApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "2f7980a6-5d3f-4d2b-a565-4c840529d8c1",
      "name": "Twitter (X)",
      "type": "@blotato/n8n-nodes-blotato.blotato",
      "position": [
        1712,
        1216
      ],
      "parameters": {
        "options": {},
        "platform": "twitter",
        "accountId": {
          "__rl": true,
          "mode": "list",
          "value": "1289",
          "cachedResultUrl": "https://backend.blotato.com/v2/accounts/1289",
          "cachedResultName": "Docteur_Firas"
        },
        "postContentText": "={{ $('Parse GPT Response').first().json.caption }}",
        "postContentMediaUrls": "={{ $json.url }}"
      },
      "credentials": {
        "blotatoApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "eaa3e024-0eef-4a71-ae0b-25fe1cc27a1c",
      "name": "Merge1",
      "type": "n8n-nodes-base.merge",
      "position": [
        2144,
        1072
      ],
      "parameters": {
        "mode": "chooseBranch",
        "numberInputs": 6
      },
      "typeVersion": 3.2
    },
    {
      "id": "4889de2f-81e3-49e2-a921-739aec5be20e",
      "name": "Send a text message",
      "type": "n8n-nodes-base.telegram",
      "position": [
        2368,
        1136
      ],
      "parameters": {
        "text": "Published",
        "chatId": "={{ $('Telegram Trigger: Receive Video Idea').first().json.message.chat.id }}",
        "additionalFields": {}
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "3e6b4da3-2e64-49f4-8e76-97753b87b81b",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        48,
        96
      ],
      "parameters": {
        "width": 652,
        "height": 1300,
        "content": "# \ud83d\ude80 AI Viral Video Workflow \u2014 NanoBanana 2 PRO \u00d7 VEO3.1 \u00d7 Blotato (By Dr. Firas)\n\n[![AI Voice Agent Preview](https://www.dr-firas.com/nanobanana2.png)](https://youtu.be/nlwpbXQqNQ4)\n\n##  \ud83d\udcd8 Documentation  \nAccess detailed setup instructions, API config, platform connection guides, and workflow customization tips:\n\n\ud83d\udcce [Open the full documentation on Notion](https://automatisation.notion.site/NonoBanan-PRO-2-2b53d6550fd981a5acbecf7cf50aeb3c?source=copy_link)\n\nThis workflow converts a simple Telegram message into a **ready-to-publish AI viral video**, fully automated.\n\n## \ud83d\udd25 What this workflow does\n### 1\ufe0f\u20e3 Image Creation (NanoBanana 2 PRO)\n- User sends on Telegram:\n  - A reference image  \n  - A short text idea  \n### 2\ufe0f\u20e3 Video Generation (VEO3.1)\n- An AI Agent builds a structured video prompt  \n- Optimizes it for **VEO3.1**  \n- Generates a vertical 9:16 video (8 seconds)  \n- Sends the final video to Telegram\n### 3\ufe0f\u20e3 Multi-Platform Publishing (Blotato)\n- Uploads the video to Blotato  \n- Auto-publishes to\n\n## \u2699\ufe0f Requirements\n1. \u2705 **Create a [Blotato](https://blotato.com/?ref=firas) account** (Pro plan required for API access)  \n2. \ud83d\udd11 **Generate your Blotato API Key** via: `Settings > API > Generate API Key`  \n3. \ud83d\udce6 **Enable \u201cVerified Community Nodes\u201d** in the n8n admin settings  \n4. \ud83e\udde9 **Install the Blotato** verified community node in n8n  \n5. \ud83d\udee0 **Create a Blotato API credential** inside your n8n credentials tab  "
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "6eeaa654-b434-47fa-b135-e915b506d7c7",
  "connections": {
    "Wait": {
      "main": [
        [
          {
            "node": "Download Video",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Think": {
      "ai_tool": [
        [
          {
            "node": "AI Agent: Generate Video Script",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Merge1": {
      "main": [
        [
          {
            "node": "Send a text message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Tiktok": {
      "main": [
        [
          {
            "node": "Merge1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Youtube": {
      "main": [
        [
          {
            "node": "Merge1",
            "type": "main",
            "index": 5
          }
        ]
      ]
    },
    "Facebook": {
      "main": [
        [
          {
            "node": "Merge1",
            "type": "main",
            "index": 2
          }
        ]
      ]
    },
    "Linkedin": {
      "main": [
        [
          {
            "node": "Merge1",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Instagram": {
      "main": [
        [
          {
            "node": "Merge1",
            "type": "main",
            "index": 3
          }
        ]
      ]
    },
    "Twitter (X)": {
      "main": [
        [
          {
            "node": "Merge1",
            "type": "main",
            "index": 4
          }
        ]
      ]
    },
    "Download Video": {
      "main": [
        [
          {
            "node": "Send Video to Telegram",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Veo Generation": {
      "main": [
        [
          {
            "node": "Wait",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "LLM: OpenAI Chat": {
      "ai_languageModel": [
        [
          {
            "node": "Generate Image Prompt",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent: Generate Video Script",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Set Master Prompt": {
      "main": [
        [
          {
            "node": "AI Agent: Generate Video Script",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse GPT Response": {
      "main": [
        [
          {
            "node": "Optimize Prompt for Veo",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait for Image Edit": {
      "main": [
        [
          {
            "node": "Download Edited Image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download Edited Image": {
      "main": [
        [
          {
            "node": "Set Master Prompt",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Image Prompt": {
      "main": [
        [
          {
            "node": "NanoBanana: Create Image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Video to Telegram": {
      "main": [
        [
          {
            "node": "Upload Video to BLOTATO",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Optimize Prompt for Veo": {
      "main": [
        [
          {
            "node": "Prepare Veo Request Body",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upload Video to BLOTATO": {
      "main": [
        [
          {
            "node": "Tiktok",
            "type": "main",
            "index": 0
          },
          {
            "node": "Linkedin",
            "type": "main",
            "index": 0
          },
          {
            "node": "Facebook",
            "type": "main",
            "index": 0
          },
          {
            "node": "Instagram",
            "type": "main",
            "index": 0
          },
          {
            "node": "Twitter (X)",
            "type": "main",
            "index": 0
          },
          {
            "node": "Youtube",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "NanoBanana: Create Image": {
      "main": [
        [
          {
            "node": "Wait for Image Edit",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Veo Request Body": {
      "main": [
        [
          {
            "node": "Veo Generation",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "AI Agent: Generate Video Script",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Telegram API: Get File URL": {
      "main": [
        [
          {
            "node": "OpenAI Vision: Analyze Reference Image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set: Bot Token (Placeholder)": {
      "main": [
        [
          {
            "node": "Telegram API: Get File URL",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "LLM: Structured Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "Generate Image Prompt",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent: Generate Video Script": {
      "main": [
        [
          {
            "node": "Parse GPT Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Telegram Trigger: Receive Video Idea": {
      "main": [
        [
          {
            "node": "Set: Bot Token (Placeholder)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Vision: Analyze Reference Image": {
      "main": [
        [
          {
            "node": "Generate Image Prompt",
            "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.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

πŸ’₯ Create AI Viral Videos using NanoBanana 2 PRO & VEO3.1 and Publish via Blotato -vide. Uses lmChatOpenAi, toolThink, outputParserStructured, telegramTrigger. Event-driven trigger; 35 nodes.

Source: https://github.com/zengfr/n8n-workflow-all-templates/blob/6a3e60251e39ea8c87e061d82f52633e5d0debe6/n8n-workflow-all-templates/00/01/12/11204_Create_AI_Viral_Videos_using_NanoBanana_2_PRO___VEO3.1_and_Publish_via_Blotato.json β€” 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

🎯 Create viral TikToks, Shorts, Reels, podcasts, and ASMR videos in minutes β€” all on autopilot.

OpenAI, HTTP Request, Form Trigger +7
AI & RAG

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.

@Blotato/N8N Nodes Blotato, Google Sheets, OpenAI Chat +9
AI & RAG

RAG CHATBOT Main. Uses telegram, telegramTrigger, lmChatOpenAi, n8n-nodes-mcp. Event-driven trigger; 87 nodes.

Telegram, Telegram Trigger, OpenAI Chat +8
AI & RAG

Creators, marketers, and brands that want to turn a single product photo into premium motion clips, then optionally publish to Instagram/TikTok/YouTube via LATE. No editing skills required.

Telegram, Agent Tool, Telegram Trigger +5
AI & RAG

Product to Social Video (xCodeWraith Edition). Uses telegram, agentTool, telegramTrigger, httpRequest. Event-driven trigger; 83 nodes.

Telegram, Agent Tool, Telegram Trigger +5