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": "Text to speech Voice clone using Zonos via API(local storage)",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "voice-clone",
"options": {}
},
"id": "76f2c278-c769-443f-8aa5-541713323b51",
"name": "Webhook Trigger",
"type": "n8n-nodes-base.webhook",
"typeVersion": 1,
"position": [
-560,
60
]
},
{
"parameters": {
"keepOnlySet": true,
"values": {
"string": [
{
"name": "text",
"value": "={{ $json.body.text || 'Hello, this is a test of voice cloning!' }}"
},
{
"name": "speaking_rate",
"value": "={{ $json.body.speaking_rate || 15 }}"
},
{
"name": "language_iso_code",
"value": "={{ $json.body.language_iso_code || 'en-us' }}"
},
{
"name": "mime_type",
"value": "={{ $json.body.mime_type || 'audio/wav'}}"
},
{
"name": "sample_voice_path",
"value": "={{ $json.body.sample_voice_path }}"
},
{
"name": "model",
"value": "={{ $json.body.model || 'zonos-v0.1-transformer' }}"
},
{
"name": "output_path",
"value": "={{ $json.body.output_path }}"
}
],
"number": [
{
"name": "happiness",
"value": "={{ $json.body.emotion.happiness || 0.6}}"
},
{
"name": "neutral",
"value": "={{ $json.body.emotion.neutral || 0.6}}"
},
{
"name": "sadness",
"value": "={{ $json.body.emotion.sadness || 0.05}}"
},
{
"name": "disgust",
"value": "={{ $json.body.emotion.disgust || 0.05}}"
},
{
"name": "fear",
"value": "={{ $json.body.emotion.fear || 0.05}}"
},
{
"name": "surprise",
"value": "={{ $json.body.emotion.surprise || 0.05}}"
},
{
"name": "anger",
"value": "={{ $json.body.emotion.anger || 0.05}}"
},
{
"name": "other",
"value": "={{ $json.body.emotion.other || 0.5}}"
}
]
},
"options": {}
},
"id": "0772d98e-7cd8-487d-a3db-26c3d6d50304",
"name": "Set Clone Parameters",
"type": "n8n-nodes-base.set",
"typeVersion": 1,
"position": [
-340,
60
]
},
{
"parameters": {
"fileSelector": "={{ $json.sample_voice_path }}",
"options": {
"mimeType": "={{ $json.mime_type }}",
"dataPropertyName": ""
}
},
"id": "b3dc1528-90d7-4397-83e6-18c5f2dbf495",
"name": "Read Sample Voice",
"type": "n8n-nodes-base.readWriteFile",
"typeVersion": 1,
"position": [
40,
60
],
"onError": "continueErrorOutput"
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 1
},
"conditions": [
{
"id": "file-exists-check",
"leftValue": "={{ $ifEmpty($binary.data, false) !== false }}\n",
"rightValue": "",
"operator": {
"type": "string",
"operation": "exists",
"singleValue": true
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "86e0f9bf-ccec-4bb1-b9ce-7d1b94fdfcca",
"name": "Check File Loaded",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
560,
-80
]
},
{
"parameters": {
"method": "POST",
"url": "http://api.zyphra.com/v1/audio/text-to-speech",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "X-API-Key",
"value": "put-your-API-key-here"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"text\": \"{{ $('Set Clone Parameters').item.json.text }}\",\n \"speaking_rate\": {{ parseFloat($('Set Clone Parameters').item.json.speaking_rate) }},\n \"language_iso_code\": \"{{ $('Set Clone Parameters').item.json.language_iso_code }}\",\n \"mime_type\": \"{{ $('Set Clone Parameters').item.json.mime_type }}\",\n \"model\": \"{{ $('Set Clone Parameters').item.json.model }}\",\n \"emotion\": {\n \"happiness\": {{ $('Set Clone Parameters').item.json.happiness }},\n \"neutral\": {{ $('Set Clone Parameters').item.json.neutral }},\n \"sadness\": {{ $('Set Clone Parameters').item.json.sadness }},\n \"disgust\": {{ $('Set Clone Parameters').item.json.disgust }},\n \"fear\": {{ $('Set Clone Parameters').item.json.fear }},\n \"surprise\": {{ $('Set Clone Parameters').item.json.surprise }},\n \"anger\": {{ $('Set Clone Parameters').item.json.anger }},\n \"other\": {{ $('Set Clone Parameters').item.json.other }}\n },\n \"speaker_audio\": \"{{ $json.base64_content }}\"\n}\n",
"options": {
"response": {
"response": {}
}
}
},
"id": "2980ae94-30e3-4065-8d2c-b607c73c3c5f",
"name": "Call Zyphra Clone API",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.1,
"position": [
980,
-120
],
"onError": "continueErrorOutput"
},
{
"parameters": {
"operation": "write",
"fileName": "={{ $('Set Clone Parameters').item.json.output_path }}{{ 'cloned_voice_' + new Date().getTime() + '.webm' }}",
"options": {}
},
"id": "0f896518-98ce-4176-8977-1f0380b54469",
"name": "Save Cloned Audio",
"type": "n8n-nodes-base.readWriteFile",
"typeVersion": 1,
"position": [
1440,
0
]
},
{
"parameters": {
"values": {
"string": [
{
"name": "success",
"value": "true"
},
{
"name": "message",
"value": "Voice cloning completed successfully!"
},
{
"name": "filename",
"value": "={{ $json.fileName }}"
},
{
"name": "text_processed",
"value": "={{ $('Set Clone Parameters').item.json.text }}"
},
{
"name": "sample_voice_used",
"value": "={{ $('Set Clone Parameters').item.json.sample_voice_path }}"
}
]
},
"options": {}
},
"id": "02f1b766-953a-4834-8d93-4cc596ffe77c",
"name": "Success Response",
"type": "n8n-nodes-base.set",
"typeVersion": 1,
"position": [
1660,
0
]
},
{
"parameters": {
"values": {
"string": [
{
"name": "success",
"value": "false"
},
{
"name": "error_type",
"value": "file_not_found"
},
{
"name": "message",
"value": "Sample voice file could not be read from: {{ $('Set Clone Parameters').item.json.sample_voice_path }}"
},
{
"name": "suggestion",
"value": "Please check the file path and ensure the file exists"
}
]
},
"options": {}
},
"id": "7da98d65-08e3-4d6e-9957-ead2c8f1133f",
"name": "File Error Response",
"type": "n8n-nodes-base.set",
"typeVersion": 1,
"position": [
860,
480
]
},
{
"parameters": {
"values": {
"string": [
{
"name": "success",
"value": "false"
},
{
"name": "error_type",
"value": "api_error"
},
{
"name": "message",
"value": "Voice cloning API request failed"
},
{
"name": "error_details",
"value": "={{ $json.error ? $json.error.message : 'Unknown API error' }}"
},
{
"name": "suggestion",
"value": "Please check your API key and try again"
}
]
},
"options": {}
},
"id": "44006f98-4241-436d-b8cf-1c586271a35a",
"name": "API Error Response",
"type": "n8n-nodes-base.set",
"typeVersion": 1,
"position": [
1100,
480
]
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ $json }}",
"options": {}
},
"id": "e2c14808-e209-4daf-93dd-9c7049261e60",
"name": "Webhook Response",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1,
"position": [
1880,
100
]
},
{
"parameters": {
"content": "\ud83c\udf99\ufe0f VOICE CLONING WORKFLOW - ZONOS API\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\nThis workflow clones voices using Zyphra's Zonos API\n\ud83d\udccb Input: Text + sample voice file + parameters \n\ud83c\udfb5 Output: Generated audio file with cloned voice\n\u26a1 Trigger: Webhook POST to /voice-clone endpoint\n\nBasic setup and use:\nConfigure your Zyphra API key in the \"Call Zyphra Clone API\" node under Header parameters \u2192 X-API-Key header parameter\n\nEnsure your sample voice files are accessible at the paths you'll specify\n\nTest the webhook endpoint is accessible\n\nSend valid POST request to your webhook\n",
"height": 340,
"width": 780,
"color": 4
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-960,
-1200
],
"id": "8268fd4a-fd84-4462-9ad1-9af8152d0cf3",
"name": "Sticky Note"
},
{
"parameters": {
"jsCode": "// Get binary data from previous node\nconst binaryData = $input.first().binary?.data;\n\nif (!binaryData) {\n throw new Error(\"No binary data found\");\n}\n\n// Binary data in n8n is already base64 encoded\nconst base64String = binaryData.data;\n\nreturn {\n json: {\n base64_content: base64String,\n // Add other fields as needed\n }\n};\n"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
400,
-80
],
"id": "cdbb775f-8408-43a9-89b1-1039315c6678",
"name": "Base64 convertor"
},
{
"parameters": {
"content": "\ud83d\udce5 REQUIRED WEBHOOK PARAMETERS\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\u2705 text: Text to synthesize\n\u2705 sample_voice_path: Path to your voice sample file \n\u2705 output_path: Where to save generated audio\n\n\ud83d\udd27 OPTIONAL PARAMETERS (with defaults):\n\u2022 speaking_rate: 15 (speech speed)\n\u2022 language_iso_code: \"en-us\" \n\u2022 mime_type: \"audio/wav\"\n\u2022 model: \"zonos-v0.1-transformer\"\n\u2022 emotion: Various emotion levels (0-1 scale)\n",
"height": 1020,
"width": 780,
"color": 6
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-960,
-740
],
"id": "88b0131c-f93b-4593-9c88-ed4f91b74c88",
"name": "Sticky Note1"
},
{
"parameters": {
"content": "\ud83d\udd10 API KEY CONFIGURATION REQUIRED!\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n1\ufe0f\u20e3 Register account at: playground.zyphra.com \n2\ufe0f\u20e3 Get API key from: playground.zyphra.com/settings/api-keys\n3\ufe0f\u20e3 Add key to \"Call Zyphra Clone API\" node\n \u2192 Header parameters section\n \u2192 Header: X-API-Key\n \u2192 Value: [Your API Key]\n\n\u274c Workflow will fail without proper API key setup!\n",
"height": 460,
"width": 480,
"color": 6
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
820,
-380
],
"id": "3be24130-054d-4435-9aac-d5ad9c7b92d0",
"name": "Sticky Note2"
},
{
"parameters": {
"content": "\ud83d\udcc1 FILE HANDLING PROCESS\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n1. Read sample voice from specified path\n2. Convert audio file to base64 format\n3. Validate file loaded successfully \n\n\u26a0\ufe0f IMPORTANT: Ensure sample voice file exists \n at the path specified in sample_voice_path!\n",
"height": 560,
"width": 740,
"color": 6
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-60,
-280
],
"id": "08780e5a-4663-4a0d-aeff-69f4059495ce",
"name": "Sticky Note3"
},
{
"parameters": {
"content": "\ud83d\udea8 ERROR HANDLING & RESPONSES\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\u2705 SUCCESS: Returns success message + filename\n\u274c FILE_NOT_FOUND: Sample voice file missing/unreadable\n\u274c API_ERROR: Zyphra API request failed\n\u274c AUTH_ERROR: Invalid or missing API key\n\nAll errors return JSON with error details and suggestions\n",
"height": 480,
"width": 480,
"color": 6
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
820,
180
],
"id": "223743b2-aeb2-45cc-8094-9bef48fc815e",
"name": "Sticky Note4"
},
{
"parameters": {
"content": "\ud83c\udfb5 OUTPUT DETAILS\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\ud83d\udccd Location: [output_path]/cloned_voice_[timestamp].webm\n\ud83d\udcca Format: Specified by mime_type parameter\n\ud83d\udd50 Filename: Auto-generated with timestamp\n\ud83d\udcdd Response: JSON with success status and file details\n\nGenerated audio ready for download!\n",
"height": 540,
"width": 660,
"color": 6
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
1400,
-220
],
"id": "939714c2-9feb-4ccb-b3b6-fd133c65c56a",
"name": "Sticky Note5"
},
{
"parameters": {
"content": "POST http://localhost:5678/webhook-test/voice-clone\nContent-Type: application/json\n\n{\n \"text\": \"Hello there, kupo! This voice sounds just like the sample!\",\n \"speaking_rate\": 18,\n \"sample_voice_path\": \"/data/output/sampleVoice.wav\",\n \"output_path\": \"/data/output/\",\n \"language_iso_code\": \"en-us\",\n \"mime_type\": \"audio/wav\",\n \"model\": \"zonos-v0.1-transformer\",\n \"emotion\": {\n \"happiness\": 0.8,\n \"neutral\": 0.3,\n \"sadness\": 0.05,\n \"disgust\": 0.05,\n \"fear\": 0.05,\n \"surprise\": 0.05,\n \"anger\": 0.05,\n \"other\": 0.5\n }\n}\n",
"height": 440,
"width": 700,
"color": 5
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-940,
-440
],
"id": "0a90485e-417a-415e-a9a4-f128aea6b9f1",
"name": "Sticky Note6"
}
],
"connections": {
"Webhook Trigger": {
"main": [
[
{
"node": "Set Clone Parameters",
"type": "main",
"index": 0
}
]
]
},
"Set Clone Parameters": {
"main": [
[
{
"node": "Read Sample Voice",
"type": "main",
"index": 0
}
]
]
},
"Read Sample Voice": {
"main": [
[
{
"node": "Base64 convertor",
"type": "main",
"index": 0
}
],
[
{
"node": "File Error Response",
"type": "main",
"index": 0
}
]
]
},
"Check File Loaded": {
"main": [
[
{
"node": "Call Zyphra Clone API",
"type": "main",
"index": 0
}
],
[
{
"node": "File Error Response",
"type": "main",
"index": 0
}
]
]
},
"Call Zyphra Clone API": {
"main": [
[
{
"node": "Save Cloned Audio",
"type": "main",
"index": 0
}
],
[
{
"node": "API Error Response",
"type": "main",
"index": 0
}
]
]
},
"Save Cloned Audio": {
"main": [
[
{
"node": "Success Response",
"type": "main",
"index": 0
}
]
]
},
"Success Response": {
"main": [
[
{
"node": "Webhook Response",
"type": "main",
"index": 0
}
]
]
},
"File Error Response": {
"main": [
[
{
"node": "Webhook Response",
"type": "main",
"index": 0
}
]
]
},
"API Error Response": {
"main": [
[
{
"node": "Webhook Response",
"type": "main",
"index": 0
}
]
]
},
"Base64 convertor": {
"main": [
[
{
"node": "Check File Loaded",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "c4a644b3-3029-47ed-9dad-6396d22a9841",
"meta": {
"templateCredsSetupCompleted": true
},
"id": "hqMRsze38RaTmgQh",
"tags": []
}
About this workflow
Text to speech Voice clone using Zonos via API(local storage). Uses readWriteFile, httpRequest, respondToWebhook, stickyNote. Webhook trigger; 18 nodes.
Source: https://gitlab.com/Tiartyos/n8n-workflows/-/blob/master/workflows/zyphry-zonos-api/workflow.json — original creator credit. Request a take-down →