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": "Shorts Clip Extractor (MinIO Source)",
"nodes": [
{
"parameters": {},
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [
16,
96
],
"id": "ff8e0d15-9b3b-465d-9a0f-e2b49187400b",
"name": "When clicking 'Execute workflow'"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "src-video",
"name": "source_video_url",
"value": "http://host.docker.internal:9000/raw-videos/microsoft.mp4",
"type": "string"
},
{
"id": "base_url",
"name": "base_url",
"value": "http://host.docker.internal:8080",
"type": "string"
},
{
"id": "api_key",
"name": "api_key",
"value": "thekey",
"type": "string"
},
{
"id": "lm_studio_url",
"name": "lm_studio_url",
"value": "http://host.docker.internal:1234/api/v1/chat",
"type": "string"
},
{
"id": "lm_model",
"name": "lm_model",
"value": "google/gemma-4-e4b:2",
"type": "string"
},
{
"id": "clip_count",
"name": "clip_count",
"value": 3,
"type": "number"
},
{
"id": "clip_duration",
"name": "clip_duration",
"value": 60,
"type": "number"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
320,
96
],
"id": "ffd82f79-0f97-45d7-a939-805b9070c131",
"name": "Set Variables"
},
{
"parameters": {
"method": "POST",
"url": "={{ $('Set Variables').first().json.base_url }}/v1/media/transcribe",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "x-api-key",
"value": "={{ $('Set Variables').first().json.api_key }}"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={ \"media_url\": \"{{ $('Set Variables').first().json.source_video_url }}\", \"language\": \"tr\", \"include_segments\": true, \"word_timestamps\": false, \"response_type\": \"direct\" }",
"options": {
"timeout": 1800000
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
800,
96
],
"id": "d2ca2bfe-fd0b-415f-8d59-6c3fc0c8f638",
"name": "Transcribe (Turkish)"
},
{
"parameters": {
"jsCode": "const segments = $('Transcribe (Turkish)').first().json.response.segments;\nconst videoUrl = $('Set Variables').first().json.source_video_url;\n\n// Use all segments directly, no chunking - compact format for large transcripts\nconst transcriptText = segments.map((s, i) => `[${i}]${s.start.toFixed(0)}s: ${s.text}`).join(' ');\n\nconst prompt = `Viral video uzman\u0131s\u0131n. Transkripsiyonu analiz et, en viral potansiyelli k\u0131s\u0131mlar\u0131 se\u00e7.\n\nKRITER: Duygusal etki, hikaye, payla\u015f\u0131labilirlik.\n\nHer se\u00e7im i\u00e7in JSON objesi:\n{\"chunk_index\":id,\"start\":saniye,\"end\":saniye(start+60 max),\"viral_score\":1-10,\"reason\":\"k\u0131sa\",\"hook\":\"3sn\"}\n\nTRANSCRIPSYON:\n${transcriptText}\n\nSADECE JSON array d\u00f6nd\u00fcr, ba\u015fka hi\u00e7bir \u015fey yazma.`;\n\n// Create 60s chunks for post-analysis reference\nconst chunkSize = 60;\nconst chunks = [];\nlet currentChunk = { start: null, end: null, texts: [] };\nsegments.forEach(seg => {\n if (currentChunk.start === null) {\n currentChunk.start = seg.start;\n currentChunk.end = seg.end;\n currentChunk.texts.push(seg.text);\n } else if (seg.end - currentChunk.start <= chunkSize) {\n currentChunk.end = seg.end;\n currentChunk.texts.push(seg.text);\n } else {\n chunks.push({ start: currentChunk.start, end: currentChunk.end, text: currentChunk.texts.join(' ').trim() });\n currentChunk = { start: seg.start, end: seg.end, texts: [seg.text] };\n }\n});\nif (currentChunk.texts.length > 0) chunks.push({ start: currentChunk.start, end: currentChunk.end, text: currentChunk.texts.join(' ').trim() });\n\nreturn [{ json: { prompt, chunks, video_url: videoUrl } }];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1040,
96
],
"id": "3264e21c-506f-47bf-8f60-dbed5579fb98",
"name": "Prepare AI Analysis Prompt"
},
{
"parameters": {
"method": "POST",
"url": "={{ $('Set Variables').first().json.lm_studio_url }}",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={{ JSON.stringify({ model: $('Set Variables').first().json.lm_model, system_prompt: 'You are a YouTube viral content expert. Output ONLY valid JSON.', input: $json.prompt, stream: false}) }}",
"options": {
"timeout": 300000
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1280,
96
],
"id": "55bdd894-f250-4ac7-8ced-b079aa6ff12f",
"name": "\ud83e\udd16 LM Studio - Viral Clip Analysis"
},
{
"parameters": {
"jsCode": "const lmResponse = $('\ud83e\udd16 LM Studio - Viral Clip Analysis').first().json;\n\n// Extract AI response text from Gemma format\nlet aiResponse = '';\nif (lmResponse.output && Array.isArray(lmResponse.output)) {\n const msgObj = lmResponse.output.find(o => o.type === 'message');\n if (msgObj) aiResponse = msgObj.content;\n}\nif (!aiResponse) {\n aiResponse = lmResponse.message?.content || lmResponse.choices?.[0]?.message?.content || lmResponse.response || lmResponse.content || '';\n}\n\n// Strip markdown code fences if present\naiResponse = aiResponse.replace(/^```(?:json)?\\n?([\\s\\S]*?)\\n?```$/gm, '$1').trim();\n\nconst videoUrl = $('Prepare AI Analysis Prompt').first().json.video_url;\nconst segments = $('Transcribe (Turkish)').first().json.response.segments;\nconst clipCount = $('Set Variables').first().json.clip_count;\nconst clipDuration = $('Set Variables').first().json.clip_duration;\n\nlet scoredClips;\ntry {\n const jsonMatch = aiResponse.match(/\\[[\\s\\S]*\\]/);\n if (jsonMatch) {\n scoredClips = JSON.parse(jsonMatch[0]);\n } else {\n const parsed = JSON.parse(aiResponse);\n scoredClips = parsed.clips || parsed.results || [parsed];\n }\n} catch (e) {\n throw new Error('AI response parsing failed: ' + e.message + '\\n\\nRaw response: ' + aiResponse);\n}\n\nconst topClips = scoredClips\n .sort((a, b) => (b.viral_score || 0) - (a.viral_score || 0))\n .slice(0, clipCount)\n .map(clip => {\n const startTime = clip.start;\n const actualEnd = Math.min(clip.end || startTime + clipDuration, startTime + clipDuration);\n const closestSeg = segments.find(s => Math.abs(s.start - startTime) < 2);\n const textPreview = closestSeg?.text?.substring(0, 100) || 'N/A';\n return {\n start_time: startTime,\n end_time: actualEnd,\n viral_score: clip.viral_score,\n reason: clip.reason,\n hook: clip.hook,\n text_preview: textPreview\n };\n });\n\nreturn [{ json: { clips: topClips, video_url: videoUrl, total_analyzed: segments.length, ai_recommendations: topClips.length } }];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1520,
96
],
"id": "9c069345-c7c8-46b3-9438-e3f38c9cbb88",
"name": "Parse AI Results & Select Clips"
},
{
"parameters": {
"fieldToSplitOut": "clips",
"options": {}
},
"type": "n8n-nodes-base.splitOut",
"typeVersion": 1,
"position": [
1760,
96
],
"id": "5f74d6a4-0469-402b-86f5-60d5dc4d4b9d",
"name": "Split Clips"
},
{
"parameters": {
"method": "POST",
"url": "={{ $('Set Variables').first().json.base_url }}/v1/ffmpeg/compose",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "x-api-key",
"value": "={{ $('Set Variables').first().json.api_key }}"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={{ JSON.stringify({ inputs: [{ file_url: $('Set Variables').first().json.source_video_url }], outputs: [{ options: [{ option: '-ss', argument: String($json.start_time) }, { option: '-t', argument: String($json.end_time - $json.start_time) }, { option: '-c:v', argument: 'libx264' }, { option: '-preset', argument: 'fast' }, { option: '-crf', argument: '23' }, { option: '-c:a', argument: 'aac' }] }], id: 'extract-clip-' + $json.start_time.toFixed(0) }) }}",
"options": {
"timeout": 600000
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
2000,
96
],
"id": "c025a7ae-b234-4ee0-907f-2622e65b535a",
"name": "Extract AI-Selected Clip"
},
{
"parameters": {
"method": "POST",
"url": "={{ $('Set Variables').first().json.base_url }}/v1/ffmpeg/compose",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "x-api-key",
"value": "={{ $('Set Variables').first().json.api_key }}"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"inputs\": [\n {\n \"file_url\": \"{{ $json.response[0].file_url }}\"\n }\n ],\n \"filters\": [\n {\n \"filter\": \"crop=w=ih*9/16:h=ih\"\n }\n ],\n \"outputs\": [\n {\n \"options\": [\n {\n \"option\": \"-c:v\",\n \"argument\": \"libx264\"\n },\n {\n \"option\": \"-preset\",\n \"argument\": \"fast\"\n },\n {\n \"option\": \"-crf\",\n \"argument\": \"23\"\n },\n {\n \"option\": \"-c:a\",\n \"argument\": \"aac\"\n }\n ]\n }\n ],\n \"id\": \"resize-clip-{{ $now.format('x') }}\"\n}",
"options": {
"timeout": 600000
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
2240,
96
],
"id": "3075182b-f738-45c6-a671-fcb92513e46b",
"name": "Resize to 9:16 (Shorts)"
},
{
"parameters": {
"method": "POST",
"url": "={{ $('Set Variables').first().json.base_url }}/v1/video/caption",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "x-api-key",
"value": "={{ $('Set Variables').first().json.api_key }}"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"video_url\": \"{{ $('Resize to 9:16 (Shorts)').first().json.response[0].file_url }}\",\n \"language\": \"tr\",\n \"settings\": {\n \"line_color\": \"#FFFFFF\",\n \"word_color\": \"#FFD700\",\n \"all_caps\": false,\n \"max_words_per_line\": 3,\n \"font_size\": 50,\n \"bold\": true,\n \"italic\": false,\n \"underline\": false,\n \"strikeout\": false,\n \"outline_width\": 3,\n \"shadow_offset\": 4,\n \"style\": \"highlight\",\n \"font_family\": \"The Bold Font\",\n \"position\": \"bottom_center\"\n },\n \"id\": \"ai-caption-{{ $now.format('x') }}\"\n}\n",
"options": {
"timeout": 600000
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
2480,
96
],
"id": "6e153e6b-f539-4e3c-828c-54aeb9c65187",
"name": "Add Turkish Captions"
},
{
"parameters": {
"jsCode": "const allClips = $('Split Clips').all();\nconst finalClips = allClips.map((clip, idx) => ({\n clip_number: idx + 1,\n start_time: clip.json.start_time.toFixed(1) + 's',\n end_time: clip.json.end_time.toFixed(1) + 's',\n duration: (clip.json.end_time - clip.json.start_time).toFixed(1) + 's',\n viral_score: clip.json.viral_score,\n ai_reason: clip.json.reason,\n ai_hook: clip.json.hook,\n final_url: clip.json.response\n}));\n\nreturn [{\n json: {\n total_clips: finalClips.length,\n clips: finalClips,\n summary: `\ud83e\udd16 AI ${finalClips.length} viral clip se\u00e7ti ve i\u015fledi`,\n ai_analysis_complete: true\n }\n}];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
2720,
96
],
"id": "5f327ec5-4ac0-4b2b-a0a9-ff28f8ff502b",
"name": "Compile Final Results"
},
{
"parameters": {
"content": "## 1\ufe0f\u20e3 Configuration",
"height": 300,
"width": 480,
"color": 3
},
"type": "n8n-nodes-base.stickyNote",
"position": [
192,
-16
],
"typeVersion": 1,
"id": "25e042c1-d7ac-418e-8b32-c7a79d48966d",
"name": "Sticky Note"
},
{
"parameters": {
"content": "## 2\ufe0f\u20e3 Transcribe & AI Analysis",
"height": 300,
"width": 480,
"color": 6
},
"type": "n8n-nodes-base.stickyNote",
"position": [
672,
-16
],
"typeVersion": 1,
"id": "d6583361-cd80-482d-adf0-2a1a4e3a5799",
"name": "Sticky Note1"
},
{
"parameters": {
"content": "## 3\ufe0f\u20e3 AI Analysis (LM Studio)",
"height": 300,
"width": 720,
"color": 4
},
"type": "n8n-nodes-base.stickyNote",
"position": [
1152,
-16
],
"typeVersion": 1,
"id": "08eda9fd-4d97-4f80-b15c-83907d19a8b1",
"name": "Sticky Note2"
},
{
"parameters": {
"content": "## 4\ufe0f\u20e3 Cut & Resize",
"height": 300,
"width": 480,
"color": 2
},
"type": "n8n-nodes-base.stickyNote",
"position": [
1872,
-16
],
"typeVersion": 1,
"id": "6e57ae8e-4950-42e0-ab48-746982446d8f",
"name": "Sticky Note3"
},
{
"parameters": {
"content": "## 5\ufe0f\u20e3 Caption & Export",
"height": 300,
"width": 720,
"color": 5
},
"type": "n8n-nodes-base.stickyNote",
"position": [
2352,
-16
],
"typeVersion": 1,
"id": "9c74c44f-d3a9-4bf0-afe6-f1955fb341c0",
"name": "Sticky Note4"
}
],
"connections": {
"When clicking 'Execute workflow'": {
"main": [
[
{
"node": "Set Variables",
"type": "main",
"index": 0
}
]
]
},
"Set Variables": {
"main": [
[
{
"node": "Transcribe (Turkish)",
"type": "main",
"index": 0
}
]
]
},
"Transcribe (Turkish)": {
"main": [
[
{
"node": "Prepare AI Analysis Prompt",
"type": "main",
"index": 0
}
]
]
},
"Prepare AI Analysis Prompt": {
"main": [
[
{
"node": "\ud83e\udd16 LM Studio - Viral Clip Analysis",
"type": "main",
"index": 0
}
]
]
},
"\ud83e\udd16 LM Studio - Viral Clip Analysis": {
"main": [
[
{
"node": "Parse AI Results & Select Clips",
"type": "main",
"index": 0
}
]
]
},
"Parse AI Results & Select Clips": {
"main": [
[
{
"node": "Split Clips",
"type": "main",
"index": 0
}
]
]
},
"Split Clips": {
"main": [
[
{
"node": "Extract AI-Selected Clip",
"type": "main",
"index": 0
}
]
]
},
"Extract AI-Selected Clip": {
"main": [
[
{
"node": "Resize to 9:16 (Shorts)",
"type": "main",
"index": 0
}
]
]
},
"Resize to 9:16 (Shorts)": {
"main": [
[
{
"node": "Add Turkish Captions",
"type": "main",
"index": 0
}
]
]
},
"Add Turkish Captions": {
"main": [
[
{
"node": "Compile Final Results",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1",
"binaryMode": "separate"
},
"versionId": "71c5ff7a-5398-4ccc-a34e-53de75a3deaa",
"id": "xBgTD4eDTXe2FUau",
"tags": []
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Shorts Clip Extractor (MinIO Source). Uses httpRequest. Event-driven trigger; 16 nodes.
Source: https://gist.github.com/yuceltoluyag/2b08bff182d3b4df944b902ebbfde340 — 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.
This workflow allows you to import any workflow from a file or another n8n instance and map the credentials easily. A multi-form setup guides you through the entire process At the beginning you have t
[n8n] Advanced URL Parsing and Shortening Workflow - Switchy.io Integration. Uses splitInBatches, stickyNote, httpRequest, html. Event-driven trigger; 56 nodes.
[](https://youtu.be/c7yCZhmMjtI)
This automation organizes your n8n workflows files into categorizes (Active, Template, Done, Archived) and uploads them directly to a categorized Google Drive folders. It is designed to help users man
Create Animated Stories using GPT-4o-mini, Midjourney, Kling and Creatomate API. Uses httpRequest. Event-driven trigger; 51 nodes.