{ "name": "Veo 3 + VideoBGRemover → Lottie JSON for Mobile", "nodes": [ { "parameters": { "httpMethod": "POST", "path": "veo3-mobile-lottie", "responseMode": "responseNode", "options": {"responseData": "allEntries"} }, "id": "webhook", "name": "Webhook Trigger", "type": "n8n-nodes-base.webhook", "typeVersion": 1.1, "position": [-1520, 40] }, { "parameters": {}, "id": "manual-trigger", "name": "Manual Trigger", "type": "n8n-nodes-base.manualTrigger", "typeVersion": 1, "position": [-1520, 280] }, { "parameters": { "height": 620, "width": 520, "content": "## šŸŽ¬ Mobile Animation Generator\n\n**What it does:**\n- Generates 4-8 second animation with Google Veo 3\n- Removes background with VideoBGRemover\n- Exports as Lottie JSON for mobile apps\n- Saves to Google Drive\n\n**Perfect for:**\n- Mobile app animations (like Duolingo)\n- Loading screens & onboarding flows\n- UI micro-interactions & transitions\n- Character animations for iOS/Android\n- Tutorial & walkthrough animations\n- App Store preview assets\n\n**Processing time:** 5-8 minutes total\n- Veo 3 generation: ~2-4 min\n- Background removal: ~1-2 min\n- Lottie export: ~1-2 min\n\n**Setup:** ~7 minutes (2 API keys)\n\n**Output:**\n- `.json` file (Lottie format)\n- 30-150KB file size\n- Full transparency via WebP\n- Compatible with lottie-ios, lottie-android, lottie-react-native\n\n[šŸ“– Full Documentation](https://docs.videobgremover.com/)" }, "id": "sticky-overview", "name": "šŸ“‹ Overview", "type": "n8n-nodes-base.stickyNote", "typeVersion": 1, "position": [-1980, -320], "notesTextSize": "large", "notesBackgroundColor": 4 }, { "parameters": { "height": 480, "width": 420, "content": "## šŸ”‘ API Keys Setup (Required)\n\n**1. FAL AI Key (for Veo 3)**\n- Visit: https://fal.ai/dashboard/keys\n- Sign up and create API key\n- Add to n8n: Settings → Variables\n - Name: `FAL_KEY`\n - Value: your FAL key\n\n**2. VideoBGRemover API Key**\n- Visit: https://videobgremover.com/api-management\n- Sign up (free tier available)\n- Add to n8n: Settings → Variables\n - Name: `VIDEOBGREMOVER_KEY`\n - Value: your API key\n\nāœ… All keys use `$vars.` (secure)\n\n**Setup time:** ~5 minutes" }, "id": "sticky-api-keys", "name": "šŸ”‘ API Keys", "type": "n8n-nodes-base.stickyNote", "typeVersion": 1, "position": [-1520, -320] }, { "parameters": { "height": 480, "width": 420, "content": "## šŸ“„ Input Required\n\n**prompt** (required)\n- Text description of animation you want\n- Be clear and descriptive\n- Include subject, action, style\n\n**duration** (required)\n- MUST be exactly: 4, 6, or 8\n- Veo 3 only accepts these values\n- Default in template: 6 seconds\n- Best for mobile: 4-6 seconds\n\n**aspect_ratio** (optional)\n- Default: 1:1 (square - best for mobile)\n- Other options: 9:16 (portrait), 16:9 (landscape)\n\n**Example:**\n```json\n{\n \"prompt\": \"A cute owl character celebrating success with confetti falling around, cartoon style with smooth movements\",\n \"duration\": 6,\n \"aspect_ratio\": \"1:1\",\n \"store_to_drive\": true\n}\n```\n\n**Prompt tips:**\n- Keep it simple and focused\n- Describe character + action + style\n- Works great for mascots, icons, characters\n- Smooth, loopable animations work best" }, "id": "sticky-inputs", "name": "šŸ“„ Inputs", "type": "n8n-nodes-base.stickyNote", "typeVersion": 1, "position": [-1060, -320] }, { "parameters": { "height": 520, "width": 420, "content": "## šŸ”„ Workflow Steps\n\n**1. Veo 3 Generation** (~2-4 min)\n- Submits prompt to Google's Veo 3\n- Generates high-quality animation\n- 1:1 aspect ratio (mobile-optimized)\n- Audio disabled (saves 50% credits)\n- 720p resolution\n\n**2. Background Removal** (~1-2 min)\n- Uploads video to VideoBGRemover\n- AI removes background frame-by-frame\n- Preserves smooth edges & transparency\n\n**3. Lottie Export** (~1-2 min)\n- Converts to Lottie JSON format\n- Embeds frames as WebP images\n- Full alpha channel transparency\n- Optimized for mobile apps\n- Tiny file size (30-150KB)\n\n**4. Google Drive Upload**\n- Saves `.json` file to Drive\n- Returns shareable link\n- Ready to use in iOS/Android apps" }, "id": "sticky-workflow", "name": "šŸ”„ Workflow", "type": "n8n-nodes-base.stickyNote", "typeVersion": 1, "position": [-600, -320] }, { "parameters": { "height": 400, "width": 460, "content": "## šŸ“± What is Lottie?\n\n**Lottie** is a JSON-based animation format for mobile apps.\n\n**Why Lottie?**\n- āœ… Tiny file size (10-50x smaller than video)\n- āœ… Scales to any resolution (vector-based)\n- āœ… Hardware-accelerated rendering\n- āœ… Native iOS/Android/React Native support\n- āœ… Transparent backgrounds\n- āœ… Programmable (play, pause, loop, reverse)\n\n**How to use:**\n\n**iOS (Swift):**\n```swift\nimport Lottie\nlet animationView = LottieAnimationView(name: \"animation\")\nanimationView.play()\n```\n\n**Android (Kotlin):**\n```kotlin\nval animationView = LottieAnimationView(this)\nanimationView.setAnimation(\"animation.json\")\nanimationView.playAnimation()\n```\n\n**React Native:**\n```javascript\nimport LottieView from 'lottie-react-native'\n\n```" }, "id": "sticky-lottie", "name": "šŸ“± Lottie Info", "type": "n8n-nodes-base.stickyNote", "typeVersion": 1, "position": [-100, -320] }, { "parameters": { "height": 400, "width": 380, "content": "## šŸ’¾ Google Drive Setup\n\n**Step 1:** Connect Google Drive\n- Click \"Upload to Google Drive\" node\n- Click \"Connect\"\n- Authorize n8n\n\n**Step 2:** Choose folder (optional)\n- Default: Root of \"My Drive\"\n- Or select specific folder\n\n**Output:**\n- `.json` file (not `.mp4`)\n- Permanent shareable link\n- Direct download URL\n- File metadata\n- Drive file ID\n\nā±ļø Setup time: ~2 minutes\n\n**Note:** Files are named automatically:\n`lottie_animation_[timestamp].json`" }, "id": "sticky-gdrive", "name": "šŸ’¾ Google Drive", "type": "n8n-nodes-base.stickyNote", "typeVersion": 1, "position": [400, -320] }, { "parameters": { "height": 560, "width": 420, "content": "## šŸš€ How to Use\n\n**Manual testing:**\n1. Update `prompt` in \"Sample Input\"\n2. Choose `duration` (4, 6, or 8 seconds)\n3. Optionally change `aspect_ratio`\n4. Click \"Execute Workflow\"\n5. Wait 5-8 minutes for processing\n6. Check Google Drive for `.json` file\n7. Download and use in your mobile app\n\n**Webhook automation:**\n1. Activate workflow\n2. Copy webhook URL\n3. POST to webhook:\n```json\n{\n \"prompt\": \"A happy character jumping with joy, cartoon style\",\n \"duration\": 5,\n \"aspect_ratio\": \"1:1\",\n \"store_to_drive\": true\n}\n```\n\n**Prompt examples:**\n- \"Cute robot loading animation, minimalist style\"\n- \"Check mark appearing with celebration confetti\"\n- \"Character waving hello, friendly cartoon style\"\n- \"Progress bar filling up with sparkles\"\n- \"Success celebration with fireworks background\"" }, "id": "sticky-usage", "name": "šŸš€ Usage", "type": "n8n-nodes-base.stickyNote", "typeVersion": 1, "position": [860, -320] }, { "parameters": { "assignments": { "assignments": [ {"name": "prompt", "type": "string", "value": "={{ $json.body?.prompt ?? $json.prompt }}"}, {"name": "duration", "type": "number", "value": "={{ $json.body?.duration ?? $json.duration ?? 5 }}"}, {"name": "aspect_ratio", "type": "string", "value": "={{ $json.body?.aspect_ratio ?? $json.aspect_ratio ?? '1:1' }}"}, {"name": "store_to_drive", "type": "boolean", "value": "={{ $json.body?.store_to_drive ?? $json.store_to_drive ?? false }}"}, {"name": "source", "type": "string", "value": "webhook"} ] } }, "id": "extract-webhook", "name": "Extract Webhook Data", "type": "n8n-nodes-base.set", "typeVersion": 3.3, "position": [-1300, 40] }, { "parameters": { "assignments": { "assignments": [ {"name": "prompt", "type": "string", "value": "A cute owl character celebrating success with confetti falling around, smooth cartoon animation style with vibrant colors"}, {"name": "duration", "type": "number", "value": 6}, {"name": "aspect_ratio", "type": "string", "value": "1:1"}, {"name": "store_to_drive", "type": "boolean", "value": true}, {"name": "source", "type": "string", "value": "manual"} ] } }, "id": "sample-input", "name": "Sample Input (Edit Here)", "type": "n8n-nodes-base.set", "typeVersion": 3.3, "position": [-1300, 280] }, { "parameters": { "mode": "append", "options": {} }, "id": "merge-triggers", "name": "Merge Triggers", "type": "n8n-nodes-base.merge", "typeVersion": 2.1, "position": [-1080, 160] }, { "parameters": { "height": 100, "width": 1000, "content": "## šŸŽØ VEO 3 AI ANIMATION GENERATION SECTION\nGoogle's Veo 3 generates high-quality animation from text prompt → 1:1 square format for mobile → Audio disabled to save 50% credits" }, "id": "sticky-section-veo3", "name": "Section: Veo 3", "type": "n8n-nodes-base.stickyNote", "typeVersion": 1, "position": [-900, 380], "notesBackgroundColor": 5 }, { "parameters": { "url": "https://queue.fal.run/fal-ai/veo3", "method": "POST", "sendHeaders": true, "headerParameters": {"parameters": [ {"name": "Authorization", "value": "=Key {{ $vars.FAL_KEY }}"}, {"name": "Content-Type", "value": "application/json"} ]}, "sendBody": true, "specifyBody": "json", "jsonBody": "={\n \"prompt\": \"{{ $json.prompt }}\",\n \"aspect_ratio\": \"{{ $json.aspect_ratio }}\",\n \"duration\": \"{{ $json.duration }}s\",\n \"resolution\": \"720p\",\n \"enhance_prompt\": true,\n \"generate_audio\": false,\n \"auto_fix\": true\n}" }, "id": "veo3-submit", "name": "Veo 3 – Submit Job", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [-860, 460] }, { "parameters": { "url": "=https://queue.fal.run/fal-ai/veo3/requests/{{ $json.request_id }}/status", "sendHeaders": true, "headerParameters": {"parameters": [{"name": "Authorization", "value": "=Key {{ $vars.FAL_KEY }}"}]}, "options": {"response": {"response": {"responseFormat": "json", "neverError": true}}} }, "id": "veo3-status", "name": "Veo 3 – Check Status", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [-640, 460] }, { "parameters": {"amount": 20, "unit": "seconds"}, "id": "wait-veo3", "name": "Wait 20s", "type": "n8n-nodes-base.wait", "typeVersion": 1.1, "position": [-420, 560] }, { "parameters": { "conditions": { "combinator": "and", "conditions": [ {"leftValue": "={{ $json.status }}", "operator": {"type": "string", "operation": "equals"}, "rightValue": "COMPLETED", "id": "ok"} ], "options": {"typeValidation": "strict", "caseSensitive": true} } }, "id": "if-veo3-done", "name": "Veo 3 Completed?", "type": "n8n-nodes-base.if", "typeVersion": 2, "position": [-420, 460] }, { "parameters": { "url": "=https://queue.fal.run/fal-ai/veo3/requests/{{ $('Veo 3 – Submit Job').item.json.request_id }}", "sendHeaders": true, "headerParameters": {"parameters": [{"name": "Authorization", "value": "='Key ' + $vars.FAL_KEY"}]} }, "id": "veo3-result", "name": "Veo 3 – Get Result", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [-180, 460] }, { "parameters": { "height": 100, "width": 1240, "content": "## šŸŽ¬ VIDEOBGREMOVER LOTTIE EXPORT SECTION\nRemoves background → Exports as Lottie JSON with full transparency → Mobile-optimized format" }, "id": "sticky-section-vbr", "name": "Section: VideoBGRemover", "type": "n8n-nodes-base.stickyNote", "typeVersion": 1, "position": [60, 680], "notesBackgroundColor": 2 }, { "parameters": { "method": "POST", "url": "https://api.videobgremover.com/api/v1/jobs", "sendHeaders": true, "headerParameters": {"parameters": [ {"name": "X-API-Key", "value": "={{ $vars.VIDEOBGREMOVER_KEY }}"}, {"name": "Content-Type", "value": "application/json"} ]}, "sendBody": true, "specifyBody": "json", "jsonBody": "={\n \"video_url\": \"{{ $json.video.url }}\"\n}" }, "id": "vbr-create", "name": "VBR – Create Job", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.1, "position": [60, 760] }, { "parameters": { "method": "POST", "url": "=https://api.videobgremover.com/api/v1/jobs/{{ $json.id }}/start", "sendHeaders": true, "headerParameters": {"parameters": [ {"name": "X-API-Key", "value": "={{ $vars.VIDEOBGREMOVER_KEY }}"}, {"name": "Content-Type", "value": "application/json"} ]}, "sendBody": true, "specifyBody": "json", "jsonBody": "={\n \"background\": {\n \"type\": \"transparent\",\n \"transparent_format\": \"lottie\"\n }\n}" }, "id": "vbr-start-lottie", "name": "VBR – Start Lottie Export", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.1, "position": [280, 760] }, { "parameters": { "method": "GET", "url": "=https://api.videobgremover.com/api/v1/jobs/{{ $('VBR – Create Job').item.json.id }}/status", "sendHeaders": true, "headerParameters": {"parameters": [{"name": "X-API-Key", "value": "={{ $vars.VIDEOBGREMOVER_KEY }}"}]}, "options": {"response": {"response": {"responseFormat": "json", "neverError": true}}} }, "id": "vbr-status", "name": "VBR – Check Status", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.1, "position": [500, 760] }, { "parameters": {"amount": 20, "unit": "seconds"}, "id": "wait-vbr", "name": "Wait 20s (VBR)", "type": "n8n-nodes-base.wait", "typeVersion": 1.1, "position": [720, 860] }, { "parameters": { "conditions": { "combinator": "and", "conditions": [ {"leftValue": "={{ $json.status }}", "operator": {"type": "string", "operation": "equals"}, "rightValue": "completed", "id": "done"} ], "options": {"typeValidation": "strict", "caseSensitive": true} } }, "id": "if-vbr-done", "name": "VBR Completed?", "type": "n8n-nodes-base.if", "typeVersion": 2, "position": [720, 760] }, { "parameters": { "assignments": { "assignments": [ {"name": "lottie_url", "type": "string", "value": "={{ $json.processed_video_url }}"}, {"name": "length_seconds", "type": "number", "value": "={{ $json.length_seconds ?? $json.meta?.duration }}"} ] } }, "id": "prepare-lottie", "name": "Prepare Lottie URL", "type": "n8n-nodes-base.set", "typeVersion": 3.3, "position": [940, 760] }, { "parameters": { "height": 100, "width": 900, "content": "## šŸ’¾ OUTPUT SECTION\nDownload Lottie JSON → Upload to Google Drive → Return response" }, "id": "sticky-section-output", "name": "Section: Output", "type": "n8n-nodes-base.stickyNote", "typeVersion": 1, "position": [1140, 980], "notesBackgroundColor": 3 }, { "parameters": { "url": "={{ $('Prepare Lottie URL').item.json.lottie_url }}", "options": {"response": {"response": {"responseFormat": "file"}}} }, "id": "download-lottie", "name": "Download Lottie JSON", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [1140, 1060] }, { "parameters": { "operation": "upload", "binaryPropertyName": "data", "name": "=lottie_animation_{{ new Date().getTime() }}.json", "driveId": {"__rl": true, "mode": "list", "value": "My Drive"}, "folderId": {"__rl": true, "mode": "list", "value": "root"}, "options": {"simplifyOutput": true} }, "id": "gdrive-upload", "name": "Upload to Google Drive", "type": "n8n-nodes-base.googleDrive", "typeVersion": 3, "position": [1360, 1060] }, { "parameters": { "assignments": { "assignments": [ {"name": "response", "type": "object", "value": "={{ { url: $json.webViewLink, drive_file_id: $json.id, source: 'google_drive', format: 'lottie', file_name: $json.name } }}"} ] } }, "id": "build-drive-resp", "name": "Build Drive Response", "type": "n8n-nodes-base.set", "typeVersion": 3.3, "position": [1580, 1060] }, { "parameters": { "conditions": { "combinator": "and", "conditions": [ {"leftValue": "={{ $('Merge Triggers').item.json.source }}", "operator": {"type": "string", "operation": "equals"}, "rightValue": "webhook", "id": "is-webhook"} ], "options": {"typeValidation": "strict", "caseSensitive": true} } }, "id": "if-webhook", "name": "From Webhook?", "type": "n8n-nodes-base.if", "typeVersion": 2, "position": [1800, 1160] }, { "parameters": {"responseBody": "={{ $json.response ?? $json }}", "responseCode": 200}, "id": "respond", "name": "Respond to Webhook", "type": "n8n-nodes-base.respondToWebhook", "typeVersion": 1.1, "position": [2020, 1060] }, { "parameters": { "assignments": { "assignments": [ {"name": "final_result", "type": "object", "value": "={{ $json.response ?? $json }}"} ] } }, "id": "manual-complete", "name": "Manual Test Complete", "type": "n8n-nodes-base.set", "typeVersion": 3.3, "position": [2020, 1260] } ], "connections": { "Webhook Trigger": {"main": [[{"node": "Extract Webhook Data", "type": "main", "index": 0}]]}, "Manual Trigger": {"main": [[{"node": "Sample Input (Edit Here)", "type": "main", "index": 0}]]}, "Extract Webhook Data": {"main": [[{"node": "Merge Triggers", "type": "main", "index": 0}]]}, "Sample Input (Edit Here)": {"main": [[{"node": "Merge Triggers", "type": "main", "index": 1}]]}, "Merge Triggers": {"main": [[{"node": "Veo 3 – Submit Job", "type": "main", "index": 0}]]}, "Veo 3 – Submit Job": {"main": [[{"node": "Veo 3 – Check Status", "type": "main", "index": 0}]]}, "Veo 3 – Check Status": {"main": [[{"node": "Veo 3 Completed?", "type": "main", "index": 0}]]}, "Veo 3 Completed?": {"main": [ [{"node": "Veo 3 – Get Result", "type": "main", "index": 0}], [{"node": "Wait 20s", "type": "main", "index": 0}] ]}, "Wait 20s": {"main": [[{"node": "Veo 3 – Check Status", "type": "main", "index": 0}]]}, "Veo 3 – Get Result": {"main": [[{"node": "VBR – Create Job", "type": "main", "index": 0}]]}, "VBR – Create Job": {"main": [[{"node": "VBR – Start Lottie Export", "type": "main", "index": 0}]]}, "VBR – Start Lottie Export": {"main": [[{"node": "VBR – Check Status", "type": "main", "index": 0}]]}, "VBR – Check Status": {"main": [[{"node": "VBR Completed?", "type": "main", "index": 0}]]}, "VBR Completed?": {"main": [ [{"node": "Prepare Lottie URL", "type": "main", "index": 0}], [{"node": "Wait 20s (VBR)", "type": "main", "index": 0}] ]}, "Wait 20s (VBR)": {"main": [[{"node": "VBR – Check Status", "type": "main", "index": 0}]]}, "Prepare Lottie URL": {"main": [[{"node": "Download Lottie JSON", "type": "main", "index": 0}]]}, "Download Lottie JSON": {"main": [[{"node": "Upload to Google Drive", "type": "main", "index": 0}]]}, "Upload to Google Drive": {"main": [[{"node": "Build Drive Response", "type": "main", "index": 0}]]}, "Build Drive Response": {"main": [[{"node": "From Webhook?", "type": "main", "index": 0}]]}, "From Webhook?": {"main": [ [{"node": "Respond to Webhook", "type": "main", "index": 0}], [{"node": "Manual Test Complete", "type": "main", "index": 0}] ]} }, "settings": {"executionOrder": "v1"} }