UNPKG

n8n-nodes-comfyui-text-to-audio

Version:

n8n node to integrate with ComfyUI stable diffusion workflows for text to audio conversion

350 lines 19.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ComfyuiTextToAudio = void 0; const n8n_workflow_1 = require("n8n-workflow"); class ComfyuiTextToAudio { constructor() { this.description = { displayName: 'ComfyUI Text to Audio', name: 'comfyuiTextToAudio', icon: 'file:comfyui.svg', group: ['transform'], version: 1, subtitle: '={{$parameter["text"]}}', description: 'Generate audio from text using ComfyUI workflows', defaults: { name: 'ComfyUI Text to Audio', }, inputs: ["main"], outputs: ["main"], credentials: [ { name: 'comfyUIApi', required: false, }, ], properties: [ { displayName: 'Workflow JSON', name: 'workflowJson', type: 'json', default: '{}', required: true, description: 'ComfyUI workflow JSON for text-to-audio generation', typeOptions: { rows: 10, }, }, { displayName: 'Text', name: 'text', type: 'string', default: '', required: true, description: 'Text to convert to audio', typeOptions: { rows: 3, }, }, { displayName: 'Timeout (Minutes)', name: 'timeout', type: 'number', default: 5, required: true, description: 'Maximum time in minutes to wait for audio generation', typeOptions: { minValue: 1, maxValue: 60, }, }, ], }; } async execute() { var _a, _b, _c; const items = this.getInputData(); const returnData = []; for (let i = 0; i < items.length; i++) { try { const workflowJson = this.getNodeParameter('workflowJson', i); const inputText = this.getNodeParameter('text', i); const timeout = this.getNodeParameter('timeout', i); if (!inputText) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Text input is required', { itemIndex: i, }); } let workflow; try { workflow = typeof workflowJson === 'string' ? JSON.parse(workflowJson) : workflowJson; } catch (error) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Invalid workflow JSON', { itemIndex: i, }); } const credentials = await this.getCredentials('comfyUIApi'); const apiUrl = (credentials === null || credentials === void 0 ? void 0 : credentials.apiUrl) || 'http://127.0.0.1:8188'; const apiKey = credentials === null || credentials === void 0 ? void 0 : credentials.apiKey; for (const nodeId in workflow) { const node = workflow[nodeId]; if (node && node.inputs) { if (node.inputs.text !== undefined) { node.inputs.text = inputText; } if (node.inputs.prompt !== undefined) { node.inputs.prompt = inputText; } if (node.inputs.string !== undefined) { node.inputs.string = inputText; } } } const headers = { 'Content-Type': 'application/json', }; if (apiKey) { headers['Authorization'] = `Bearer ${apiKey}`; } const promptResponse = await this.helpers.request({ method: 'POST', url: `${apiUrl}/prompt`, headers, body: { prompt: workflow, }, json: true, }); if (!promptResponse.prompt_id) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Failed to queue ComfyUI prompt'); } const promptId = promptResponse.prompt_id; const timeoutMs = timeout * 60 * 1000; const startTime = Date.now(); while (Date.now() - startTime < timeoutMs) { try { const historyResponse = await this.helpers.request({ method: 'GET', url: `${apiUrl}/history/${promptId}`, headers: apiKey ? { 'Authorization': `Bearer ${apiKey}` } : {}, json: true, }); if (historyResponse[promptId]) { const history = historyResponse[promptId]; if (history.status && history.status.completed) { const outputs = history.outputs || {}; let audioFound = false; for (const nodeId in outputs) { const nodeOutput = outputs[nodeId]; if (nodeOutput.files && nodeOutput.files.length > 0) { for (const file of nodeOutput.files) { const filename = file.filename || file; if (typeof filename === 'string' && (filename.endsWith('.wav') || filename.endsWith('.mp3') || filename.endsWith('.ogg') || filename.endsWith('.flac') || filename.endsWith('.aac') || filename.endsWith('.m4a'))) { try { const downloadUrl = `${apiUrl}/view?filename=${encodeURIComponent(filename)}&type=output`; const downloadHeaders = {}; if (apiKey) { downloadHeaders['Authorization'] = `Bearer ${apiKey}`; } const audioBuffer = await this.helpers.request({ method: 'GET', url: downloadUrl, headers: downloadHeaders, encoding: null, }); const audioData = Buffer.from(audioBuffer).toString('base64'); const originalExtension = ((_a = filename.split('.').pop()) === null || _a === void 0 ? void 0 : _a.toLowerCase()) || 'wav'; const mimeTypes = { 'wav': 'audio/wav', 'mp3': 'audio/mpeg', 'ogg': 'audio/ogg', 'flac': 'audio/flac', 'aac': 'audio/aac', 'm4a': 'audio/mp4', }; const mimeType = mimeTypes[originalExtension] || 'audio/wav'; const binaryData = { data: audioData, mimeType: mimeType, fileName: filename, fileExtension: originalExtension, }; returnData.push({ json: { success: true, fileName: filename, fileExtension: originalExtension, mimeType: mimeType, text: inputText, downloadUrl: downloadUrl, }, binary: { data: binaryData, }, }); audioFound = true; } catch (error) { continue; } } } if (audioFound) break; } if (!audioFound && nodeOutput.audio && nodeOutput.audio.length > 0) { const audioFile = nodeOutput.audio[0]; const originalFilename = audioFile.filename; const downloadUrl = `${apiUrl}/view?filename=${encodeURIComponent(originalFilename)}&type=output`; const downloadHeaders = {}; if (apiKey) { downloadHeaders['Authorization'] = `Bearer ${apiKey}`; } const audioBuffer = await this.helpers.request({ method: 'GET', url: downloadUrl, headers: downloadHeaders, encoding: null, }); const audioData = Buffer.from(audioBuffer).toString('base64'); const originalExtension = ((_b = originalFilename.split('.').pop()) === null || _b === void 0 ? void 0 : _b.toLowerCase()) || 'wav'; const mimeTypes = { 'wav': 'audio/wav', 'mp3': 'audio/mpeg', 'ogg': 'audio/ogg', 'flac': 'audio/flac', 'aac': 'audio/aac', 'm4a': 'audio/mp4', }; const mimeType = mimeTypes[originalExtension] || 'audio/wav'; const binaryData = { data: audioData, mimeType: mimeType, fileName: originalFilename, fileExtension: originalExtension, }; returnData.push({ json: { success: true, fileName: originalFilename, fileExtension: originalExtension, mimeType: mimeType, text: inputText, downloadUrl: downloadUrl, }, binary: { data: binaryData, }, }); audioFound = true; break; } if (!audioFound && nodeOutput.outputs && nodeOutput.outputs.audio) { const audioOutput = nodeOutput.outputs.audio; if (audioOutput && audioOutput.length > 0) { const audioFile = audioOutput[0]; const originalFilename = audioFile.filename; const downloadUrl = `${apiUrl}/view?filename=${encodeURIComponent(originalFilename)}&type=output`; const downloadHeaders = {}; if (apiKey) { downloadHeaders['Authorization'] = `Bearer ${apiKey}`; } const audioBuffer = await this.helpers.request({ method: 'GET', url: downloadUrl, headers: downloadHeaders, encoding: null, }); const audioData = Buffer.from(audioBuffer).toString('base64'); const originalExtension = ((_c = originalFilename.split('.').pop()) === null || _c === void 0 ? void 0 : _c.toLowerCase()) || 'wav'; const mimeTypes = { 'wav': 'audio/wav', 'mp3': 'audio/mpeg', 'ogg': 'audio/ogg', 'flac': 'audio/flac', 'aac': 'audio/aac', 'm4a': 'audio/mp4', }; const mimeType = mimeTypes[originalExtension] || 'audio/wav'; const binaryData = { data: audioData, mimeType: mimeType, fileName: originalFilename, fileExtension: originalExtension, }; returnData.push({ json: { success: true, fileName: originalFilename, fileExtension: originalExtension, mimeType: mimeType, text: inputText, downloadUrl: downloadUrl, }, binary: { data: binaryData, }, }); audioFound = true; break; } } } if (!audioFound) { returnData.push({ json: { success: true, message: 'ComfyUI workflow completed successfully - no audio output found', text: inputText, outputs: outputs, debug: { outputKeys: Object.keys(outputs), outputStructure: JSON.stringify(outputs, null, 2), }, }, }); } break; } if (history.status && history.status.status_str === 'error') { throw new n8n_workflow_1.NodeOperationError(this.getNode(), `ComfyUI execution failed: ${JSON.stringify(history.status)}`); } } await new Promise(resolve => setTimeout(resolve, 2000)); } catch (error) { if (error instanceof n8n_workflow_1.NodeOperationError) { throw error; } await new Promise(resolve => setTimeout(resolve, 2000)); } } if (returnData.length === 0) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), `ComfyUI execution timed out after ${timeout} minutes`); } } catch (error) { if (this.continueOnFail()) { returnData.push({ json: { error: error.message, success: false, }, pairedItem: { item: i, }, }); continue; } throw error; } } return [returnData]; } } exports.ComfyuiTextToAudio = ComfyuiTextToAudio; //# sourceMappingURL=ComfyuiTextToAudio.node.js.map