n8n-nodes-eranol 0.1.1 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Eranol
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,60 @@
1
+ # n8n-nodes-eranol
2
+
3
+ This is an n8n community node that lets you professionaly process media using the [Eranol FFmpeg API](https://www.eranol.com). Eranol provides a powerful, cloud-based FFmpeg engine for video, audio, and image processing.
4
+
5
+ [n8n](https://n8n.io/) is a [fair-code licensed](https://docs.n8n.io/reference/license/) workflow automation tool.
6
+
7
+ ## Features
8
+
9
+ - **Video Processing**: Trim, watermark, caption, overlay, progressBar, reframe, thumbnail, generate GIF, and more.
10
+ - **Audio Processing**: Denoise, highlights, remove silence, and conversion.
11
+ - **Composition**: Merge multiple images into videos with transitions and background audio.
12
+ - **Conversion**: Batch convert between common video (MP4, WebM), audio (MP3, WAV), and image (JPG, WebP) formats.
13
+ - **Job Management**: Long-running media tasks managed via a robust job system.
14
+
15
+ ## Installation
16
+
17
+ Follow the [installation guide](https://docs.n8n.io/integrations/community-nodes/installation/) in the n8n community nodes documentation.
18
+
19
+ ```bash
20
+ npm install n8n-nodes-eranol
21
+ ```
22
+
23
+ ## Credentials
24
+
25
+ You'll need an API Key from your [Eranol Dashboard](https://www.eranol.com/dashboard).
26
+
27
+ 1. Go to **Credentials** in n8n.
28
+ 2. Select **Eranol API**.
29
+ 3. Paste your **API Key**.
30
+
31
+ ## Resources & Operations
32
+
33
+ ### Video
34
+ - **Add Intro/Outro**: Seamlessly stitch intro or outro videos.
35
+ - **Caption**: Add text overlays or closed captions.
36
+ - **Extract Audio/Images**: Pull assets from your video files.
37
+ - **Generate GIF**: Convert video segments into high-quality GIFs.
38
+ - **Overlay**: Layer images or videos over your footage.
39
+ - **Progress Bar**: Add custom progress bars to your videos.
40
+ - **Reframe**: Automatically adjust video aspect ratios.
41
+ - **Thumbnail**: Generate preview images at specific timestamps.
42
+ - **Trim**: Precise cut operations.
43
+ - **Watermark**: Brand your content with logo overlays.
44
+
45
+ ### Audio
46
+ - **Denoise**: Remove background noise from recordings.
47
+ - **Highlights**: Automatically extract key moments from audio.
48
+ - **Remove Silence**: Tighten up recordings by removing dead air.
49
+
50
+ ### Compose
51
+ - **Merge**: Combine images into a slideshow video with transitions.
52
+
53
+ ### Convert
54
+ - **Video**: MP4, WebM.
55
+ - **Audio**: MP3, WAV.
56
+ - **Image**: JPG, WebP.
57
+
58
+ ## License
59
+
60
+ [MIT](LICENSE)
@@ -7,6 +7,8 @@ const audio_1 = require("./resources/audio");
7
7
  const convert_1 = require("./resources/convert");
8
8
  const compose_1 = require("./resources/compose");
9
9
  const job_1 = require("./resources/job");
10
+ const image_1 = require("./resources/image");
11
+ const notify_1 = require("./resources/notify");
10
12
  class Eranol {
11
13
  constructor() {
12
14
  this.description = {
@@ -54,10 +56,18 @@ class Eranol {
54
56
  name: 'Convert',
55
57
  value: 'convert',
56
58
  },
59
+ {
60
+ name: 'Image',
61
+ value: 'image',
62
+ },
57
63
  {
58
64
  name: 'Job',
59
65
  value: 'job',
60
66
  },
67
+ {
68
+ name: 'Notify',
69
+ value: 'notify',
70
+ },
61
71
  {
62
72
  name: 'Video',
63
73
  value: 'video',
@@ -69,6 +79,8 @@ class Eranol {
69
79
  ...audio_1.audioDescription,
70
80
  ...convert_1.convertDescription,
71
81
  ...compose_1.composeDescription,
82
+ ...image_1.imageDescription,
83
+ ...notify_1.notifyDescription,
72
84
  ...job_1.jobDescription,
73
85
  ],
74
86
  usableAsTool: true,
@@ -0,0 +1,2 @@
1
+ import type { INodeProperties } from 'n8n-workflow';
2
+ export declare const composeVideoDescription: INodeProperties[];
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.composeVideoDescription = void 0;
4
+ const displayOptions = {
5
+ show: {
6
+ resource: ['compose'],
7
+ operation: ['composeVideo'],
8
+ },
9
+ };
10
+ exports.composeVideoDescription = [
11
+ {
12
+ displayName: 'Main Video URL',
13
+ name: 'mainVideoUrl',
14
+ type: 'string',
15
+ required: true,
16
+ default: '',
17
+ displayOptions,
18
+ description: 'URL of the main/base video',
19
+ routing: {
20
+ send: {
21
+ type: 'body',
22
+ property: 'main_video_url',
23
+ },
24
+ },
25
+ },
26
+ {
27
+ displayName: 'Overlays',
28
+ name: 'overlays',
29
+ type: 'fixedCollection',
30
+ typeOptions: {
31
+ multipleValues: true,
32
+ },
33
+ required: true,
34
+ default: {},
35
+ displayOptions,
36
+ description: 'Video or image segments to overlay onto the main video at specific time ranges',
37
+ options: [
38
+ {
39
+ name: 'overlayValues',
40
+ displayName: 'Overlay',
41
+ values: [
42
+ {
43
+ displayName: 'URL',
44
+ name: 'url',
45
+ type: 'string',
46
+ default: '',
47
+ required: true,
48
+ description: 'URL of the video or image to overlay',
49
+ },
50
+ {
51
+ displayName: 'Type',
52
+ name: 'type',
53
+ type: 'options',
54
+ default: 'video',
55
+ options: [
56
+ { name: 'Video', value: 'video' },
57
+ { name: 'Image', value: 'image' },
58
+ ],
59
+ description: 'Type of the overlay media',
60
+ },
61
+ {
62
+ displayName: 'Start Time (Seconds)',
63
+ name: 'start_time',
64
+ type: 'number',
65
+ default: 0,
66
+ required: true,
67
+ description: 'When the overlay starts in the main video (seconds)',
68
+ },
69
+ {
70
+ displayName: 'End Time (Seconds)',
71
+ name: 'end_time',
72
+ type: 'number',
73
+ default: 5,
74
+ required: true,
75
+ description: 'When the overlay ends in the main video (seconds)',
76
+ },
77
+ ],
78
+ },
79
+ ],
80
+ routing: {
81
+ send: {
82
+ type: 'body',
83
+ property: 'overlays',
84
+ value: '={{$value.overlayValues}}',
85
+ },
86
+ },
87
+ },
88
+ ];
@@ -0,0 +1,2 @@
1
+ import type { INodeProperties } from 'n8n-workflow';
2
+ export declare const concatDescription: INodeProperties[];
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.concatDescription = void 0;
4
+ const displayOptions = {
5
+ show: {
6
+ resource: ['compose'],
7
+ operation: ['concat'],
8
+ },
9
+ };
10
+ exports.concatDescription = [
11
+ {
12
+ displayName: 'Clips',
13
+ name: 'clips',
14
+ type: 'fixedCollection',
15
+ typeOptions: {
16
+ multipleValues: true,
17
+ },
18
+ required: true,
19
+ default: {},
20
+ displayOptions,
21
+ description: 'Video clips to concatenate in order',
22
+ options: [
23
+ {
24
+ name: 'clipValues',
25
+ displayName: 'Clip',
26
+ values: [
27
+ {
28
+ displayName: 'Video URL',
29
+ name: 'url',
30
+ type: 'string',
31
+ default: '',
32
+ required: true,
33
+ description: 'URL of the video clip (mp4, webm, avi, mkv, mov, etc.)',
34
+ },
35
+ {
36
+ displayName: 'Order',
37
+ name: 'order',
38
+ type: 'number',
39
+ default: 1,
40
+ required: true,
41
+ description: 'Position of this clip in the final video (1 = first)',
42
+ },
43
+ ],
44
+ },
45
+ ],
46
+ routing: {
47
+ send: {
48
+ type: 'body',
49
+ property: 'clips',
50
+ value: '={{$value.clipValues}}',
51
+ },
52
+ },
53
+ },
54
+ ];
@@ -2,6 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.composeDescription = void 0;
4
4
  const merge_1 = require("./merge");
5
+ const concat_1 = require("./concat");
6
+ const composeVideo_1 = require("./composeVideo");
5
7
  exports.composeDescription = [
6
8
  {
7
9
  displayName: 'Operation',
@@ -14,6 +16,30 @@ exports.composeDescription = [
14
16
  },
15
17
  },
16
18
  options: [
19
+ {
20
+ name: 'Concat',
21
+ value: 'concat',
22
+ action: 'Concatenate videos',
23
+ description: 'Merge video clips in order into a single video',
24
+ routing: {
25
+ request: {
26
+ method: 'POST',
27
+ url: '/ffmpeg/video/concat',
28
+ },
29
+ },
30
+ },
31
+ {
32
+ name: 'Compose Video',
33
+ value: 'composeVideo',
34
+ action: 'Compose video with overlays',
35
+ description: 'Overlay video or image segments onto a main video at specific time ranges',
36
+ routing: {
37
+ request: {
38
+ method: 'POST',
39
+ url: '/ffmpeg/video/compose',
40
+ },
41
+ },
42
+ },
17
43
  {
18
44
  name: 'Merge',
19
45
  value: 'merge',
@@ -29,5 +55,7 @@ exports.composeDescription = [
29
55
  ],
30
56
  default: 'merge',
31
57
  },
58
+ ...concat_1.concatDescription,
59
+ ...composeVideo_1.composeVideoDescription,
32
60
  ...merge_1.mergeDescription,
33
61
  ];
@@ -0,0 +1,2 @@
1
+ import type { INodeProperties } from 'n8n-workflow';
2
+ export declare const generateImageDescription: INodeProperties[];
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateImageDescription = void 0;
4
+ const displayOptions = {
5
+ show: {
6
+ resource: ['image'],
7
+ operation: ['generateImage'],
8
+ },
9
+ };
10
+ exports.generateImageDescription = [
11
+ {
12
+ displayName: 'Prompt',
13
+ name: 'prompt',
14
+ type: 'string',
15
+ required: true,
16
+ default: '',
17
+ displayOptions,
18
+ description: 'Text prompt describing the image to generate',
19
+ routing: {
20
+ send: {
21
+ type: 'body',
22
+ property: 'prompt',
23
+ },
24
+ },
25
+ },
26
+ {
27
+ displayName: 'Additional Fields',
28
+ name: 'additionalFields',
29
+ type: 'collection',
30
+ placeholder: 'Add Field',
31
+ default: {},
32
+ displayOptions,
33
+ options: [
34
+ {
35
+ displayName: 'Height',
36
+ name: 'height',
37
+ type: 'number',
38
+ default: 768,
39
+ description: 'Output image height in pixels',
40
+ routing: {
41
+ send: {
42
+ type: 'body',
43
+ property: 'height',
44
+ },
45
+ },
46
+ },
47
+ {
48
+ displayName: 'Negative Prompt',
49
+ name: 'negativePrompt',
50
+ type: 'string',
51
+ default: '',
52
+ description: 'Text describing what to exclude from the image',
53
+ routing: {
54
+ send: {
55
+ type: 'body',
56
+ property: 'negative_prompt',
57
+ },
58
+ },
59
+ },
60
+ {
61
+ displayName: 'Seed',
62
+ name: 'seed',
63
+ type: 'number',
64
+ default: 42,
65
+ description: 'Random seed for reproducibility',
66
+ routing: {
67
+ send: {
68
+ type: 'body',
69
+ property: 'seed',
70
+ },
71
+ },
72
+ },
73
+ {
74
+ displayName: 'Width',
75
+ name: 'width',
76
+ type: 'number',
77
+ default: 512,
78
+ description: 'Output image width in pixels',
79
+ routing: {
80
+ send: {
81
+ type: 'body',
82
+ property: 'width',
83
+ },
84
+ },
85
+ },
86
+ ],
87
+ },
88
+ ];
@@ -0,0 +1,2 @@
1
+ import type { INodeProperties } from 'n8n-workflow';
2
+ export declare const imageStatusDescription: INodeProperties[];
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.imageStatusDescription = void 0;
4
+ const displayOptions = {
5
+ show: {
6
+ resource: ['image'],
7
+ operation: ['imageStatus'],
8
+ },
9
+ };
10
+ exports.imageStatusDescription = [
11
+ {
12
+ displayName: 'Job ID',
13
+ name: 'jobId',
14
+ type: 'string',
15
+ required: true,
16
+ default: '',
17
+ displayOptions,
18
+ description: 'The job ID returned from the Generate Image operation',
19
+ },
20
+ ];
@@ -0,0 +1,2 @@
1
+ import type { INodeProperties } from 'n8n-workflow';
2
+ export declare const imageDescription: INodeProperties[];
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.imageDescription = void 0;
4
+ const generateImage_1 = require("./generateImage");
5
+ const imageStatus_1 = require("./imageStatus");
6
+ exports.imageDescription = [
7
+ {
8
+ displayName: 'Operation',
9
+ name: 'operation',
10
+ type: 'options',
11
+ noDataExpression: true,
12
+ displayOptions: {
13
+ show: {
14
+ resource: ['image'],
15
+ },
16
+ },
17
+ options: [
18
+ {
19
+ name: 'Generate Image',
20
+ value: 'generateImage',
21
+ action: 'Generate image with AI',
22
+ description: 'Generate an image using AI from a text prompt',
23
+ routing: {
24
+ request: {
25
+ method: 'POST',
26
+ url: '/image',
27
+ },
28
+ },
29
+ },
30
+ {
31
+ name: 'Get Image Status',
32
+ value: 'imageStatus',
33
+ action: 'Get image generation status',
34
+ description: 'Check the status of an image generation job',
35
+ routing: {
36
+ request: {
37
+ method: 'GET',
38
+ url: '=/image/status/{{$parameter.jobId}}',
39
+ },
40
+ },
41
+ },
42
+ ],
43
+ default: 'generateImage',
44
+ },
45
+ ...generateImage_1.generateImageDescription,
46
+ ...imageStatus_1.imageStatusDescription,
47
+ ];
@@ -4,6 +4,7 @@ exports.jobDescription = void 0;
4
4
  const getStatus_1 = require("./getStatus");
5
5
  const getResult_1 = require("./getResult");
6
6
  const deleteJob_1 = require("./deleteJob");
7
+ const verify_1 = require("./verify");
7
8
  exports.jobDescription = [
8
9
  {
9
10
  displayName: 'Operation',
@@ -17,14 +18,14 @@ exports.jobDescription = [
17
18
  },
18
19
  options: [
19
20
  {
20
- name: 'Get Status',
21
- value: 'getStatus',
22
- action: 'Get job status',
23
- description: 'Retrieve current job status, progress, and completion data',
21
+ name: 'Delete',
22
+ value: 'deleteJob',
23
+ action: 'Delete a job',
24
+ description: 'Remove a job and its associated output file',
24
25
  routing: {
25
26
  request: {
26
- method: 'GET',
27
- url: '=/ffmpeg/status/{{$parameter.jobId}}',
27
+ method: 'DELETE',
28
+ url: '=/ffmpeg/jobs/{{$parameter.jobId}}',
28
29
  },
29
30
  },
30
31
  },
@@ -41,14 +42,26 @@ exports.jobDescription = [
41
42
  },
42
43
  },
43
44
  {
44
- name: 'Delete',
45
- value: 'deleteJob',
46
- action: 'Delete a job',
47
- description: 'Remove a job and its associated output file',
45
+ name: 'Get Status',
46
+ value: 'getStatus',
47
+ action: 'Get job status',
48
+ description: 'Retrieve current job status, progress, and completion data',
48
49
  routing: {
49
50
  request: {
50
- method: 'DELETE',
51
- url: '=/ffmpeg/jobs/{{$parameter.jobId}}',
51
+ method: 'GET',
52
+ url: '=/ffmpeg/status/{{$parameter.jobId}}',
53
+ },
54
+ },
55
+ },
56
+ {
57
+ name: 'Verify API Key',
58
+ value: 'verify',
59
+ action: 'Verify API key',
60
+ description: 'Check that the API key is valid and retrieve account details',
61
+ routing: {
62
+ request: {
63
+ method: 'GET',
64
+ url: '/verify',
52
65
  },
53
66
  },
54
67
  },
@@ -58,4 +71,5 @@ exports.jobDescription = [
58
71
  ...getStatus_1.getStatusDescription,
59
72
  ...getResult_1.getResultDescription,
60
73
  ...deleteJob_1.deleteJobDescription,
74
+ ...verify_1.verifyDescription,
61
75
  ];
@@ -0,0 +1,2 @@
1
+ import type { INodeProperties } from 'n8n-workflow';
2
+ export declare const verifyDescription: INodeProperties[];
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.verifyDescription = void 0;
4
+ exports.verifyDescription = [];
@@ -0,0 +1,2 @@
1
+ import type { INodeProperties } from 'n8n-workflow';
2
+ export declare const notifyDescription: INodeProperties[];
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.notifyDescription = void 0;
4
+ const sendEmail_1 = require("./sendEmail");
5
+ exports.notifyDescription = [
6
+ {
7
+ displayName: 'Operation',
8
+ name: 'operation',
9
+ type: 'options',
10
+ noDataExpression: true,
11
+ displayOptions: {
12
+ show: {
13
+ resource: ['notify'],
14
+ },
15
+ },
16
+ options: [
17
+ {
18
+ name: 'Send Email',
19
+ value: 'sendEmail',
20
+ action: 'Send email notification',
21
+ description: 'Send an HTML email notification',
22
+ routing: {
23
+ request: {
24
+ method: 'POST',
25
+ url: '/notifications/email',
26
+ },
27
+ },
28
+ },
29
+ ],
30
+ default: 'sendEmail',
31
+ },
32
+ ...sendEmail_1.sendEmailDescription,
33
+ ];
@@ -0,0 +1,2 @@
1
+ import type { INodeProperties } from 'n8n-workflow';
2
+ export declare const sendEmailDescription: INodeProperties[];
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sendEmailDescription = void 0;
4
+ const displayOptions = {
5
+ show: {
6
+ resource: ['notify'],
7
+ operation: ['sendEmail'],
8
+ },
9
+ };
10
+ exports.sendEmailDescription = [
11
+ {
12
+ displayName: 'To',
13
+ name: 'to',
14
+ type: 'string',
15
+ required: true,
16
+ default: '',
17
+ displayOptions,
18
+ description: 'Recipient email address',
19
+ routing: {
20
+ send: {
21
+ type: 'body',
22
+ property: 'to',
23
+ },
24
+ },
25
+ },
26
+ {
27
+ displayName: 'Subject',
28
+ name: 'subject',
29
+ type: 'string',
30
+ required: true,
31
+ default: '',
32
+ displayOptions,
33
+ description: 'Email subject line',
34
+ routing: {
35
+ send: {
36
+ type: 'body',
37
+ property: 'subject',
38
+ },
39
+ },
40
+ },
41
+ {
42
+ displayName: 'Message',
43
+ name: 'message',
44
+ type: 'string',
45
+ required: true,
46
+ default: '',
47
+ displayOptions,
48
+ description: 'HTML email body',
49
+ typeOptions: {
50
+ rows: 5,
51
+ },
52
+ routing: {
53
+ send: {
54
+ type: 'body',
55
+ property: 'message',
56
+ },
57
+ },
58
+ },
59
+ ];
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "n8n-nodes-eranol",
3
- "version": "0.1.1",
3
+ "version": "0.2.1",
4
4
  "description": "n8n community node for Eranol FFmpeg media processing API",
5
5
  "license": "MIT",
6
- "homepage": "https://github.com/eranol/n8n-nodes-eranol",
6
+ "homepage": "https://github.com/harshalone/n8n-nodes-eranol",
7
7
  "keywords": [
8
8
  "n8n-community-node-package",
9
9
  "n8n",
@@ -15,11 +15,12 @@
15
15
  ],
16
16
  "author": {
17
17
  "name": "Eranol",
18
+ "email": "harshalone@gmail.com",
18
19
  "url": "https://www.eranol.com"
19
20
  },
20
21
  "repository": {
21
22
  "type": "git",
22
- "url": "https://github.com/eranol/n8n-nodes-eranol.git"
23
+ "url": "https://github.com/harshalone/n8n-nodes-eranol.git"
23
24
  },
24
25
  "scripts": {
25
26
  "build": "n8n-node build",