{ "name": "Content Pipeline - BlendedFamilyKitchen", "nodes": [ { "parameters": { "rule": { "interval": [{"field": "minutes", "minutesInterval": 30}] } }, "id": "a1b2c3d4-1111-4000-8000-000000000001", "name": "Schedule Trigger", "type": "n8n-nodes-base.scheduleTrigger", "typeVersion": 1.2, "position": [0, 300] }, { "parameters": { "method": "POST", "url": "http://192.168.2.210:5000/webapi/auth.cgi", "sendBody": true, "bodyParameters": { "parameters": [ {"name": "api", "value": "SYNO.API.Auth"}, {"name": "version", "value": "6"}, {"name": "method", "value": "login"}, {"name": "account", "value": "={{ $env.SYNOLOGY_USER }}"}, {"name": "passwd", "value": "={{ $env.SYNOLOGY_PASS }}"}, {"name": "format", "value": "sid"} ] } }, "id": "a1b2c3d4-1111-4000-8000-000000000002", "name": "NAS Login", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [220, 300] }, { "parameters": { "method": "POST", "url": "http://192.168.2.210:5000/webapi/entry.cgi", "sendBody": true, "bodyParameters": { "parameters": [ {"name": "api", "value": "SYNO.FileStation.List"}, {"name": "version", "value": "2"}, {"name": "method", "value": "list"}, {"name": "folder_path", "value": "/BlendedFamilyKitchen/DropZone"}, {"name": "_sid", "value": "={{ $json.data.sid }}"} ] } }, "id": "a1b2c3d4-1111-4000-8000-000000000003", "name": "Poll NAS DropZone", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [440, 300] }, { "parameters": { "conditions": { "options": {"caseSensitive": true, "leftValue": "", "typeValidation": "strict"}, "conditions": [ { "id": "cond1", "leftValue": "={{ $json.data.files.length }}", "rightValue": "0", "operator": {"type": "number", "operation": "gt"} } ], "combinator": "and" } }, "id": "a1b2c3d4-1111-4000-8000-000000000004", "name": "IF New Files?", "type": "n8n-nodes-base.if", "typeVersion": 2, "position": [660, 300] }, { "parameters": { "fieldToSplitOut": "data.files" }, "id": "a1b2c3d4-1111-4000-8000-000000000005", "name": "Split Into Batches", "type": "n8n-nodes-base.splitOut", "typeVersion": 1, "position": [880, 200] }, { "parameters": { "mode": "manual", "duplicateItem": false, "assignments": { "assignments": [ {"id": "a1", "name": "filename", "value": "={{ $json.name }}", "type": "string"}, {"id": "a2", "name": "filepath", "value": "={{ $json.path }}", "type": "string"}, {"id": "a3", "name": "filesize", "value": "={{ $json.additional?.size }}", "type": "number"}, {"id": "a4", "name": "timestamp", "value": "={{ $now.toISO() }}", "type": "string"} ] } }, "id": "a1b2c3d4-1111-4000-8000-000000000006", "name": "Extract Metadata", "type": "n8n-nodes-base.set", "typeVersion": 3.4, "position": [1100, 200] }, { "parameters": { "method": "POST", "url": "http://192.168.2.210:5000/webapi/entry.cgi", "sendBody": true, "bodyParameters": { "parameters": [ {"name": "api", "value": "SYNO.FileStation.Download"}, {"name": "version", "value": "2"}, {"name": "method", "value": "download"}, {"name": "path", "value": "={{ $json.filepath }}"}, {"name": "_sid", "value": "={{ $('NAS Login').item.json.data.sid }}"} ] }, "options": {"response": {"response": {"responseFormat": "file"}}} }, "id": "a1b2c3d4-1111-4000-8000-000000000007", "name": "Download Raw Video", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [1320, 200] }, { "parameters": { "command": "=ffmpeg -i /tmp/{{ $json.filename }} -vn -acodec pcm_s16le -ar 16000 -ac 1 /tmp/{{ $json.filename }}_audio.wav && echo '{\"status\":\"ok\",\"audio_file\":\"/tmp/{{ $json.filename }}_audio.wav\"}'" }, "id": "a1b2c3d4-1111-4000-8000-000000000008", "name": "FFmpeg Extract Audio", "type": "n8n-nodes-base.executeCommand", "typeVersion": 1, "position": [1540, 200] }, { "parameters": { "method": "POST", "url": "http://localhost:9000/asr", "sendBody": true, "contentType": "multipart-form-data", "bodyParameters": { "parameters": [ {"name": "audio_file", "value": "={{ $json.audio_file }}"}, {"name": "task", "value": "transcribe"}, {"name": "language", "value": "en"}, {"name": "output", "value": "srt"} ] } }, "id": "a1b2c3d4-1111-4000-8000-000000000009", "name": "Whisper Transcribe", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [1760, 200] }, { "parameters": { "method": "POST", "url": "https://api.anthropic.com/v1/messages", "sendHeaders": true, "headerParameters": { "parameters": [ {"name": "x-api-key", "value": "={{ $env.ANTHROPIC_API_KEY }}"}, {"name": "anthropic-version", "value": "2023-06-01"}, {"name": "content-type", "value": "application/json"} ] }, "sendBody": true, "specifyBody": "json", "jsonBody": "={\n \"model\": \"claude-haiku-4-5-20251001\",\n \"max_tokens\": 500,\n \"messages\": [{\n \"role\": \"user\",\n \"content\": \"You are a TikTok content strategist for a blended family cooking channel. Given this video transcript, generate:\\n1. Three hook text options (bold, attention-grabbing, 5-8 words max)\\n2. A brief video description with relevant hashtags\\n3. Best posting time suggestion\\n\\nTranscript: {{ $json.data }}\\n\\nRespond in JSON format: {hooks: [str,str,str], description: str, hashtags: [str], best_time: str}\"\n }]\n}" }, "id": "a1b2c3d4-1111-4000-8000-000000000010", "name": "AI Generate Hooks", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [1980, 200] }, { "parameters": { "command": "=ffmpeg -i /tmp/{{ $('Extract Metadata').item.json.filename }} \\\n -vf \"scale=1080:1920:force_original_aspect_ratio=decrease,pad=1080:1920:(ow-iw)/2:(oh-ih)/2,eq=brightness=0.04:contrast=1.1:saturation=1.15,unsharp=5:5:0.3\" \\\n -af \"loudnorm=I=-16:TP=-1.5:LRA=11\" \\\n -c:v libx264 -preset medium -b:v 6M \\\n -c:a aac -b:a 128k \\\n /tmp/{{ $('Extract Metadata').item.json.filename }}_normalized.mp4 && echo '{\"status\":\"ok\"}'" }, "id": "a1b2c3d4-1111-4000-8000-000000000011", "name": "FFmpeg Normalize Video", "type": "n8n-nodes-base.executeCommand", "typeVersion": 1, "position": [2200, 200] }, { "parameters": { "command": "=ffmpeg -i /tmp/{{ $('Extract Metadata').item.json.filename }}_normalized.mp4 \\\n -vf \"subtitles=/tmp/{{ $('Extract Metadata').item.json.filename }}_captions.srt:force_style='FontName=Arial,FontSize=22,PrimaryColour=&H00FFFFFF,OutlineColour=&H00000000,Outline=2,Shadow=1,Alignment=2,MarginV=40'\" \\\n -c:v libx264 -preset medium -b:v 6M \\\n -c:a copy \\\n /tmp/{{ $('Extract Metadata').item.json.filename }}_captioned.mp4 && echo '{\"status\":\"ok\"}'" }, "id": "a1b2c3d4-1111-4000-8000-000000000012", "name": "FFmpeg Burn Captions", "type": "n8n-nodes-base.executeCommand", "typeVersion": 1, "position": [2420, 200] }, { "parameters": { "command": "=ffmpeg -i /tmp/{{ $('Extract Metadata').item.json.filename }}_captioned.mp4 \\\n -i /opt/music_library/kitchen_vibes/track_01.mp3 \\\n -filter_complex \"[1:a]volume=0.12[bg];[0:a][bg]amix=inputs=2:duration=first\" \\\n -c:v copy -c:a aac -b:a 128k \\\n /tmp/{{ $('Extract Metadata').item.json.filename }}_final.mp4 && echo '{\"status\":\"ok\"}'" }, "id": "a1b2c3d4-1111-4000-8000-000000000013", "name": "FFmpeg Mix Background Music", "type": "n8n-nodes-base.executeCommand", "typeVersion": 1, "position": [2640, 200] }, { "parameters": { "command": "=ffmpeg -i /tmp/{{ $('Extract Metadata').item.json.filename }}_final.mp4 \\\n -vf \"select='gt(scene,0.3)',scale=1080:1920\" \\\n -frames:v 1 \\\n /tmp/{{ $('Extract Metadata').item.json.filename }}_thumbnail.jpg && echo '{\"status\":\"ok\"}'" }, "id": "a1b2c3d4-1111-4000-8000-000000000014", "name": "FFmpeg Extract Thumbnail", "type": "n8n-nodes-base.executeCommand", "typeVersion": 1, "position": [2860, 200] }, { "parameters": { "method": "GET", "url": "https://ads.tiktok.com/creative_radar_api/v1/popular_trend/sound/list", "sendQuery": true, "queryParameters": { "parameters": [ {"name": "period", "value": "7"}, {"name": "page", "value": "1"}, {"name": "limit", "value": "10"}, {"name": "country_code", "value": "US"} ] } }, "id": "a1b2c3d4-1111-4000-8000-000000000015", "name": "Scrape Trending Sounds", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [2860, 500] }, { "parameters": { "mode": "manual", "duplicateItem": false, "assignments": { "assignments": [ {"id": "s1", "name": "trending_sounds", "value": "={{ $json.data?.sound_list?.slice(0,3).map(s => s.title + ' by ' + s.author).join('\\n') || 'No trending data available' }}", "type": "string"}, {"id": "s2", "name": "curated_picks", "value": "šŸ³ Kitchen Vibes:\n• Cozy Cooking Lo-Fi (royalty-free)\n• Sunday Morning Jazz (royalty-free)\n• Feel Good Acoustic (royalty-free)", "type": "string"} ] } }, "id": "a1b2c3d4-1111-4000-8000-000000000016", "name": "Format Sound Suggestions", "type": "n8n-nodes-base.set", "typeVersion": 3.4, "position": [3080, 500] }, { "parameters": { "mode": "combine", "mergeByFields": {}, "combinationMode": "mergeByPosition", "options": {} }, "id": "a1b2c3d4-1111-4000-8000-000000000017", "name": "Merge Results", "type": "n8n-nodes-base.merge", "typeVersion": 3, "position": [3300, 300] }, { "parameters": { "method": "POST", "url": "http://192.168.2.210:5000/webapi/entry.cgi", "sendBody": true, "bodyParameters": { "parameters": [ {"name": "api", "value": "SYNO.FileStation.Upload"}, {"name": "version", "value": "2"}, {"name": "method", "value": "upload"}, {"name": "path", "value": "/BlendedFamilyKitchen/Processed"}, {"name": "_sid", "value": "={{ $('NAS Login').item.json.data.sid }}"} ] } }, "id": "a1b2c3d4-1111-4000-8000-000000000018", "name": "Upload to NAS Processed", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [3520, 300] }, { "parameters": { "method": "POST", "url": "=https://api.telegram.org/bot{{ $env.TELEGRAM_BOT_TOKEN }}/sendMessage", "sendBody": true, "specifyBody": "json", "jsonBody": "={\n \"chat_id\": \"{{ $env.CLOE_CHAT_ID }}\",\n \"parse_mode\": \"HTML\",\n \"text\": \"šŸŽ¬ New Video Ready for Review!\\n\\nšŸ“ File: {{ $('Extract Metadata').item.json.filename }}\\n\\nāœļø Hook Options:\\n1ļøāƒ£ {{ $('AI Generate Hooks').item.json.content[0].text.hooks[0] }}\\n2ļøāƒ£ {{ $('AI Generate Hooks').item.json.content[0].text.hooks[1] }}\\n3ļøāƒ£ {{ $('AI Generate Hooks').item.json.content[0].text.hooks[2] }}\\n\\nšŸ“ Description:\\n{{ $('AI Generate Hooks').item.json.content[0].text.description }}\\n\\nšŸŽµ Trending Sounds This Week:\\n{{ $('Format Sound Suggestions').item.json.trending_sounds }}\\n\\nšŸ³ Kitchen-Appropriate Picks:\\n{{ $('Format Sound Suggestions').item.json.curated_picks }}\\n\\nā° Best Time to Post: {{ $('AI Generate Hooks').item.json.content[0].text.best_time }}\\n\\nšŸ‘‡ What would you like to do?\",\n \"reply_markup\": {\n \"inline_keyboard\": [\n [{\"text\": \"āœ… Approve & Post\", \"callback_data\": \"approve_{{ $('Extract Metadata').item.json.filename }}\"}, {\"text\": \"šŸ“ Edit First\", \"callback_data\": \"edit_{{ $('Extract Metadata').item.json.filename }}\"}],\n [{\"text\": \"šŸŽµ Change Sound\", \"callback_data\": \"sound_{{ $('Extract Metadata').item.json.filename }}\"}, {\"text\": \"āŒ Reject\", \"callback_data\": \"reject_{{ $('Extract Metadata').item.json.filename }}\"}],\n [{\"text\": \"ā° Schedule for Later\", \"callback_data\": \"schedule_{{ $('Extract Metadata').item.json.filename }}\"}]\n ]\n }\n}" }, "id": "a1b2c3d4-1111-4000-8000-000000000019", "name": "Notify Cloe via Telegram", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [3740, 300] }, { "parameters": { "url": "=https://api.telegram.org/bot{{ $env.TELEGRAM_BOT_TOKEN }}/getUpdates", "sendQuery": true, "queryParameters": { "parameters": [ {"name": "offset", "value": "-1"}, {"name": "timeout", "value": "30"} ] } }, "id": "a1b2c3d4-1111-4000-8000-000000000020", "name": "Wait for Cloe Response", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [3960, 300] }, { "parameters": { "rules": { "rules": [ {"value": "approve", "output": 0}, {"value": "edit", "output": 1}, {"value": "sound", "output": 2}, {"value": "reject", "output": 3}, {"value": "schedule", "output": 4} ] }, "value": "={{ $json.result?.[0]?.callback_query?.data?.split('_')[0] }}" }, "id": "a1b2c3d4-1111-4000-8000-000000000021", "name": "Switch Cloe Decision", "type": "n8n-nodes-base.switch", "typeVersion": 3, "position": [4180, 300] }, { "parameters": { "method": "POST", "url": "=https://api.telegram.org/bot{{ $env.TELEGRAM_BOT_TOKEN }}/sendMessage", "sendBody": true, "specifyBody": "json", "jsonBody": "={\"chat_id\": \"{{ $env.CLOE_CHAT_ID }}\", \"text\": \"āœ… Video approved! Moving to publish queue...\"}" }, "id": "a1b2c3d4-1111-4000-8000-000000000022", "name": "Handle Approve", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [4400, 60] }, { "parameters": { "method": "POST", "url": "=https://api.telegram.org/bot{{ $env.TELEGRAM_BOT_TOKEN }}/sendMessage", "sendBody": true, "specifyBody": "json", "jsonBody": "={\"chat_id\": \"{{ $env.CLOE_CHAT_ID }}\", \"text\": \"šŸ“ Opening video in edit mode. Make your changes and re-drop when ready!\"}" }, "id": "a1b2c3d4-1111-4000-8000-000000000023", "name": "Handle Edit", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [4400, 200] }, { "parameters": { "method": "POST", "url": "=https://api.telegram.org/bot{{ $env.TELEGRAM_BOT_TOKEN }}/sendMessage", "sendBody": true, "specifyBody": "json", "jsonBody": "={\"chat_id\": \"{{ $env.CLOE_CHAT_ID }}\", \"text\": \"šŸŽµ Pick a sound to use:\\n\\nšŸ”„ Trending:\\n{{ $('Format Sound Suggestions').item.json.trending_sounds }}\\n\\nšŸ³ Kitchen Picks:\\n{{ $('Format Sound Suggestions').item.json.curated_picks }}\\n\\nReply with the sound name or paste a TikTok sound link!\"}" }, "id": "a1b2c3d4-1111-4000-8000-000000000024", "name": "Handle Sound Change", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [4400, 340] }, { "parameters": { "method": "POST", "url": "=https://api.telegram.org/bot{{ $env.TELEGRAM_BOT_TOKEN }}/sendMessage", "sendBody": true, "specifyBody": "json", "jsonBody": "={\"chat_id\": \"{{ $env.CLOE_CHAT_ID }}\", \"text\": \"āŒ Video rejected. Moving to archive.\"}" }, "id": "a1b2c3d4-1111-4000-8000-000000000025", "name": "Handle Reject", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [4400, 480] }, { "parameters": { "method": "POST", "url": "=https://api.telegram.org/bot{{ $env.TELEGRAM_BOT_TOKEN }}/sendMessage", "sendBody": true, "specifyBody": "json", "jsonBody": "={\"chat_id\": \"{{ $env.CLOE_CHAT_ID }}\", \"text\": \"ā° When should this go live? Reply with a date/time (e.g., 'Tomorrow 6pm' or 'Friday 12pm MST')\"}" }, "id": "a1b2c3d4-1111-4000-8000-000000000026", "name": "Handle Schedule", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [4400, 620] }, { "parameters": { "method": "POST", "url": "http://192.168.2.210:5000/webapi/entry.cgi", "sendBody": true, "bodyParameters": { "parameters": [ {"name": "api", "value": "SYNO.FileStation.Rename"}, {"name": "version", "value": "2"}, {"name": "method", "value": "rename"}, {"name": "path", "value": "={{ $('Extract Metadata').item.json.filepath }}"}, {"name": "name", "value": "=archived_{{ $('Extract Metadata').item.json.filename }}"}, {"name": "_sid", "value": "={{ $('NAS Login').item.json.data.sid }}"} ] } }, "id": "a1b2c3d4-1111-4000-8000-000000000027", "name": "Archive Original on NAS", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [4620, 60] }, { "parameters": {}, "id": "a1b2c3d4-1111-4000-8000-000000000028", "name": "Error Trigger", "type": "n8n-nodes-base.errorTrigger", "typeVersion": 1, "position": [0, 700] }, { "parameters": { "method": "POST", "url": "=https://api.telegram.org/bot{{ $env.TELEGRAM_BOT_TOKEN }}/sendMessage", "sendBody": true, "specifyBody": "json", "jsonBody": "={\n \"chat_id\": \"{{ $env.JORDAN_CHAT_ID }}\",\n \"parse_mode\": \"HTML\",\n \"text\": \"🚨 Content Pipeline Error\\n\\nNode: {{ $json.execution?.error?.node?.name || 'Unknown' }}\\nError: {{ $json.execution?.error?.message || 'Unknown error' }}\\nExecution: {{ $json.execution?.id }}\\n\\nView in n8n\"\n}" }, "id": "a1b2c3d4-1111-4000-8000-000000000029", "name": "Notify Jordan Error", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [220, 700] }, { "parameters": { "content": "## šŸ“ Stage 1: NAS Drop Zone Polling\n\n**How it works:**\nPolls Synology NAS every 30 min for new files in /BlendedFamilyKitchen/DropZone\n\n**Cloe's workflow:**\n1. Records video on phone\n2. Saves/uploads to NAS DropZone folder\n3. Pipeline auto-detects and processes\n\n**TODO - Infrastructure:**\n- [ ] Create NAS folders: /BlendedFamilyKitchen/DropZone, /Processed, /Archive\n- [ ] Set up Synology FileStation API access\n- [ ] Add SYNOLOGY_USER and SYNOLOGY_PASS to n8n env vars\n- [ ] Test NAS API connectivity from CT 113\n- [ ] Set up Synology DS file app on Cloe's phone for easy upload", "width": 520, "height": 380 }, "id": "a1b2c3d4-1111-4000-8000-000000000030", "name": "Sticky - NAS Polling", "type": "n8n-nodes-base.stickyNote", "typeVersion": 1, "position": [-40, -140] }, { "parameters": { "content": "## šŸ¤– Stage 2: AI Processing Pipeline\n\n**Processing chain:**\n1. FFmpeg extracts audio → Whisper transcribes → .srt captions\n2. Claude AI generates 3 hook options + description + hashtags\n3. FFmpeg normalizes video (9:16, color, audio levels)\n4. FFmpeg burns captions (white text, black outline, bottom-third)\n5. FFmpeg mixes low-volume background music from curated library\n6. FFmpeg extracts best thumbnail frame (scene detection)\n\n**TODO - Infrastructure:**\n- [ ] Deploy Whisper Docker container (onerahmet/openai-whisper-asr-webservice)\n- [ ] Install FFmpeg on CT 113 (apt install ffmpeg)\n- [ ] Add ANTHROPIC_API_KEY to n8n env vars\n- [ ] Create /opt/music_library/kitchen_vibes/ with 10-20 royalty-free tracks\n- [ ] Test full processing chain with a sample video", "width": 560, "height": 420 }, "id": "a1b2c3d4-1111-4000-8000-000000000031", "name": "Sticky - AI Processing", "type": "n8n-nodes-base.stickyNote", "typeVersion": 1, "position": [1280, -180] }, { "parameters": { "content": "## šŸŽµ Stage 3: Sound Suggestions\n\n**Trending Sounds:**\nScrapes TikTok Creative Center API weekly for top 10 trending sounds in US region. Presents top 3 to Cloe as suggestions.\n\n**Curated Kitchen Picks:**\nPre-selected royalty-free tracks appropriate for cooking content. Cloe can choose from these without worrying about copyright.\n\n**Cloe's autonomy preserved:**\n- She picks the final sound (or uses her own)\n- Suggestions are recommendations, not auto-applied\n- She can paste any TikTok sound link to use instead\n\n**TODO:**\n- [ ] Test TikTok Creative Radar API access\n- [ ] Build curated music library (royalty-free)\n- [ ] If API blocked, fallback to manual weekly curation", "width": 520, "height": 420 }, "id": "a1b2c3d4-1111-4000-8000-000000000032", "name": "Sticky - Sound Suggestions", "type": "n8n-nodes-base.stickyNote", "typeVersion": 1, "position": [2820, 680] }, { "parameters": { "content": "## šŸ“± Stage 4: Cloe Approval Flow\n\n**Telegram notification includes:**\n- Video filename and preview info\n- 3 AI-generated hook options (she picks one or writes her own)\n- Auto-generated description with hashtags\n- Trending sound suggestions + curated kitchen picks\n- Best posting time recommendation\n\n**Cloe's options (inline keyboard buttons):**\nāœ… Approve & Post — publishes as-is with selected hook\nšŸ“ Edit First — sends video back for manual edits\nšŸŽµ Change Sound — shows full sound list to pick from\nāŒ Reject — archives the video\nā° Schedule — asks for preferred date/time\n\n**TODO:**\n- [ ] Set up Telegram bot for Cloe (or use Garvis bot)\n- [ ] Add TELEGRAM_BOT_TOKEN and CLOE_CHAT_ID to n8n env\n- [ ] Implement callback query handler for button responses\n- [ ] Test full approval flow end-to-end", "width": 560, "height": 480 }, "id": "a1b2c3d4-1111-4000-8000-000000000033", "name": "Sticky - Cloe Approval", "type": "n8n-nodes-base.stickyNote", "typeVersion": 1, "position": [3680, -160] }, { "parameters": { "content": "## 🚨 Error Handling\n\n**On any node failure:**\n- Error trigger catches the failure\n- Sends detailed error notification to Jordan via Telegram\n- Includes: failed node name, error message, execution ID\n- Direct link to the failed execution in n8n UI\n\n**TODO:**\n- [ ] Add JORDAN_CHAT_ID to n8n env vars\n- [ ] Test error handling with intentional failure\n- [ ] Consider retry logic for transient failures (NAS timeout, API rate limit)", "width": 480, "height": 320 }, "id": "a1b2c3d4-1111-4000-8000-000000000034", "name": "Sticky - Error Handling", "type": "n8n-nodes-base.stickyNote", "typeVersion": 1, "position": [-40, 560] } ], "connections": { "Schedule Trigger": { "main": [[{"node": "NAS Login", "type": "main", "index": 0}]] }, "NAS Login": { "main": [[{"node": "Poll NAS DropZone", "type": "main", "index": 0}]] }, "Poll NAS DropZone": { "main": [[{"node": "IF New Files?", "type": "main", "index": 0}]] }, "IF New Files?": { "main": [ [{"node": "Split Into Batches", "type": "main", "index": 0}], [] ] }, "Split Into Batches": { "main": [[{"node": "Extract Metadata", "type": "main", "index": 0}]] }, "Extract Metadata": { "main": [[{"node": "Download Raw Video", "type": "main", "index": 0}]] }, "Download Raw Video": { "main": [[{"node": "FFmpeg Extract Audio", "type": "main", "index": 0}]] }, "FFmpeg Extract Audio": { "main": [[{"node": "Whisper Transcribe", "type": "main", "index": 0}]] }, "Whisper Transcribe": { "main": [[{"node": "AI Generate Hooks", "type": "main", "index": 0}]] }, "AI Generate Hooks": { "main": [[{"node": "FFmpeg Normalize Video", "type": "main", "index": 0}]] }, "FFmpeg Normalize Video": { "main": [[{"node": "FFmpeg Burn Captions", "type": "main", "index": 0}]] }, "FFmpeg Burn Captions": { "main": [[{"node": "FFmpeg Mix Background Music", "type": "main", "index": 0}]] }, "FFmpeg Mix Background Music": { "main": [[{"node": "FFmpeg Extract Thumbnail", "type": "main", "index": 0}]] }, "FFmpeg Extract Thumbnail": { "main": [[{"node": "Merge Results", "type": "main", "index": 0}]] }, "Scrape Trending Sounds": { "main": [[{"node": "Format Sound Suggestions", "type": "main", "index": 0}]] }, "Format Sound Suggestions": { "main": [[{"node": "Merge Results", "type": "main", "index": 1}]] }, "Merge Results": { "main": [[{"node": "Upload to NAS Processed", "type": "main", "index": 0}]] }, "Upload to NAS Processed": { "main": [[{"node": "Notify Cloe via Telegram", "type": "main", "index": 0}]] }, "Notify Cloe via Telegram": { "main": [[{"node": "Wait for Cloe Response", "type": "main", "index": 0}]] }, "Wait for Cloe Response": { "main": [[{"node": "Switch Cloe Decision", "type": "main", "index": 0}]] }, "Switch Cloe Decision": { "main": [ [{"node": "Handle Approve", "type": "main", "index": 0}], [{"node": "Handle Edit", "type": "main", "index": 0}], [{"node": "Handle Sound Change", "type": "main", "index": 0}], [{"node": "Handle Reject", "type": "main", "index": 0}], [{"node": "Handle Schedule", "type": "main", "index": 0}] ] }, "Handle Approve": { "main": [[{"node": "Archive Original on NAS", "type": "main", "index": 0}]] }, "Error Trigger": { "main": [[{"node": "Notify Jordan Error", "type": "main", "index": 0}]] } }, "settings": { "executionOrder": "v1" }, "staticData": null, "tags": [], "triggerCount": 1, "active": false }