{
  "id": "BaYb30Mgg3ILNtfX",
  "name": "# Edit Video with Gemini Omni Flash and upload to TikTok",
  "tags": [],
  "nodes": [
    {
      "id": "78627d87-ddb1-490b-85e4-b3ecc5d39bca",
      "name": "Get status",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        480,
        304
      ],
      "parameters": {
        "url": "=https://queue.fal.run/google/gemini-omni-flash/requests/{{ $('Create Video').item.json.request_id }}/status ",
        "options": {},
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "5ccdb023-16d4-4fb3-8215-43fca0e8d59b",
      "name": "Wait 60 sec.",
      "type": "n8n-nodes-base.wait",
      "position": [
        256,
        384
      ],
      "parameters": {
        "amount": 60
      },
      "typeVersion": 1.1
    },
    {
      "id": "65905c27-017f-45fd-9dfd-5b7adb70ab2e",
      "name": "Completed?",
      "type": "n8n-nodes-base.if",
      "position": [
        704,
        384
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "383d112e-2cc6-4dd4-8985-f09ce0bd1781",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.status }}",
              "rightValue": "COMPLETED"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "30ae84d7-b8f0-4d37-9750-af066e262077",
      "name": "Create Video",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        32,
        384
      ],
      "parameters": {
        "url": "https://queue.fal.run/google/gemini-omni-flash/edit",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n     \"prompt\": \"{{ $json.prompt }}\",\n     \"video_url\": \"{{ $json.video_url }}\"\n   }",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "ec5a69fa-8ff5-466d-86ac-5289c44641e6",
      "name": "Get Url Video",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        928,
        384
      ],
      "parameters": {
        "url": "=https://queue.fal.run/google/gemini-omni-flash/requests/{{ $json.request_id }}",
        "options": {},
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "b1532c22-c0e0-4114-b594-31ead9783c73",
      "name": "Get File Video",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1504,
        384
      ],
      "parameters": {
        "url": "={{ $('Get Url Video').item.json.video.url }}",
        "options": {}
      },
      "typeVersion": 4.2
    },
    {
      "id": "c9c3f0c5-666f-41af-aca3-0a839cc50530",
      "name": "HTTP Request",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1728,
        384
      ],
      "parameters": {
        "url": "https://api.upload-post.com/api/upload",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "contentType": "multipart-form-data",
        "authentication": "genericCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "title",
              "value": "={{ $('Generate title').item.json.message.content }}"
            },
            {
              "name": "user",
              "value": "YOUR_USERNAME"
            },
            {
              "name": "platform[]",
              "value": "tiktok"
            },
            {
              "name": "video",
              "parameterType": "formBinaryData",
              "inputDataFieldName": "data"
            }
          ]
        },
        "genericAuthType": "httpHeaderAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "53ac9c3a-dcc8-404f-8c09-4c23cc0e5af8",
      "name": "Generate title",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        1152,
        384
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-5",
          "cachedResultName": "GPT-5"
        },
        "options": {},
        "messages": {
          "values": [
            {
              "content": "=Input: {{ $('Webhook').item.json.prompt }}"
            },
            {
              "role": "system",
              "content": "You are a Video SEO expert specialized in creating engaging and optimized titles.\n\nYour task is to generate an effective title for a YouTube video based on the user's video description.\n\nGUIDELINES:\n- Maximum 60 characters to avoid truncation\n- Use relevant keywords for SEO\n- Make the title catchy and clickable\n- Avoid excessive or misleading clickbait\n- Consider the target audience of the content\n- Use numbers, questions, or power words when appropriate\n- IMPORTANT: Generate the title in the same language as the input description\n\nOUTPUT FORMAT:\nProvide only the title, without additional explanations.\n\nEXAMPLE:\nInput: \"Tutorial video on how to cook perfect pasta carbonara\"\nOutput: \"PERFECT Carbonara in 10 Minutes - Chef's Secrets\""
            }
          ]
        }
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.8
    },
    {
      "id": "106ca95c-3460-4323-8985-c4e25d98b4b1",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -192,
        384
      ],
      "parameters": {
        "path": "f3a35424-8d70-46e4-9f50-6286c6f66edc",
        "options": {},
        "responseMode": "responseNode"
      },
      "typeVersion": 2.1
    },
    {
      "id": "f3dce797-8aed-4f2a-9555-3123004b67cb",
      "name": "Respond to Webhook",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        1952,
        384
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 1.5
    },
    {
      "id": "1cf57e4e-2886-4030-ab36-228f514d03ea",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -272,
        -704
      ],
      "parameters": {
        "width": 1120,
        "height": 816,
        "content": "# Edit Video with Gemini Omni Flash and upload to TikTok\n\n## How It Works\n\n1. A webhook receives a video editing request and starts the workflow.\n2. The workflow submits the request to Gemini Omni Flash to edit the video and waits for the rendering process to complete.\n3. It continuously checks the job status until the video has been successfully rendered.\n4. Once the job is complete, the workflow retrieves the generated video URL, creates an SEO-friendly title using OpenAI, and downloads the final video.\n5. Finally, the workflow uploads the processed video to Upload-Post and returns the upload response to the original caller.\n\n## Setup Steps\n\n- [ ] Configure the **Webhook** trigger path and ensure the incoming payload includes both the `video_url` and `prompt` fields.\n- [ ] Configure your **Fal API** credentials for the HTTP Request nodes used to submit the editing job, check the rendering status, and retrieve the final video information.\n- [ ] Verify that the **Post Edit Job to Gemini** node contains the correct editing prompt and the source video URL.\n- [ ] Configure your **OpenAI** credentials for the **Generate Video Title** node.\n- [ ] Ensure the **Download Video File** node can access the signed URL returned by the Fal API.\n- [ ] Configure your **Upload-Post API** credentials in the **Upload Video to Upload-Post** node.\n\nCreate an [Upload-Post account for FREE](https://www.upload-post.com/?linkId=lp_144414&sourceId=n3witalia&tenantId=upload-post-app) and obtain your API credentials visit:\n\n## Customization\n\nYou can easily customize this workflow by:\n\n- Changing the polling interval in the **Wait 60 Seconds** node.\n- Modifying the prompt used by the **Generate Video Title** node.\n- Updating the default upload parameters (user, platforms, metadata, etc.) sent to Upload-Post.\n- Replacing the final upload destination with another storage service or API if required."
      },
      "typeVersion": 1
    },
    {
      "id": "332e45c6-37b9-420b-b0bb-4c7e1d951e25",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -272,
        144
      ],
      "parameters": {
        "color": 7,
        "width": 464,
        "height": 480,
        "content": "## Receive Edit Request\n\nThe webhook receives the video editing request and starts the workflow by sending the provided video and prompt to Gemini Omni Flash for processing."
      },
      "typeVersion": 1
    },
    {
      "id": "86ca73e5-3270-43b8-aa3d-eb8dce953119",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        224,
        144
      ],
      "parameters": {
        "color": 7,
        "width": 848,
        "height": 480,
        "content": "## Monitor Rendering Status\n\nThe workflow periodically checks the status of the rendering job on Fal until the video generation is complete. If the job is still running, it waits before checking again."
      },
      "typeVersion": 1
    },
    {
      "id": "90481a0b-841f-4b81-a360-84c27df1e5ea",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        880,
        -672
      ],
      "parameters": {
        "color": 7,
        "width": 736,
        "height": 784,
        "content": "## MY NEW YOUTUBE CHANNEL\n\ud83d\udc49 [Subscribe to my new **YouTube channel**](https://youtube.com/@n3witalia). Here I\u2019ll share videos and Shorts with practical tutorials and **FREE templates for n8n**.\n\n[![image](https://n3wstorage.b-cdn.net/n3witalia/youtube-n8n-cover.jpg)](https://youtube.com/@n3witalia)"
      },
      "typeVersion": 1
    },
    {
      "id": "cf3b3e56-f6ae-4f36-bda3-8babe70e12d0",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1104,
        144
      ],
      "parameters": {
        "color": 7,
        "width": 560,
        "height": 480,
        "content": "## Prepare the Final Video\n\nOnce the rendering is finished, the workflow retrieves the generated video URL, creates an SEO-friendly title using OpenAI, and downloads the final video file.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "78e5b430-2e03-4d12-914f-5877ebf36e0e",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1696,
        144
      ],
      "parameters": {
        "color": 7,
        "width": 448,
        "height": 480,
        "content": "## Publish to TikTok and Return the Response\n\nThe completed video is uploaded to [Upload-Post](https://www.upload-post.com/?linkId=lp_144414&sourceId=n3witalia&tenantId=upload-post-app) through its API, and the workflow returns the upload response to the original webhook request."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "1f9167a2-6d8d-45f2-be34-d8a62d93767f",
  "nodeGroups": [],
  "connections": {
    "Webhook": {
      "main": [
        [
          {
            "node": "Create Video",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Completed?": {
      "main": [
        [
          {
            "node": "Get Url Video",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Wait 60 sec.",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get status": {
      "main": [
        [
          {
            "node": "Completed?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Video": {
      "main": [
        [
          {
            "node": "Wait 60 sec.",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request": {
      "main": [
        [
          {
            "node": "Respond to Webhook",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait 60 sec.": {
      "main": [
        [
          {
            "node": "Get status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Url Video": {
      "main": [
        [
          {
            "node": "Generate title",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate title": {
      "main": [
        [
          {
            "node": "Get File Video",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get File Video": {
      "main": [
        [
          {
            "node": "HTTP Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}