This workflow corresponds to n8n.io template #15118 — we link there as the canonical source.
This workflow follows the Form Trigger → Gmail 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 →
{
"meta": {
"templateCredsSetupCompleted": true
},
"nodes": [
{
"id": "70b879a1-c100-4b22-a3db-cfbce96252d2",
"name": "Overview",
"type": "n8n-nodes-base.stickyNote",
"position": [
-3376,
-352
],
"parameters": {
"color": 4,
"width": 700,
"height": 1192,
"content": "## Webinar to Social Media Clips \u2014 WayinVideo + Sheets + Gmail\n\nFor content marketers and social media teams who want to turn a 1\u20132 hour webinar into ready-to-post vertical short videos in 10\u201315 minutes with zero manual editing. Submit a YouTube, Vimeo, or Zoom recording URL via the form. The workflow runs a two-phase WayinVideo pipeline: Phase 1 identifies all viral clips from the video without rendering, Phase 2 exports only the highest-scoring clips as 9:16 vertical videos with animated captions, an AI hook, and AI subject reframing. Every clip is logged to Google Sheets and a Gmail digest with direct download links arrives when everything is ready.\n\n## How it works\n- **1. Form \u2014 Enter Video URL** collects the video URL, title, your name, and how many clips you want (max 5)\n- **2. Set \u2014 Config Values** stores the WayinVideo API key, Sheet ID, recipient email, and all export settings\n- **3. HTTP \u2014 Submit AI Clipping Task** submits the video to WayinVideo with enable_export false \u2014 identifies clips without rendering\n- **4. Code \u2014 Save Clipping Project ID** saves the project ID and initializes the poll counter\n- **5\u20138. Phase 1 Polling Loop** polls every 60 seconds until all clips are identified \u2014 up to 25 polls (25 minutes)\n- **10. Code \u2014 Select Top Clips for Export** sorts clips by viral score and extracts the clip indices for export\n- **11. HTTP \u2014 Submit Export Task** sends the top clips for full rendering with captions, AI hook, and 9:16 reframe\n- **12. Code \u2014 Save Export Task ID** saves the export task ID and resets the poll counter\n- **13\u201316. Phase 2 Polling Loop** polls every 60 seconds until rendering is complete \u2014 up to 20 polls (20 minutes)\n- **18. Code \u2014 Build Sheet Rows** merges export download links with clip metadata and prepares one row per clip\n- **19. Google Sheets \u2014 Log Clips** appends every clip as a row with score, tags, description, and download link\n- **21. Code \u2014 Build Gmail Digest** assembles the email with all clip details and a 24-hour link expiry warning\n- **22. Gmail \u2014 Send Clips Digest** delivers the final report to your inbox\n\n## Set up steps\n1. In **2. Set \u2014 Config Values** \u2014 replace YOUR_WAYINVIDEO_API_KEY, YOUR_GOOGLE_SHEET_ID, recipient email, and sender name\n2. In **19. Google Sheets \u2014 Log Clips** \u2014 connect your Google Sheets OAuth2 credential\n3. In **22. Gmail \u2014 Send Clips Digest** \u2014 connect your Gmail OAuth2 credential\n4. Create a Google Sheet tab named Social Media Clips with columns: Date, Video Title, Clip #, Clip Title, Duration (sec), Viral Score, Tags, Description, Export Link, Logged At\n5. Activate the workflow and open the Form URL to submit your first video"
},
"typeVersion": 1
},
{
"id": "1b388157-e051-4987-875f-3c74c6f1c9b6",
"name": "Section \u2014 Form Input and Config",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2640,
-16
],
"parameters": {
"color": 5,
"width": 484,
"height": 372,
"content": "## Form Input and Config\nUser submits the video URL, title, name, and clip count via the n8n form. Config stores WayinVideo API key, sheet and email settings, and all export parameters including clip duration, aspect ratio, and resolution."
},
"typeVersion": 1
},
{
"id": "3da64c58-6724-4347-bb14-c57cd97e7a5c",
"name": "Section \u2014 Phase 1 AI Clipping Identification",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2144,
-96
],
"parameters": {
"color": 6,
"width": 1284,
"height": 788,
"content": "## Phase 1 \u2014 AI Clipping Identification and Polling Loop\nSubmits video to WayinVideo with enable_export false to identify all viral clips without rendering. Polls every 60 seconds until SUCCEEDED. Clips are ranked but not yet rendered \u2014 only metadata returned. Timeout after 25 polls (25 minutes)."
},
"typeVersion": 1
},
{
"id": "baf83c57-1c92-4cc5-8794-c3fd342775b4",
"name": "Section \u2014 Phase 2 Selective Export and Rendering",
"type": "n8n-nodes-base.stickyNote",
"position": [
-832,
-288
],
"parameters": {
"color": 6,
"width": 1508,
"height": 804,
"content": "## Phase 2 \u2014 Selective Export and Rendering Loop\nSelects only the highest-scoring clips by viral score and submits them for full rendering with animated captions, AI hook text, and AI subject reframing. Polls every 60 seconds until all clips are rendered and export links are available. Timeout after 20 polls (20 minutes)."
},
"typeVersion": 1
},
{
"id": "9cc7aa3f-d136-4881-b735-46adb8c4ab4f",
"name": "Section \u2014 Sheet Logging and Gmail Delivery",
"type": "n8n-nodes-base.stickyNote",
"position": [
720,
-528
],
"parameters": {
"color": 4,
"width": 1060,
"height": 644,
"content": "## Sheet Logging and Gmail Delivery\nMerges export download links with clip metadata. Logs one row per clip to Google Sheets. After the last clip is logged, builds a Gmail digest with all clip details, scores, tags, and download links. Export links expire after 24 hours \u2014 download immediately after receiving the email."
},
"typeVersion": 1
},
{
"id": "7093db00-30e7-4bae-a2d4-621110badca9",
"name": "1. Form \u2014 Enter Video URL",
"type": "n8n-nodes-base.formTrigger",
"position": [
-2560,
128
],
"parameters": {
"options": {},
"formTitle": "Webinar to Social Media Clips",
"formFields": {
"values": [
{
"fieldLabel": "Video URL",
"placeholder": "https://www.youtube.com/watch?v=... OR Zoom/Vimeo link",
"requiredField": true
},
{
"fieldLabel": "Video Title",
"placeholder": "e.g. SEO Strategy Webinar April 2026",
"requiredField": true
},
{
"fieldLabel": "Your Name",
"placeholder": "e.g. Rahul Dutt",
"requiredField": true
},
{
"fieldLabel": "Number of Clips (max 5)",
"placeholder": "3"
}
]
},
"formDescription": "Paste a webinar or YouTube video URL. WayinVideo will find the top viral clips and deliver them as ready-to-post 9:16 short videos with captions."
},
"typeVersion": 2.2
},
{
"id": "b7f054a4-9485-45e4-a278-8db7e77601a9",
"name": "2. Set \u2014 Config Values",
"type": "n8n-nodes-base.set",
"position": [
-2336,
128
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "cfg-001",
"name": "wayinVideoApiKey",
"type": "string",
"value": "YOUR_WAYINVIDEO_API_KEY"
},
{
"id": "cfg-002",
"name": "sheetId",
"type": "string",
"value": "YOUR_GOOGLE_SHEET_ID"
},
{
"id": "cfg-003",
"name": "sheetName",
"type": "string",
"value": "Social Media Clips"
},
{
"id": "cfg-004",
"name": "recipientEmail",
"type": "string",
"value": "user@example.com"
},
{
"id": "cfg-005",
"name": "senderName",
"type": "string",
"value": "YOUR NAME"
},
{
"id": "cfg-006",
"name": "targetDuration",
"type": "string",
"value": "DURATION_30_60"
},
{
"id": "cfg-007",
"name": "exportRatio",
"type": "string",
"value": "RATIO_9_16"
},
{
"id": "cfg-008",
"name": "exportResolution",
"type": "string",
"value": "HD_720"
},
{
"id": "cfg-009",
"name": "videoUrl",
"type": "string",
"value": "={{ $json['Video URL'].trim() }}"
},
{
"id": "cfg-010",
"name": "videoTitle",
"type": "string",
"value": "={{ $json['Video Title'] }}"
},
{
"id": "cfg-011",
"name": "submittedBy",
"type": "string",
"value": "={{ $json['Your Name'] }}"
},
{
"id": "cfg-012",
"name": "maxClips",
"type": "number",
"value": "={{ Math.min(parseInt($json['Number of Clips (max 5)']) || 3, 5) }}"
},
{
"id": "cfg-013",
"name": "submittedAt",
"type": "string",
"value": "={{ $now.toFormat('dd MMM yyyy HH:mm') }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "39148735-995d-47a4-b91e-7b21e0e80907",
"name": "3. HTTP \u2014 Submit AI Clipping Task",
"type": "n8n-nodes-base.httpRequest",
"position": [
-2112,
128
],
"parameters": {
"url": "https://wayinvideo-api.wayin.ai/api/v2/clips",
"method": "POST",
"options": {},
"jsonBody": "={\n \"video_url\": \"{{ $json.videoUrl }}\",\n \"project_name\": \"{{ $json.videoTitle }}\",\n \"target_duration\": \"{{ $json.targetDuration }}\",\n \"enable_export\": false\n}",
"sendBody": true,
"sendHeaders": true,
"specifyBody": "json",
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "Authorization",
"value": "=Bearer {{ $json.wayinVideoApiKey }}"
},
{
"name": "x-wayinvideo-api-version",
"value": "v2"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "e50025bc-9a9b-4ea7-b689-a5f07cbff1f5",
"name": "4. Code \u2014 Save Clipping Project ID",
"type": "n8n-nodes-base.code",
"position": [
-1888,
128
],
"parameters": {
"jsCode": "const response = $input.first().json;\nconst config = $('2. Set \u2014 Config Values').item.json;\n\nconst projectId = response?.data?.id;\nif (!projectId) throw new Error('WayinVideo did not return a project ID. Check API key and video URL.');\n\nreturn [{\n json: {\n projectId,\n status: response.data.status || 'CREATED',\n videoTitle: config.videoTitle,\n videoUrl: config.videoUrl,\n submittedBy: config.submittedBy,\n submittedAt: config.submittedAt,\n maxClips: config.maxClips,\n wayinVideoApiKey: config.wayinVideoApiKey,\n exportRatio: config.exportRatio,\n exportResolution: config.exportResolution,\n sheetId: config.sheetId,\n sheetName: config.sheetName,\n recipientEmail: config.recipientEmail,\n senderName: config.senderName,\n pollCount: 0\n }\n}];"
},
"typeVersion": 2
},
{
"id": "266fc967-dae9-48be-b31b-927546f9224e",
"name": "5. Wait \u2014 60 Seconds",
"type": "n8n-nodes-base.wait",
"position": [
-1680,
128
],
"parameters": {
"amount": 60
},
"typeVersion": 1.1
},
{
"id": "3ea2aac8-cfe4-4f2d-99c7-f52a88365f3f",
"name": "6. HTTP \u2014 Poll Clipping Results",
"type": "n8n-nodes-base.httpRequest",
"position": [
-1456,
128
],
"parameters": {
"url": "=https://wayinvideo-api.wayin.ai/api/v2/clips/results/{{ $json.projectId }}",
"options": {},
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "=Bearer {{ $json.wayinVideoApiKey }}"
},
{
"name": "x-wayinvideo-api-version",
"value": "v2"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "b6f9a51f-bbb8-4022-8393-f440809d0feb",
"name": "7. Code \u2014 Check Clipping Status",
"type": "n8n-nodes-base.code",
"position": [
-1232,
128
],
"parameters": {
"jsCode": "const pollResponse = $input.first().json;\nconst prev = $('4. Code \u2014 Save Clipping Project ID').item.json;\n\nconst status = pollResponse?.data?.status || 'UNKNOWN';\nconst pollCount = (prev.pollCount || 0) + 1;\n\nif (pollCount >= 25 && status !== 'SUCCEEDED') {\n throw new Error('WayinVideo clipping timeout after 25 polls (~25 min). Project: ' + prev.projectId);\n}\n\nif (status === 'FAILED') {\n const errMsg = pollResponse?.data?.error_message || 'Unknown error';\n throw new Error('WayinVideo clipping failed: ' + errMsg);\n}\n\nreturn [{\n json: {\n projectId: prev.projectId,\n status,\n clips: pollResponse?.data?.clips || [],\n pollCount,\n isReady: status === 'SUCCEEDED',\n videoTitle: prev.videoTitle,\n videoUrl: prev.videoUrl,\n submittedBy: prev.submittedBy,\n submittedAt: prev.submittedAt,\n maxClips: prev.maxClips,\n wayinVideoApiKey: prev.wayinVideoApiKey,\n exportRatio: prev.exportRatio,\n exportResolution: prev.exportResolution,\n sheetId: prev.sheetId,\n sheetName: prev.sheetName,\n recipientEmail: prev.recipientEmail,\n senderName: prev.senderName\n }\n}];"
},
"typeVersion": 2
},
{
"id": "01571844-6665-4939-9836-a56f9d21e901",
"name": "8. IF \u2014 Clips Ready?",
"type": "n8n-nodes-base.if",
"position": [
-1008,
128
],
"parameters": {
"options": {},
"conditions": {
"options": {
"leftValue": "",
"caseSensitive": false,
"typeValidation": "loose"
},
"combinator": "and",
"conditions": [
{
"id": "cond-clip-ready",
"operator": {
"type": "boolean",
"operation": "true"
},
"leftValue": "={{ $json.isReady }}",
"rightValue": true
}
]
}
},
"typeVersion": 2.2
},
{
"id": "4292019b-b4d5-4c02-bca4-21381560edf1",
"name": "9. Set \u2014 Still Clipping",
"type": "n8n-nodes-base.set",
"position": [
-1008,
320
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "loop-clip-001",
"name": "result",
"type": "string",
"value": "Clipping still processing \u2014 looping back."
}
]
}
},
"typeVersion": 3.4
},
{
"id": "5b794245-7810-46e5-b63a-5b0dd96297cc",
"name": "10. Code \u2014 Select Top Clips for Export",
"type": "n8n-nodes-base.code",
"position": [
-800,
-32
],
"parameters": {
"jsCode": "const data = $input.first().json;\nconst allClips = data.clips || [];\n\nif (allClips.length === 0) {\n throw new Error('WayinVideo returned no clips for this video.');\n}\n\nconst topClips = [...allClips]\n .sort((a, b) => (b.score || 0) - (a.score || 0))\n .slice(0, data.maxClips || 3);\n\nconst clipIndices = topClips.map(c => c.idx);\n\nreturn [{\n json: {\n projectId: data.projectId,\n clipIndices,\n topClips,\n totalFound: allClips.length,\n exporting: topClips.length,\n videoTitle: data.videoTitle,\n submittedBy: data.submittedBy,\n submittedAt: data.submittedAt,\n wayinVideoApiKey: data.wayinVideoApiKey,\n exportRatio: data.exportRatio,\n exportResolution: data.exportResolution,\n sheetId: data.sheetId,\n sheetName: data.sheetName,\n recipientEmail: data.recipientEmail,\n senderName: data.senderName\n }\n}];"
},
"typeVersion": 2
},
{
"id": "66763eaa-7845-4cb3-9f00-4dc6a85c15bb",
"name": "11. HTTP \u2014 Submit Export Task",
"type": "n8n-nodes-base.httpRequest",
"position": [
-576,
-32
],
"parameters": {
"url": "https://wayinvideo-api.wayin.ai/api/v2/clips/export",
"method": "POST",
"options": {},
"jsonBody": "={\n \"project_id\": \"{{ $json.projectId }}\",\n \"clip_indices\": {{ JSON.stringify($json.clipIndices) }},\n \"resolution\": \"{{ $json.exportResolution }}\",\n \"enable_caption\": true,\n \"caption_display\": \"original\",\n \"cc_style_tpl\": \"temp-7\",\n \"enable_ai_hook\": true,\n \"ai_hook_script_style\": \"excited\",\n \"ai_hook_position\": \"beginning\",\n \"enable_ai_reframe\": true,\n \"ratio\": \"{{ $json.exportRatio }}\"\n}",
"sendBody": true,
"sendHeaders": true,
"specifyBody": "json",
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "Authorization",
"value": "=Bearer {{ $json.wayinVideoApiKey }}"
},
{
"name": "x-wayinvideo-api-version",
"value": "v2"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "92f69111-8959-4371-8d18-350c2c292389",
"name": "12. Code \u2014 Save Export Task ID",
"type": "n8n-nodes-base.code",
"position": [
-352,
-32
],
"parameters": {
"jsCode": "const response = $input.first().json;\nconst prev = $('10. Code \u2014 Select Top Clips for Export').item.json;\n\nconst exportTaskId = response?.data?.export_task_id;\nif (!exportTaskId) throw new Error('WayinVideo export did not return export_task_id.');\n\nreturn [{\n json: {\n exportTaskId,\n exportStatus: response.data.status || 'CREATED',\n topClips: prev.topClips,\n totalFound: prev.totalFound,\n exporting: prev.exporting,\n videoTitle: prev.videoTitle,\n submittedBy: prev.submittedBy,\n submittedAt: prev.submittedAt,\n wayinVideoApiKey: prev.wayinVideoApiKey,\n exportRatio: prev.exportRatio,\n sheetId: prev.sheetId,\n sheetName: prev.sheetName,\n recipientEmail: prev.recipientEmail,\n senderName: prev.senderName,\n exportPollCount: 0\n }\n}];"
},
"typeVersion": 2
},
{
"id": "a6306212-c6f1-4d28-b6f8-13d58b519a2f",
"name": "13. Wait \u2014 60 Seconds (Export)",
"type": "n8n-nodes-base.wait",
"position": [
-128,
-32
],
"parameters": {
"amount": 60
},
"typeVersion": 1.1
},
{
"id": "70a82d8a-ca42-4000-a677-8e9d925b42bb",
"name": "14. HTTP \u2014 Poll Export Results",
"type": "n8n-nodes-base.httpRequest",
"position": [
96,
-32
],
"parameters": {
"url": "=https://wayinvideo-api.wayin.ai/api/v2/clips/export/{{ $json.exportTaskId }}",
"options": {},
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "=Bearer {{ $json.wayinVideoApiKey }}"
},
{
"name": "x-wayinvideo-api-version",
"value": "v2"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "9fd097c5-49c7-4f54-923c-ee63dfb947b9",
"name": "15. Code \u2014 Check Export Status",
"type": "n8n-nodes-base.code",
"position": [
320,
-32
],
"parameters": {
"jsCode": "const pollResponse = $input.first().json;\nconst prev = $('12. Code \u2014 Save Export Task ID').item.json;\n\nconst status = pollResponse?.data?.status || 'UNKNOWN';\nconst exportPollCount = (prev.exportPollCount || 0) + 1;\n\nif (exportPollCount >= 20 && status !== 'SUCCEEDED') {\n throw new Error('WayinVideo export timeout after 20 polls (~20 min). Export: ' + prev.exportTaskId);\n}\n\nif (status === 'FAILED') {\n throw new Error('WayinVideo export failed: ' + (pollResponse?.data?.error_message || 'Unknown error'));\n}\n\nreturn [{\n json: {\n exportTaskId: prev.exportTaskId,\n exportStatus: status,\n exportedClips: pollResponse?.data?.clips || [],\n exportPollCount,\n isExportReady: status === 'SUCCEEDED',\n topClips: prev.topClips,\n totalFound: prev.totalFound,\n videoTitle: prev.videoTitle,\n submittedBy: prev.submittedBy,\n submittedAt: prev.submittedAt,\n wayinVideoApiKey: prev.wayinVideoApiKey,\n sheetId: prev.sheetId,\n sheetName: prev.sheetName,\n recipientEmail: prev.recipientEmail,\n senderName: prev.senderName\n }\n}];"
},
"typeVersion": 2
},
{
"id": "837e0380-675b-4367-8382-556c88331e77",
"name": "16. IF \u2014 Export Ready?",
"type": "n8n-nodes-base.if",
"position": [
544,
-32
],
"parameters": {
"options": {},
"conditions": {
"options": {
"leftValue": "",
"caseSensitive": false,
"typeValidation": "loose"
},
"combinator": "and",
"conditions": [
{
"id": "cond-export-ready",
"operator": {
"type": "boolean",
"operation": "true"
},
"leftValue": "={{ $json.isExportReady }}",
"rightValue": true
}
]
}
},
"typeVersion": 2.2
},
{
"id": "81ac7d67-e015-4d10-9df9-9d0234c5e42c",
"name": "17. Set \u2014 Still Exporting",
"type": "n8n-nodes-base.set",
"position": [
544,
176
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "loop-exp-001",
"name": "result",
"type": "string",
"value": "Export still rendering \u2014 looping back."
}
]
}
},
"typeVersion": 3.4
},
{
"id": "f32c5002-a49f-47aa-9a6c-2beb5be91d8c",
"name": "18. Code \u2014 Build Sheet Rows",
"type": "n8n-nodes-base.code",
"position": [
768,
-176
],
"parameters": {
"jsCode": "const data = $input.first().json;\nconst exportedClips = data.exportedClips || [];\nconst topClips = data.topClips || [];\n\nconst clipsWithLinks = topClips.map(tc => {\n const exported = exportedClips.find(ec => ec.idx === tc.idx);\n return {\n ...tc,\n exportLink: exported?.export_link || 'Processing'\n };\n});\n\nconst msToTime = ms => {\n const s = Math.floor((ms || 0) / 1000);\n return Math.floor(s / 60) + ':' + String(s % 60).padStart(2, '0');\n};\n\nconst loggedAt = new Date().toISOString().replace('T', ' ').substring(0, 16);\nconst today = new Date().toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' });\n\nconst sheetRows = clipsWithLinks.map((clip, i) => ({\n date: today,\n videoTitle: data.videoTitle,\n clipNum: i + 1,\n clipTitle: clip.title || 'Clip ' + (i + 1),\n durationSec: Math.round(((clip.end_ms || 0) - (clip.begin_ms || 0)) / 1000),\n viralScore: clip.score || 0,\n tags: (clip.tags || []).join(', '),\n description: (clip.desc || '').substring(0, 200),\n exportLink: clip.exportLink,\n loggedAt,\n sheetId: data.sheetId,\n sheetName: data.sheetName,\n isLastRow: i === clipsWithLinks.length - 1,\n clipsWithLinks: i === clipsWithLinks.length - 1 ? clipsWithLinks : [],\n totalFound: data.totalFound,\n submittedBy: data.submittedBy,\n submittedAt: data.submittedAt,\n recipientEmail: data.recipientEmail,\n senderName: data.senderName\n}));\n\nreturn sheetRows.map(r => ({ json: r }));"
},
"typeVersion": 2
},
{
"id": "bf16a703-45b2-443f-bbdb-81f18aebc752",
"name": "19. Google Sheets \u2014 Log Clips",
"type": "n8n-nodes-base.googleSheets",
"position": [
976,
-176
],
"parameters": {
"columns": {
"value": {
"Date": "={{ $json.date }}",
"Tags": "={{ $json.tags }}",
"Clip #": "={{ $json.clipNum }}",
"Logged At": "={{ $json.loggedAt }}",
"Clip Title": "={{ $json.clipTitle }}",
"Description": "={{ $json.description }}",
"Export Link": "={{ $json.exportLink }}",
"Video Title": "={{ $json.videoTitle }}",
"Viral Score": "={{ $json.viralScore }}",
"Duration (sec)": "={{ $json.durationSec }}"
},
"mappingMode": "defineBelow"
},
"options": {
"cellFormat": "USER_ENTERED"
},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "name",
"value": "={{ $json.sheetName }}"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "={{ $json.sheetId }}"
}
},
"typeVersion": 4.5
},
{
"id": "794c667f-4d9d-4eb9-9d22-affc0f1756b5",
"name": "20. IF \u2014 Last Row?",
"type": "n8n-nodes-base.if",
"position": [
1200,
-176
],
"parameters": {
"options": {},
"conditions": {
"options": {
"leftValue": "",
"caseSensitive": false,
"typeValidation": "loose"
},
"combinator": "and",
"conditions": [
{
"id": "cond-last",
"operator": {
"type": "boolean",
"operation": "true"
},
"leftValue": "={{ $json.isLastRow }}",
"rightValue": true
}
]
}
},
"typeVersion": 2.2
},
{
"id": "b81e589f-4721-43ed-a17d-57990e7d9239",
"name": "21. Code \u2014 Build Gmail Digest",
"type": "n8n-nodes-base.code",
"position": [
1424,
-336
],
"parameters": {
"jsCode": "const data = $json;\nconst clips = data.clipsWithLinks || [];\n\nlet clipLines = '';\nclips.forEach((clip, i) => {\n const dur = Math.round(((clip.end_ms || 0) - (clip.begin_ms || 0)) / 1000);\n const tags = (clip.tags || []).join(', ');\n clipLines +=\n '\\n--- Clip ' + (i + 1) + ' ---\\n' +\n 'Title: ' + (clip.title || 'Untitled') + '\\n' +\n 'Duration: ' + dur + ' seconds | Viral Score: ' + (clip.score || 0) + '/100\\n' +\n 'Tags: ' + tags + '\\n' +\n 'Description: ' + (clip.desc || '').substring(0, 150) + '\\n' +\n 'Download Link: ' + (clip.exportLink || 'Not available') + '\\n';\n});\n\nconst emailSubject = 'Social Media Clips Ready \u2014 ' + data.videoTitle;\n\nconst emailBody =\n 'Hi ' + data.submittedBy + ',\\n\\n' +\n 'Your social media clips are ready! Here are the top ' + clips.length + ' clips from your webinar.\\n\\n' +\n 'VIDEO: ' + data.videoTitle + '\\n' +\n 'Total clips found: ' + data.totalFound + ' | Exported: ' + clips.length + '\\n' +\n 'Format: 9:16 vertical | Captions: Yes | AI Hook: Yes\\n' +\n 'Submitted: ' + data.submittedAt + '\\n' +\n clipLines +\n '\\nIMPORTANT: Download links expire in 24 hours. Download now!\\n\\n' +\n 'All clips also logged in Google Sheets for reference.\\n\\n' +\n 'Best regards,\\n' +\n data.senderName;\n\nreturn [{\n json: {\n emailSubject,\n emailBody,\n recipientEmail: data.recipientEmail\n }\n}];"
},
"typeVersion": 2
},
{
"id": "9049c329-56c6-4c18-8dbe-91309f9412e9",
"name": "22. Gmail \u2014 Send Clips Digest",
"type": "n8n-nodes-base.gmail",
"position": [
1648,
-336
],
"parameters": {
"sendTo": "={{ $json.recipientEmail }}",
"message": "={{ $json.emailBody }}",
"options": {
"appendAttribution": false
},
"subject": "={{ $json.emailSubject }}"
},
"typeVersion": 2.1
},
{
"id": "83ee9550-aa9d-494e-bbfb-796f999d8938",
"name": "23. Set \u2014 More Rows",
"type": "n8n-nodes-base.set",
"position": [
1424,
-32
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "more-rows-001",
"name": "result",
"type": "string",
"value": "More rows being logged."
}
]
}
},
"typeVersion": 3.4
}
],
"connections": {
"20. IF \u2014 Last Row?": {
"main": [
[
{
"node": "21. Code \u2014 Build Gmail Digest",
"type": "main",
"index": 0
}
],
[
{
"node": "23. Set \u2014 More Rows",
"type": "main",
"index": 0
}
]
]
},
"5. Wait \u2014 60 Seconds": {
"main": [
[
{
"node": "6. HTTP \u2014 Poll Clipping Results",
"type": "main",
"index": 0
}
]
]
},
"8. IF \u2014 Clips Ready?": {
"main": [
[
{
"node": "10. Code \u2014 Select Top Clips for Export",
"type": "main",
"index": 0
}
],
[
{
"node": "9. Set \u2014 Still Clipping",
"type": "main",
"index": 0
}
]
]
},
"16. IF \u2014 Export Ready?": {
"main": [
[
{
"node": "18. Code \u2014 Build Sheet Rows",
"type": "main",
"index": 0
}
],
[
{
"node": "17. Set \u2014 Still Exporting",
"type": "main",
"index": 0
}
]
]
},
"2. Set \u2014 Config Values": {
"main": [
[
{
"node": "3. HTTP \u2014 Submit AI Clipping Task",
"type": "main",
"index": 0
}
]
]
},
"9. Set \u2014 Still Clipping": {
"main": [
[
{
"node": "5. Wait \u2014 60 Seconds",
"type": "main",
"index": 0
}
]
]
},
"1. Form \u2014 Enter Video URL": {
"main": [
[
{
"node": "2. Set \u2014 Config Values",
"type": "main",
"index": 0
}
]
]
},
"17. Set \u2014 Still Exporting": {
"main": [
[
{
"node": "13. Wait \u2014 60 Seconds (Export)",
"type": "main",
"index": 0
}
]
]
},
"18. Code \u2014 Build Sheet Rows": {
"main": [
[
{
"node": "19. Google Sheets \u2014 Log Clips",
"type": "main",
"index": 0
}
]
]
},
"11. HTTP \u2014 Submit Export Task": {
"main": [
[
{
"node": "12. Code \u2014 Save Export Task ID",
"type": "main",
"index": 0
}
]
]
},
"19. Google Sheets \u2014 Log Clips": {
"main": [
[
{
"node": "20. IF \u2014 Last Row?",
"type": "main",
"index": 0
}
]
]
},
"21. Code \u2014 Build Gmail Digest": {
"main": [
[
{
"node": "22. Gmail \u2014 Send Clips Digest",
"type": "main",
"index": 0
}
]
]
},
"12. Code \u2014 Save Export Task ID": {
"main": [
[
{
"node": "13. Wait \u2014 60 Seconds (Export)",
"type": "main",
"index": 0
}
]
]
},
"13. Wait \u2014 60 Seconds (Export)": {
"main": [
[
{
"node": "14. HTTP \u2014 Poll Export Results",
"type": "main",
"index": 0
}
]
]
},
"14. HTTP \u2014 Poll Export Results": {
"main": [
[
{
"node": "15. Code \u2014 Check Export Status",
"type": "main",
"index": 0
}
]
]
},
"15. Code \u2014 Check Export Status": {
"main": [
[
{
"node": "16. IF \u2014 Export Ready?",
"type": "main",
"index": 0
}
]
]
},
"6. HTTP \u2014 Poll Clipping Results": {
"main": [
[
{
"node": "7. Code \u2014 Check Clipping Status",
"type": "main",
"index": 0
}
]
]
},
"7. Code \u2014 Check Clipping Status": {
"main": [
[
{
"node": "8. IF \u2014 Clips Ready?",
"type": "main",
"index": 0
}
]
]
},
"3. HTTP \u2014 Submit AI Clipping Task": {
"main": [
[
{
"node": "4. Code \u2014 Save Clipping Project ID",
"type": "main",
"index": 0
}
]
]
},
"4. Code \u2014 Save Clipping Project ID": {
"main": [
[
{
"node": "5. Wait \u2014 60 Seconds",
"type": "main",
"index": 0
}
]
]
},
"10. Code \u2014 Select Top Clips for Export": {
"main": [
[
{
"node": "11. HTTP \u2014 Submit Export Task",
"type": "main",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Submit any YouTube, Vimeo, or Zoom webinar URL using a simple form and the workflow handles everything from there. It runs a two-phase pipeline: first identifying the top viral moments in your video without rendering anything, then exporting only the best clips as ready-to-post…
Source: https://n8n.io/workflows/15118/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
Stop chasing blurry receipts and manually typing expense data. This workflow creates an intelligent, "snap-and-submit" reimbursement pipeline that hosts photos via UploadToURL, extracts deep data via
Shopify and E-Commerce store owners often struggle to create engaging 3D videos from static product images. This workflow automates that entire process—from image upload to video delivery—so store own
Streamline Your Zoom Meetings With Secure Automated Stripe Payments. Uses zoom, httpRequest, gmail, googleSheets. Event-driven trigger; 20 nodes.
Streamline Your Zoom Meetings with Secure, Automated Stripe Payments. Uses zoom, httpRequest, gmail, googleSheets. Event-driven trigger; 20 nodes.
🎉 Do you want to master AI automation, so you can save time and build cool stuff?