n8n-nodes-jiemeng
Version:
n8n node for Jiemeng AI video generation using Volcengine Doubao Seedance model. Generate videos from images and text prompts.
220 lines • 9.77 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Jiemeng = void 0;
const n8n_workflow_1 = require("n8n-workflow");
class Jiemeng {
constructor() {
this.description = {
displayName: 'Jiemeng',
name: 'jiemeng',
icon: 'file:jiemeng.svg',
group: ['transform'],
version: 1,
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
description: 'Use Jiemeng API to generate videos from images and prompts',
defaults: {
name: 'Jiemeng',
},
inputs: ['main'],
outputs: ['main'],
credentials: [
{
name: 'jiemengApi',
required: true,
},
],
properties: [
{
displayName: 'Resource',
name: 'resource',
type: 'options',
noDataExpression: true,
options: [
{
name: 'Video Generation',
value: 'videoGeneration',
},
],
default: 'videoGeneration',
},
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['videoGeneration'],
},
},
options: [
{
name: 'Image to Video',
value: 'imageToVideo',
action: 'Generate a video from an image and a prompt',
},
],
default: 'imageToVideo',
},
{
displayName: 'Image URL',
name: 'imageUrl',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
resource: ['videoGeneration'],
operation: ['imageToVideo'],
},
},
description: 'The URL of the image to use as the base for the video',
},
{
displayName: 'Prompt',
name: 'prompt',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
resource: ['videoGeneration'],
operation: ['imageToVideo'],
},
},
description: 'The prompt to guide the video generation',
},
],
};
}
static getErrorSuggestions(errorCode) {
switch (errorCode) {
case 'ModelNotOpen':
return [
'前往火山方舟控制台开通模型服务',
'访问: https://console.volcengine.com/ark/region:ark+cn-beijing/openManagement',
'在「视觉大模型」下找到 Seedance 相关模型并开通服务',
'确保账户有足够的额度'
];
case 'InvalidEndpoint.NotFound':
return [
'检查 API 端点 URL 是否正确',
'确认使用的是正确的火山引擎 API 地址'
];
case 'Unauthorized':
return [
'检查 API Key 是否正确',
'确认 API Key 有相应的权限',
'检查 API Key 是否已过期'
];
default:
return ['请检查网络连接和API配置'];
}
}
async execute() {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
const items = this.getInputData();
const returnData = [];
for (let i = 0; i < items.length; i++) {
try {
const imageUrl = this.getNodeParameter('imageUrl', i, '');
const prompt = this.getNodeParameter('prompt', i, '');
const credentials = await this.getCredentials('jiemengApi');
const createTaskBody = {
model: 'doubao-seedance-1-0-lite-i2v-250428',
content: [
{
type: 'text',
text: prompt,
},
{
type: 'image_url',
image_url: {
url: imageUrl,
},
}
],
};
const createTaskResponse = await this.helpers.request({
method: 'POST',
url: 'https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks',
headers: {
'Authorization': `Bearer ${credentials.apiKey}`,
'Content-Type': 'application/json',
'Accept': 'application/json',
},
body: createTaskBody,
json: true,
});
const taskId = createTaskResponse.id;
if (!taskId) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Failed to create generation task. No task ID returned.');
}
let taskResult;
let taskDone = false;
const maxRetries = 60;
let retries = 0;
while (!taskDone && retries < maxRetries) {
taskResult = await this.helpers.request({
method: 'GET',
url: `https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks/${taskId}`,
headers: {
'Authorization': `Bearer ${credentials.apiKey}`,
'Accept': 'application/json',
},
json: true,
});
if (taskResult.status === 'done' || taskResult.status === 'succeeded') {
taskDone = true;
}
else if (taskResult.status === 'failed' || taskResult.status === 'canceled') {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Task failed with status: ${taskResult.status}`, { itemIndex: i });
}
else {
retries++;
await new Promise(resolve => setTimeout(resolve, 5000));
}
}
if (!taskDone) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Task timed out after 5 minutes.', { itemIndex: i });
}
const outputData = {
success: true,
taskId: taskResult.id,
status: taskResult.status,
videoUrl: ((_a = taskResult.content) === null || _a === void 0 ? void 0 : _a.video_url) || null,
model: taskResult.model,
usage: taskResult.usage,
createdAt: taskResult.created_at,
updatedAt: taskResult.updated_at,
originalResponse: taskResult,
};
returnData.push({
json: outputData,
pairedItem: { item: i },
});
}
catch (error) {
if (this.continueOnFail()) {
const errorData = {
success: false,
error: error.message,
errorCode: ((_d = (_c = (_b = error.response) === null || _b === void 0 ? void 0 : _b.data) === null || _c === void 0 ? void 0 : _c.error) === null || _d === void 0 ? void 0 : _d.code) || 'UNKNOWN_ERROR',
errorType: ((_g = (_f = (_e = error.response) === null || _e === void 0 ? void 0 : _e.data) === null || _f === void 0 ? void 0 : _f.error) === null || _g === void 0 ? void 0 : _g.type) || 'UNKNOWN_TYPE',
statusCode: ((_h = error.response) === null || _h === void 0 ? void 0 : _h.status) || null,
suggestions: Jiemeng.getErrorSuggestions(((_l = (_k = (_j = error.response) === null || _j === void 0 ? void 0 : _j.data) === null || _k === void 0 ? void 0 : _k.error) === null || _l === void 0 ? void 0 : _l.code) || 'UNKNOWN_ERROR'),
};
returnData.push({
json: errorData,
pairedItem: { item: i },
});
continue;
}
throw error;
}
}
return this.prepareOutputData(returnData);
}
}
exports.Jiemeng = Jiemeng;
//# sourceMappingURL=Jiemeng.node.js.map