n8n-nodes-piapi
Version:
Community n8n nodes for PiAPI - integrate generative AI capabilities (image, video, audio, 3D) into your workflows
425 lines • 17.5 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.KlingImageToVideo = void 0;
const GenericFunctions_1 = require("../shared/GenericFunctions");
class KlingImageToVideo {
constructor() {
this.description = {
displayName: 'PiAPI Kling Image to Video',
name: 'klingImageToVideo',
icon: 'file:../piapi.svg',
group: ['transform'],
version: 1,
description: 'Generate videos from images using PiAPI Kling',
defaults: {
name: 'Kling Image to Video',
},
inputs: ["main"],
outputs: ["main"],
credentials: [
{
name: 'piAPIApi',
required: true,
},
],
properties: [
{
displayName: 'Image Source',
name: 'imageSource',
type: 'options',
options: [
{
name: 'URL',
value: 'url',
description: 'Load image from URL',
},
{
name: 'Binary Data',
value: 'binaryData',
description: 'Use image from binary field',
},
],
default: 'url',
description: 'Where to get the image from',
},
{
displayName: 'Image URL',
name: 'imageUrl',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
imageSource: ['url'],
},
},
description: 'URL of the image to transform into a video',
},
{
displayName: 'Binary Property',
name: 'binaryPropertyName',
type: 'string',
default: 'data',
required: true,
displayOptions: {
show: {
imageSource: ['binaryData'],
},
},
description: 'Name of the binary property containing the image',
},
{
displayName: 'End Frame Image Source',
name: 'endFrameImageSource',
type: 'options',
options: [
{
name: 'None',
value: 'none',
description: 'Do not use an end frame image',
},
{
name: 'URL',
value: 'url',
description: 'Load end frame image from URL',
},
{
name: 'Binary Data',
value: 'binaryData',
description: 'Use end frame image from binary field',
},
],
default: 'none',
description: 'Whether to use an end frame image',
},
{
displayName: 'End Frame Image URL',
name: 'endFrameImageUrl',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
endFrameImageSource: ['url'],
},
},
description: 'URL of the end frame image',
},
{
displayName: 'End Frame Binary Property',
name: 'endFrameBinaryPropertyName',
type: 'string',
default: 'endFrame',
required: true,
displayOptions: {
show: {
endFrameImageSource: ['binaryData'],
},
},
description: 'Name of the binary property containing the end frame image',
},
{
displayName: 'Prompt',
name: 'prompt',
type: 'string',
typeOptions: {
rows: 4,
},
default: '',
required: false,
description: 'Text prompt to guide the video generation',
},
{
displayName: 'Negative Prompt',
name: 'negativePrompt',
type: 'string',
typeOptions: {
rows: 4,
},
default: '',
description: 'Negative prompt to avoid certain elements in the video',
},
{
displayName: 'Use Elements',
name: 'useElements',
type: 'boolean',
default: false,
description: 'Whether to use elements feature (V1.6 only)',
},
{
displayName: 'Elements',
name: 'elements',
type: 'fixedCollection',
typeOptions: {
multipleValues: true,
sortable: true,
},
default: {},
displayOptions: {
show: {
useElements: [true],
},
},
options: [
{
name: 'elementsList',
displayName: 'Element',
values: [
{
displayName: 'Element Image URL',
name: 'elementImageUrl',
type: 'string',
default: '',
description: 'URL of the element image',
},
],
},
],
description: 'Elements to include in the video (1-4 images)',
},
{
displayName: 'Duration',
name: 'duration',
type: 'options',
options: [
{
name: '5 Seconds',
value: 5,
},
{
name: '10 Seconds',
value: 10,
},
],
default: 5,
description: 'Duration of the generated video',
},
{
displayName: 'Aspect Ratio',
name: 'aspectRatio',
type: 'options',
options: [
{
name: 'Landscape (16:9)',
value: '16:9',
},
{
name: 'Portrait (9:16)',
value: '9:16',
},
{
name: 'Square (1:1)',
value: '1:1',
},
],
default: '16:9',
description: 'Aspect ratio of the generated video',
},
{
displayName: 'Mode',
name: 'mode',
type: 'options',
options: [
{
name: 'Standard',
value: 'std',
},
{
name: 'Professional',
value: 'pro',
},
],
default: 'std',
description: 'Generation mode of the video',
},
{
displayName: 'Version',
name: 'version',
type: 'options',
options: [
{
name: 'V1.0',
value: '1.0',
},
{
name: 'V1.5',
value: '1.5',
},
{
name: 'V1.6',
value: '1.6',
},
{
name: 'V2.0 ($0.96 for 5s, $1.92 for 10s)',
value: '2.0',
description: 'Warning: Higher price',
},
{
name: 'V2.1',
value: '2.1',
},
{
name: 'V2.1 Master',
value: '2.1-master',
description: 'Warning: Higher price',
},
],
default: '1.6',
description: 'Model version to use',
},
{
displayName: 'CFG Scale',
name: 'cfgScale',
type: 'number',
typeOptions: {
minValue: 0,
maxValue: 1,
numberPrecision: 2,
},
default: 0.5,
description: 'How strongly the video adheres to the prompt (between 0-1, recommended: 0.5)',
},
{
displayName: 'Wait for Completion',
name: 'waitForCompletion',
type: 'boolean',
default: false,
description: 'Whether to wait for the task to complete before returning',
},
],
};
}
async execute() {
var _a, _b;
const items = this.getInputData();
const returnData = [];
for (let i = 0; i < items.length; i++) {
try {
const imageSource = this.getNodeParameter('imageSource', i);
const endFrameImageSource = this.getNodeParameter('endFrameImageSource', i);
const prompt = this.getNodeParameter('prompt', i, '');
const negativePrompt = this.getNodeParameter('negativePrompt', i, '');
const duration = this.getNodeParameter('duration', i);
const aspectRatio = this.getNodeParameter('aspectRatio', i);
const mode = this.getNodeParameter('mode', i);
const version = this.getNodeParameter('version', i);
const cfgScale = this.getNodeParameter('cfgScale', i);
const useElements = this.getNodeParameter('useElements', i, false);
const waitForCompletion = this.getNodeParameter('waitForCompletion', i, false);
let imageUrl = '';
let endFrameImageUrl = '';
let elements = [];
if (imageSource === 'url') {
imageUrl = this.getNodeParameter('imageUrl', i);
try {
new URL(imageUrl);
}
catch (error) {
throw new Error(`Invalid image URL: ${error.message}`);
}
}
else if (imageSource === 'binaryData') {
const binaryPropertyName = this.getNodeParameter('binaryPropertyName', i);
const binaryItem = (_a = items[i].binary) === null || _a === void 0 ? void 0 : _a[binaryPropertyName];
if (!binaryItem) {
throw new Error(`No binary data found in property ${binaryPropertyName}`);
}
const binaryData = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName);
if (!binaryData) {
throw new Error(`No binary data found in property ${binaryPropertyName}`);
}
const binaryMimeType = binaryItem.mimeType || 'image/png';
imageUrl = `data:${binaryMimeType};base64,${binaryData.toString('base64')}`;
}
if (endFrameImageSource === 'url') {
endFrameImageUrl = this.getNodeParameter('endFrameImageUrl', i);
try {
new URL(endFrameImageUrl);
}
catch (error) {
throw new Error(`Invalid end frame image URL: ${error.message}`);
}
}
else if (endFrameImageSource === 'binaryData') {
const endFrameBinaryPropertyName = this.getNodeParameter('endFrameBinaryPropertyName', i);
const binaryItem = (_b = items[i].binary) === null || _b === void 0 ? void 0 : _b[endFrameBinaryPropertyName];
if (!binaryItem) {
throw new Error(`No binary data found in property ${endFrameBinaryPropertyName}`);
}
const binaryData = await this.helpers.getBinaryDataBuffer(i, endFrameBinaryPropertyName);
if (!binaryData) {
throw new Error(`No binary data found in property ${endFrameBinaryPropertyName}`);
}
const binaryMimeType = binaryItem.mimeType || 'image/png';
endFrameImageUrl = `data:${binaryMimeType};base64,${binaryData.toString('base64')}`;
}
if (useElements) {
const elementsList = this.getNodeParameter('elements.elementsList', i, []);
if (elementsList.length === 0) {
throw new Error('Elements feature requires at least one element image');
}
else if (elementsList.length > 4) {
throw new Error('Elements feature supports a maximum of 4 element images');
}
elements = elementsList.map(element => ({
image_url: element.elementImageUrl,
}));
}
const body = {
model: 'kling',
task_type: 'video_generation',
input: {
prompt,
negative_prompt: negativePrompt,
duration,
aspect_ratio: aspectRatio,
mode,
version,
cfg_scale: cfgScale,
},
config: {
webhook_config: {
endpoint: '',
secret: '',
},
},
};
if (!useElements) {
body.input.image_url = imageUrl;
if (endFrameImageSource !== 'none' && endFrameImageUrl) {
body.input.image_tail_url = endFrameImageUrl;
}
}
else {
body.input.elements = elements;
}
const response = await GenericFunctions_1.piApiRequest.call(this, 'POST', '/api/v1/task', body);
if (response.code !== 200) {
throw new Error(`API Error: ${response.message}`);
}
const taskId = response.data.task_id;
let taskData = response.data;
if (waitForCompletion) {
taskData = await GenericFunctions_1.waitForTaskCompletion.call(this, taskId);
}
returnData.push({
json: taskData,
});
}
catch (error) {
if (this.continueOnFail()) {
returnData.push({
json: {
error: error.message,
},
});
continue;
}
throw error;
}
}
return [returnData];
}
}
exports.KlingImageToVideo = KlingImageToVideo;
//# sourceMappingURL=KlingImageToVideo.node.js.map
;