This workflow follows the Executecommand → 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 →
{
"name": "KZ-01-Ingestion",
"nodes": [
{
"parameters": {
"rule": {
"interval": [
{
"field": "minutes",
"minutesInterval": 5
}
]
}
},
"name": "Cron 5min",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.1,
"position": [
240,
300
]
},
{
"parameters": {
"resource": "fileFolder",
"operation": "list",
"options": {
"fields": [
"id",
"name",
"mimeType",
"modifiedTime",
"size",
"parents"
],
"q": "'={{$json[\"DRIVE_INBOX_FOLDER_ID\"]}}' in parents and trashed = false and (mimeType contains 'video/')"
}
},
"name": "List Drive Inbox",
"type": "n8n-nodes-base.googleDrive",
"typeVersion": 3,
"position": [
460,
300
],
"credentials": {
"googleDriveOAuth2Api": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"batchSize": 1,
"options": {}
},
"name": "Iterate",
"type": "n8n-nodes-base.splitInBatches",
"typeVersion": 3,
"position": [
680,
300
]
},
{
"parameters": {
"conditions": {
"boolean": [],
"string": [
{
"value1": "={{ $json[\"mimeType\"] }}",
"operation": "startsWith",
"value2": "video/"
}
]
}
},
"name": "Is Video",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
900,
300
]
},
{
"parameters": {
"resource": "file",
"operation": "download",
"fileId": "={{ $json[\"id\"] }}"
},
"name": "Download File",
"type": "n8n-nodes-base.googleDrive",
"typeVersion": 3,
"position": [
1120,
220
],
"credentials": {
"googleDriveOAuth2Api": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"command": "=ffprobe -v error -show_streams -show_format -of json {{$binary.data.fileName}}"
},
"name": "ffprobe",
"type": "n8n-nodes-base.executeCommand",
"typeVersion": 1,
"position": [
1340,
220
]
},
{
"parameters": {
"functionCode": "// Generate job_id and clip_id; infer cam from filename + EXIF\nconst fn = $input.first().json.name || '';\nconst nowDate = new Date().toISOString().slice(0,10).replace(/-/g,'');\n\nlet cam = 'A';\nif (/^DJI/i.test(fn)) cam = 'C';\nelse if (/^G[HX]/i.test(fn) || /^INS_/i.test(fn) || /^LRV/i.test(fn)) cam = 'D';\nelse if (/^IMG/i.test(fn)) cam = 'A';\n\nconst service = 'OTHER'; // placeholder until slate parser fires\nconst seq = '01'; // resolve from Supabase select max+1 in next node\nconst job_id = `${nowDate}-${service}-${seq}`;\nconst clip_id = `${job_id}-${cam}-001`;\n\nreturn [{ json: { job_id, clip_id, cam, source_name: fn } }];"
},
"name": "Generate IDs",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1560,
220
]
},
{
"parameters": {
"command": "=whisper-ctranslate2 --model large-v3 --language auto --output_format txt --max_duration 8 --vad_filter True {{$binary.data.fileName}} > slate.txt && head -c 2000 slate.txt"
},
"name": "Whisper Slate",
"type": "n8n-nodes-base.executeCommand",
"typeVersion": 1,
"position": [
1780,
220
]
},
{
"parameters": {
"functionCode": "// Parse address, service, phase from slate transcript\nconst t = ($input.first().json.stdout || '').toLowerCase();\nconst phase = /\\bbefore|\u0434\u043e\\b/.test(t) ? 'before'\n : /\\bafter|\u043f\u043e\u0441\u043b\u0435\\b/.test(t) ? 'after'\n : 'unknown';\n\nconst svcMap = {\n 'lawn': 'MOW','mow':'MOW','\u0433\u0430\u0437\u043e\u043d':'MOW',\n 'overgrow': 'OVR','\u0437\u0430\u0440\u043e\u0441':'OVR',\n 'pool': 'POO','\u0431\u0430\u0441\u0441\u0435\u0439\u043d':'POO',\n 'stump':'STM','\u043f\u0435\u043d\u044c':'STM',\n 'tree':'TRE','\u0434\u0435\u0440\u0435\u0432':'TRE',\n 'clear':'CLR','\u0440\u0430\u0441\u0447':'CLR',\n 'clean':'CLN','\u0443\u0431\u043e\u0440\u043a':'CLN',\n 'plow':'PLW','\u0432\u0441\u043f\u0430':'PLW',\n 'maint':'MNT'\n};\nlet service = 'OTHER';\nfor (const k of Object.keys(svcMap)) { if (t.includes(k)) { service = svcMap[k]; break; } }\n\nconst addrMatch = t.match(/([a-z\u0430-\u044f0-9\\-.\\s]{4,80})(?:,| \u0434\u0430\u0442\u0430| address)/i);\nconst address = addrMatch ? addrMatch[1].trim() : null;\n\nreturn [{ json: { service, phase, address, slate_transcript: t } }];"
},
"name": "Parse Slate",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
2000,
220
]
},
{
"parameters": {
"url": "=https://{{$env[\"R2_ACCOUNT_ID\"]}}.r2.cloudflarestorage.com/{{$env[\"R2_BUCKET\"]}}/raw/{{$now.year}}/{{$now.month.padStart(2,'0')}}/{{$now.day.padStart(2,'0')}}/{{$json[\"job_id\"]}}/{{$json[\"clip_id\"]}}.mp4",
"method": "PUT",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "awsCredential",
"sendBinaryData": true,
"binaryPropertyName": "data",
"options": {}
},
"name": "R2 Upload Raw",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
2220,
220
],
"credentials": {
"awsCredential": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"command": "=ffmpeg -y -ss 00:00:02 -i {{$binary.data.fileName}} -frames:v 1 -q:v 2 thumb.jpg && stat -c '%s' thumb.jpg"
},
"name": "Make Thumbnail",
"type": "n8n-nodes-base.executeCommand",
"typeVersion": 1,
"position": [
2440,
220
]
},
{
"parameters": {
"tableId": "clips",
"dataMode": "autoMapInputData",
"fieldsUi": {
"fieldValues": [
{
"fieldId": "clip_id",
"fieldValue": "={{$json[\"clip_id\"]}}"
},
{
"fieldId": "job_id",
"fieldValue": "={{$json[\"job_id\"]}}"
},
{
"fieldId": "cam",
"fieldValue": "={{$json[\"cam\"]}}"
},
{
"fieldId": "shot_seq",
"fieldValue": "=1"
},
{
"fieldId": "storage_key",
"fieldValue": "=raw/{{$now.year}}/{{$now.month.padStart(2,'0')}}/{{$now.day.padStart(2,'0')}}/{{$json[\"job_id\"]}}/{{$json[\"clip_id\"]}}.mp4"
},
{
"fieldId": "duration_s",
"fieldValue": "={{$json[\"duration_s\"]}}"
},
{
"fieldId": "slate_address",
"fieldValue": "={{$json[\"address\"]}}"
},
{
"fieldId": "slate_service",
"fieldValue": "={{$json[\"service\"]}}"
},
{
"fieldId": "slate_phase",
"fieldValue": "={{$json[\"phase\"]}}"
},
{
"fieldId": "status",
"fieldValue": "ingested"
}
]
}
},
"name": "Insert clip row",
"type": "n8n-nodes-base.supabase",
"typeVersion": 1,
"position": [
2660,
220
],
"credentials": {
"supabaseApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"resource": "file",
"operation": "update",
"fileId": "={{$json[\"id\"]}}",
"options": {
"parents": "={{$env[\"DRIVE_ARCHIVE_FOLDER_ID\"]}}"
}
},
"name": "Move to _archived",
"type": "n8n-nodes-base.googleDrive",
"typeVersion": 3,
"position": [
2880,
220
],
"credentials": {
"googleDriveOAuth2Api": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"url": "={{$env[\"N8N_EVENT_BUS_URL\"]}}/events",
"method": "POST",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"workflow\": \"02-classification\",\n \"clip_id\": \"{{$json[\"clip_id\"]}}\"\n}"
},
"name": "Enqueue Classify",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
3100,
220
]
}
],
"connections": {
"Cron 5min": {
"main": [
[
{
"node": "List Drive Inbox",
"type": "main",
"index": 0
}
]
]
},
"List Drive Inbox": {
"main": [
[
{
"node": "Iterate",
"type": "main",
"index": 0
}
]
]
},
"Iterate": {
"main": [
[
{
"node": "Is Video",
"type": "main",
"index": 0
}
]
]
},
"Is Video": {
"main": [
[
{
"node": "Download File",
"type": "main",
"index": 0
}
]
]
},
"Download File": {
"main": [
[
{
"node": "ffprobe",
"type": "main",
"index": 0
}
]
]
},
"ffprobe": {
"main": [
[
{
"node": "Generate IDs",
"type": "main",
"index": 0
}
]
]
},
"Generate IDs": {
"main": [
[
{
"node": "Whisper Slate",
"type": "main",
"index": 0
}
]
]
},
"Whisper Slate": {
"main": [
[
{
"node": "Parse Slate",
"type": "main",
"index": 0
}
]
]
},
"Parse Slate": {
"main": [
[
{
"node": "R2 Upload Raw",
"type": "main",
"index": 0
}
]
]
},
"R2 Upload Raw": {
"main": [
[
{
"node": "Make Thumbnail",
"type": "main",
"index": 0
}
]
]
},
"Make Thumbnail": {
"main": [
[
{
"node": "Insert clip row",
"type": "main",
"index": 0
}
]
]
},
"Insert clip row": {
"main": [
[
{
"node": "Move to _archived",
"type": "main",
"index": 0
}
]
]
},
"Move to _archived": {
"main": [
[
{
"node": "Enqueue Classify",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1"
},
"tags": [
"kontent-zavod",
"ingestion"
]
}
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.
awsCredentialgoogleDriveOAuth2ApisupabaseApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
KZ-01-Ingestion. Uses googleDrive, executeCommand, httpRequest, supabase. Scheduled trigger; 14 nodes.
Source: https://github.com/alexdmitrievi/Kontent_zavod_podryadpro/blob/claude/ai-content-factory-design-hzhVn/workflows/01-ingestion.json — 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.
Automated Knowledge Management Backup & Recovery. Uses executeCommand, postgres, httpRequest, googleDrive. Scheduled trigger; 30 nodes.
This workflow is a multi-system document synchronization pipeline built in n8n, designed to automatically sync and back up files between Microsoft SharePoint, Supabase/Postgres, and Google Drive.
This workflow solves a common problem with RSS feeds: they often only provide a short summary or snippet of the full article. This template automatically monitors a list of your favorite blog RSS feed
Post Scheduler. Uses postgres, googleDrive, httpRequest. Scheduled trigger; 20 nodes.
03 - Recordatorio 4h (CON VERIFICACIÓN) ✅. Uses supabase, httpRequest, twilio. Scheduled trigger; 17 nodes.