UNPKG

n8n-nodes-comfyui-media

Version:

n8n node to integrate with ComfyUI stable diffusion workflows for image to video conversion

147 lines 6.62 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ComfyuiWfToMedia = void 0; const n8n_workflow_1 = require("n8n-workflow"); const apiClient_1 = require("./apiClient"); const poller_1 = require("./poller"); const workflowService_1 = require("./workflowService"); class ComfyuiWfToMedia { constructor() { this.description = { displayName: 'ComfyUI Wf to Media', name: 'comfyuiWfToMedia', icon: 'file:comfyui.svg', group: ['transform'], version: 1, description: 'Convert Wf to medias using ComfyUI workflow', defaults: { name: 'ComfyUI Wf to Media', }, credentials: [ { name: 'comfyUIApi', required: true, }, ], inputs: ['main'], outputs: ['main'], properties: [ { displayName: 'Workflow JSON', name: 'workflow', type: 'string', typeOptions: { rows: 10, }, default: '', required: true, description: 'The ComfyUI workflow in JSON format', }, { displayName: 'Timeout', name: 'timeout', type: 'number', default: 30, description: 'Maximum time in minutes to wait for video generation', }, ], }; } async execute() { var _a; const api = new apiClient_1.N8nApiClient(this.helpers); const credentials = await this.getCredentials('comfyUIApi'); const apiUrl = credentials.apiUrl; const apiKey = credentials.apiKey; const headers = { 'Content-Type': 'application/json' }; if (apiKey) headers['Authorization'] = `Bearer ${apiKey}`; try { const workflow = this.getNodeParameter('workflow', 0); const timeout = this.getNodeParameter('timeout', 0); const wf = workflowService_1.WorkflowService.parse(workflow); const response = await api.request({ method: 'POST', url: `${apiUrl}/prompt`, headers, body: { prompt: wf }, json: true, }); if (!response.prompt_id) throw new n8n_workflow_1.NodeApiError(this.getNode(), { message: 'Failed to get prompt ID' }); const poller = new poller_1.Poller(api, apiUrl, headers); const promptResult = await poller.waitForCompletion(response.prompt_id, timeout); console.log('[ComfyUI] Video generation completed'); if (((_a = promptResult.status) === null || _a === void 0 ? void 0 : _a.status_str) === 'error') { throw new n8n_workflow_1.NodeApiError(this.getNode(), { message: '[ComfyUI] Video generation failed' }); } console.log('[ComfyUI] Raw outputs structure:', JSON.stringify(promptResult.outputs, null, 2)); const mediaOutputs = Object.values(promptResult.outputs) .flatMap((nodeOutput) => nodeOutput.images || nodeOutput.gifs || []) .filter((out) => out.type === 'output' || out.type === 'temp') .map((out) => ({ ...out, url: `${apiUrl}/view?filename=${out.filename}&subfolder=${out.subfolder || ''}&type=${out.type}`, })); if (mediaOutputs.length === 0) { throw new n8n_workflow_1.NodeApiError(this.getNode(), { message: '[ComfyUI] No media outputs found' }); } const videoOutputs = mediaOutputs.filter(o => o.filename.endsWith('.webp') || o.filename.endsWith('.mp4') || o.filename.endsWith('.gif')); const imageOutputs = mediaOutputs.filter(o => o.filename.endsWith('.png') || o.filename.endsWith('.jpg') || o.filename.endsWith('.jpeg')); const results = []; const downloadAndWrap = async (output, fileType) => { const res = await this.helpers.request({ method: 'GET', url: output.url, encoding: null, resolveWithFullResponse: true, }); if (res.statusCode === 404) { throw new n8n_workflow_1.NodeApiError(this.getNode(), { message: `File not found at ${output.url}` }); } const buffer = Buffer.from(res.body); const base64Data = buffer.toString('base64'); const fileSize = Math.round(buffer.length / 1024 * 10) / 10 + ' kB'; let mimeType = 'application/octet-stream'; if (output.filename.endsWith('.mp4')) mimeType = 'video/mp4'; else if (output.filename.endsWith('.gif')) mimeType = 'image/gif'; else if (output.filename.endsWith('.webp')) mimeType = 'image/webp'; else if (output.filename.endsWith('.png')) mimeType = 'image/png'; else if (output.filename.endsWith('.jpg') || output.filename.endsWith('.jpeg')) mimeType = 'image/jpeg'; results.push({ json: { mimeType, fileName: output.filename, data: base64Data, status: promptResult.status, }, binary: { data: { fileName: output.filename, data: base64Data, fileType, fileSize, fileExtension: output.filename.split('.').pop(), mimeType, }, }, }); }; for (const v of videoOutputs) await downloadAndWrap(v, 'video'); for (const i of imageOutputs) await downloadAndWrap(i, 'image'); return [results]; } catch (err) { throw new n8n_workflow_1.NodeApiError(this.getNode(), { message: err.message }); } } } exports.ComfyuiWfToMedia = ComfyuiWfToMedia; //# sourceMappingURL=ComfyuiWfToMedia.node.js.map