{
	"name": "Label speakers in a call recording",
	"meta": {
		"templateCredsSetupCompleted": false,
		"description": "Upload a call recording to Agent Leverage, run Speaker Separation, wait for the transcript, then return a labeled .txt transcript with the names you typed."
	},
	"settings": {
		"executionOrder": "v1"
	},
	"nodes": [
		{
			"parameters": {
				"formTitle": "Label speakers in a call recording",
				"formDescription": "Upload a call recording. Agent Leverage separates the speakers and returns a labeled transcript.",
				"formFields": {
					"values": [
						{
							"fieldLabel": "Recording",
							"fieldType": "file",
							"multipleFiles": false,
							"acceptFileTypes": ".mp3, .wav, .m4a, .ogg, .webm, .flac",
							"requiredField": true
						},
						{
							"fieldLabel": "Number of speakers",
							"fieldType": "number",
							"placeholder": "3",
							"requiredField": false
						},
						{
							"fieldLabel": "Speaker names",
							"placeholder": "Samantha, Daniel, Karen",
							"requiredField": false
						}
					]
				},
				"options": {}
			},
			"id": "b1c2d3e4-0001-4000-8000-000000000001",
			"name": "Form",
			"type": "n8n-nodes-base.formTrigger",
			"typeVersion": 2.2,
			"position": [0, 0],
			"webhookId": "agentleverage-label-speakers"
		},
		{
			"parameters": {
				"resource": "file",
				"operation": "uploadAudio",
				"binaryPropertyName": "Recording",
				"filename": "={{ $json.Recording?.filename || $json.Recording?.[0]?.filename || 'recording' }}",
				"mimeType": "={{ $json.Recording?.mimetype || $json.Recording?.[0]?.mimetype || 'audio/mpeg' }}"
			},
			"id": "b1c2d3e4-0002-4000-8000-000000000002",
			"name": "Upload Audio",
			"type": "n8n-nodes-agentleverage.agentLeverage",
			"typeVersion": 1,
			"position": [240, 0],
			"credentials": {
				"agentLeverageApi": {
					"id": null,
					"name": "Agent Leverage API"
				}
			}
		},
		{
			"parameters": {
				"resource": "speakerSeparation",
				"operation": "create",
				"audioFileUrl": "={{ $json.audioFileUrl }}",
				"additionalFields": {
					"speakersExpected": "={{ Number($('Form').first().json['Number of speakers']) || 0 }}"
				}
			},
			"id": "b1c2d3e4-0003-4000-8000-000000000003",
			"name": "Speaker Separation",
			"type": "n8n-nodes-agentleverage.agentLeverage",
			"typeVersion": 1,
			"position": [480, 0],
			"credentials": {
				"agentLeverageApi": {
					"id": null,
					"name": "Agent Leverage API"
				}
			}
		},
		{
			"parameters": {
				"resource": "job",
				"operation": "wait",
				"jobId": "={{ $json.job.id }}",
				"pollIntervalMs": 5000,
				"timeoutMs": 600000
			},
			"id": "b1c2d3e4-0004-4000-8000-000000000004",
			"name": "Wait for Transcript",
			"type": "n8n-nodes-agentleverage.agentLeverage",
			"typeVersion": 1,
			"position": [720, 0],
			"credentials": {
				"agentLeverageApi": {
					"id": null,
					"name": "Agent Leverage API"
				}
			}
		},
		{
			"parameters": {
				"jsCode": "// Turn Speaker Separation segments into a labeled transcript.\n// Names from the form are applied in the order each voice first speaks.\nconst job = $json.job;\nconst segments = job.output?.segments ?? [];\nconst raw = $('Form').first().json['Speaker names'] || '';\nconst names = raw.split(',').map((n) => n.trim()).filter(Boolean);\n\nconst order = [];\nfor (const s of segments) if (!order.includes(s.speaker)) order.push(s.speaker);\nconst labelFor = (id) => names[order.indexOf(id)] || `Speaker ${id}`;\n\nconst stamp = (t) => {\n  const m = Math.floor(t / 60);\n  const s = Math.floor(t % 60);\n  return `${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}`;\n};\n\n// Merge back-to-back segments from the same speaker into one turn.\nconst turns = [];\nfor (const s of segments) {\n  const last = turns[turns.length - 1];\n  if (last && last.speaker === s.speaker) last.text += ' ' + s.text.trim();\n  else turns.push({ speaker: s.speaker, start: s.startTime, text: s.text.trim() });\n}\n\nconst lines = turns.map((t) => `[${stamp(t.start)}] ${labelFor(t.speaker)}: ${t.text}`);\n\nreturn [{\n  json: {\n    speakers: order.map((id) => ({ id, label: labelFor(id) })),\n    turns: turns.length,\n    transcript: lines.join('\\n'),\n  },\n}];"
			},
			"id": "b1c2d3e4-0005-4000-8000-000000000005",
			"name": "Label Transcript",
			"type": "n8n-nodes-base.code",
			"typeVersion": 2,
			"position": [960, 0]
		},
		{
			"parameters": {
				"operation": "toText",
				"sourceProperty": "transcript",
				"options": {
					"fileName": "={{ ($('Form').first().json.Recording?.filename || 'recording').replace(/\\.[^.]+$/, '') }}-labeled-transcript.txt"
				}
			},
			"id": "b1c2d3e4-0006-4000-8000-000000000006",
			"name": "Transcript File",
			"type": "n8n-nodes-base.convertToFile",
			"typeVersion": 1.1,
			"position": [1200, 0]
		},
		{
			"parameters": {
				"operation": "completion",
				"respondWith": "returnBinary",
				"completionTitle": "Your labeled transcript is ready",
				"completionMessage": "The download starts automatically. Check names on overlapping turns before you share it.",
				"inputDataFieldName": "data",
				"options": {}
			},
			"id": "b1c2d3e4-0007-4000-8000-000000000007",
			"name": "Download Transcript",
			"type": "n8n-nodes-base.form",
			"typeVersion": 1,
			"position": [1440, 0],
			"webhookId": "agentleverage-label-speakers-done"
		}
	],
	"connections": {
		"Form": {
			"main": [
				[
					{
						"node": "Upload Audio",
						"type": "main",
						"index": 0
					}
				]
			]
		},
		"Upload Audio": {
			"main": [
				[
					{
						"node": "Speaker Separation",
						"type": "main",
						"index": 0
					}
				]
			]
		},
		"Speaker Separation": {
			"main": [
				[
					{
						"node": "Wait for Transcript",
						"type": "main",
						"index": 0
					}
				]
			]
		},
		"Wait for Transcript": {
			"main": [
				[
					{
						"node": "Label Transcript",
						"type": "main",
						"index": 0
					}
				]
			]
		},
		"Label Transcript": {
			"main": [
				[
					{
						"node": "Transcript File",
						"type": "main",
						"index": 0
					}
				]
			]
		},
		"Transcript File": {
			"main": [
				[
					{
						"node": "Download Transcript",
						"type": "main",
						"index": 0
					}
				]
			]
		}
	},
	"pinData": {}
}
