{ "nodes": [ { "id": "translate-french-speech-to-english-audio-0", "name": "When clicking \"Execute Workflow\"", "type": "n8n-nodes-base.manualTrigger", "position": [ -160, 320 ], "parameters": {}, "typeVersion": 1 }, { "id": "translate-french-speech-to-english-audio-1", "name": "Transcribe Audio", "type": "n8n-nodes-base.httpRequest", "position": [ 720, 320 ], "parameters": { "method": "POST", "url": "https://api.openai.com/v1/audio/transcriptions", "authentication": "predefinedCredentialType", "nodeCredentialType": "openAiApi", "sendBody": true, "contentType": "multipart-form-data", "bodyParameters": { "parameters": [ { "name": "file", "parameterType": "formBinaryData", "inputDataFieldName": "data" }, { "name": "model", "value": "whisper-1" }, { "name": "response_format", "value": "json" } ] }, "options": { "response": { "response": { "responseFormat": "json" } } } }, "typeVersion": 4.2 }, { "id": "translate-french-speech-to-english-audio-2", "name": "English Translation Model", "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi", "position": [ 940, 500 ], "parameters": { "model": { "__rl": true, "mode": "id", "value": "gpt-4o-mini-2024-07-18" }, "options": { "temperature": 0, "maxRetries": 2 } }, "typeVersion": 1.2 }, { "id": "translate-french-speech-to-english-audio-3", "name": "Configure French Text and Voice", "type": "n8n-nodes-base.set", "position": [ 60, 320 ], "parameters": { "assignments": { "assignments": [ { "id": "french-text", "name": "french_text", "type": "string", "value": "Bonjour. Notre équipe prépare un guide public pour expliquer son travail." }, { "id": "voice-id", "name": "voice_id", "type": "string", "value": "YOUR_ELEVENLABS_VOICE_ID" } ] }, "options": {} }, "typeVersion": 3.4 }, { "id": "translate-french-speech-to-english-audio-4", "name": "Generate French Audio", "type": "n8n-nodes-base.httpRequest", "position": [ 300, 320 ], "parameters": { "method": "POST", "url": "=https://api.elevenlabs.io/v1/text-to-speech/{{ encodeURIComponent($('Validate Text and Voice').first().json.voiceId) }}", "authentication": "genericCredentialType", "genericAuthType": "httpHeaderAuth", "sendQuery": true, "queryParameters": { "parameters": [ { "name": "optimize_streaming_latency", "value": "1" }, { "name": "output_format", "value": "mp3_44100_128" } ] }, "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "accept", "value": "audio/mpeg" } ] }, "sendBody": true, "specifyBody": "json", "jsonBody": "={{ {text:$json.frenchText,model_id:\"eleven_multilingual_v2\",voice_settings:{stability:0.5,similarity_boost:0.5}} }}", "options": { "response": { "response": { "responseFormat": "file", "outputPropertyName": "data" } } } }, "typeVersion": 4.2 }, { "id": "translate-french-speech-to-english-audio-5", "name": "Translate Text to English", "type": "@n8n/n8n-nodes-langchain.chainLlm", "position": [ 960, 320 ], "parameters": { "promptType": "define", "text": "=Translate to English:\n{{ $json.frenchTranscript }}", "batching": { "batchSize": 1 } }, "typeVersion": 1.7 }, { "id": "translate-french-speech-to-english-audio-6", "name": "Translate English text to speech", "type": "n8n-nodes-base.httpRequest", "position": [ 1320, 320 ], "parameters": { "method": "POST", "url": "=https://api.elevenlabs.io/v1/text-to-speech/{{ encodeURIComponent($('Validate Text and Voice').first().json.voiceId) }}", "authentication": "genericCredentialType", "genericAuthType": "httpHeaderAuth", "sendQuery": true, "queryParameters": { "parameters": [ { "name": "optimize_streaming_latency", "value": "1" }, { "name": "output_format", "value": "mp3_44100_128" } ] }, "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "accept", "value": "audio/mpeg" } ] }, "sendBody": true, "specifyBody": "json", "jsonBody": "={{ {text:$json.englishText,model_id:\"eleven_multilingual_v2\",voice_settings:{stability:0.5,similarity_boost:0.5}} }}", "options": { "response": { "response": { "responseFormat": "file", "outputPropertyName": "data" } } } }, "typeVersion": 4.2 }, { "id": "translate-french-speech-to-english-audio-7", "name": "Validate Text and Voice", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 600, 0 ], "parameters": { "mode": "runOnceForAllItems", "jsCode": "const prepare = function prepareSpeechInput({french_text,voice_id}) {\n if(typeof french_text!=='string'||!french_text.trim()||Array.from(french_text).length>10000) throw new Error('Supply French text with 1–10000 characters.');\n if(typeof voice_id!=='string'||!voice_id.trim()) throw new Error('Supply an ElevenLabs voice ID.');\n return {frenchText:french_text,voiceId:voice_id.trim()};\n}\n\nreturn [{json:prepare($input.first().json),pairedItem:{item:0}}];" } }, { "id": "translate-french-speech-to-english-audio-8", "name": "Prepare French Audio", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1000, 0 ], "parameters": { "mode": "runOnceForAllItems", "jsCode": "const item=$input.first(),audio=item.binary?.data;\nconst mime=typeof audio?.mimeType==='string'?audio.mimeType.split(';')[0].trim().toLowerCase():'';\nif(!['audio/mpeg','audio/mp3','application/octet-stream'].includes(mime))throw new Error('The speech response is not MP3 audio.');\nreturn [{json:{},binary:{...item.binary,data:{...audio,fileName:'french.mp3'}},pairedItem:{item:0}}];" } }, { "id": "translate-french-speech-to-english-audio-9", "name": "Read French Transcript", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1400, 0 ], "parameters": { "mode": "runOnceForAllItems", "jsCode": "const prepare = function readFrenchTranscript({transcription}) {\n if(!transcription||typeof transcription.text!=='string'||!transcription.text.trim()) throw new Error('The French audio returned no transcript.');\n return {frenchTranscript:transcription.text};\n}\n\nreturn [{json:prepare({transcription:$input.first().json}),pairedItem:{item:0}}];" } }, { "id": "translate-french-speech-to-english-audio-10", "name": "Validate English Translation", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1800, 0 ], "parameters": { "mode": "runOnceForAllItems", "jsCode": "const prepare = function validateEnglishSpeechText({text}) {\n if(typeof text!=='string'||!text.trim()) throw new Error('The translation returned no English text.');\n const englishText=text.trim();\n if(Array.from(englishText).length>10000) throw new Error('The English translation exceeds the 10000-character speech limit.');\n return {englishText};\n}\n\nreturn [{json:prepare({text:$input.first().json.text}),pairedItem:{item:0}}];" } }, { "id": "translate-french-speech-to-english-audio-11", "name": "French and English Audio", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 2200, 0 ], "parameters": { "mode": "runOnceForAllItems", "jsCode": "const item=$input.first(),audio=item.binary?.data;\nconst mime=typeof audio?.mimeType==='string'?audio.mimeType.split(';')[0].trim().toLowerCase():'';\nif(!['audio/mpeg','audio/mp3','application/octet-stream'].includes(mime))throw new Error('The speech response is not MP3 audio.');\nreturn [{json:{frenchTranscript:$('Read French Transcript').first().json.frenchTranscript,englishText:$('Validate English Translation').first().json.englishText},binary:{data:{...audio,fileName:'english.mp3'},french:{...$('Prepare French Audio').first().binary.data,fileName:'french.mp3'}},pairedItem:{item:0}}];" } } ], "pinData": {}, "connections": { "When clicking \"Execute Workflow\"": { "main": [ [ { "node": "Configure French Text and Voice", "type": "main", "index": 0 } ] ] }, "Configure French Text and Voice": { "main": [ [ { "node": "Validate Text and Voice", "type": "main", "index": 0 } ] ] }, "Validate Text and Voice": { "main": [ [ { "node": "Generate French Audio", "type": "main", "index": 0 } ] ] }, "Generate French Audio": { "main": [ [ { "node": "Prepare French Audio", "type": "main", "index": 0 } ] ] }, "Prepare French Audio": { "main": [ [ { "node": "Transcribe Audio", "type": "main", "index": 0 } ] ] }, "Transcribe Audio": { "main": [ [ { "node": "Read French Transcript", "type": "main", "index": 0 } ] ] }, "Read French Transcript": { "main": [ [ { "node": "Translate Text to English", "type": "main", "index": 0 } ] ] }, "Translate Text to English": { "main": [ [ { "node": "Validate English Translation", "type": "main", "index": 0 } ] ] }, "Validate English Translation": { "main": [ [ { "node": "Translate English text to speech", "type": "main", "index": 0 } ] ] }, "Translate English text to speech": { "main": [ [ { "node": "French and English Audio", "type": "main", "index": 0 } ] ] }, "English Translation Model": { "ai_languageModel": [ [ { "node": "Translate Text to English", "type": "ai_languageModel", "index": 0 } ] ] } }, "name": "Translate French Speech to English Audio", "active": false }