@asyncai/n8n-nodes-asyncai 0.1.0

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.md ADDED
@@ -0,0 +1,19 @@
1
+ Copyright 2025 n8n
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7
+ of the Software, and to permit persons to whom the Software is furnished to do
8
+ so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,34 @@
1
+ # @asyncai/n8n-nodes-asyncai
2
+
3
+ This is the official AsyncAI n8n community node.
4
+
5
+ [n8n](https://n8n.io/) is a [fair-code licensed](https://docs.n8n.io/reference/license/) workflow automation platform.
6
+
7
+ [Installation](#installation)
8
+ [Operations](#operations)
9
+ [Credentials](#credentials)
10
+ [Resources](#resources)
11
+
12
+ ## Installation
13
+
14
+ Follow the [installation guide](https://docs.n8n.io/integrations/community-nodes/installation/) in the n8n community nodes documentation.
15
+
16
+ ## Operations
17
+
18
+ ### Speech
19
+ - Text to Speech
20
+
21
+ ### Voice
22
+ - Get
23
+ - Create Clone
24
+ - Delete
25
+
26
+ ## Credentials
27
+
28
+ This node requires an API Key from AsyncAI, You can generate one by going to your [Account](https://app.async.ai/auth).
29
+
30
+
31
+ ## Resources
32
+
33
+ * [n8n community nodes documentation](https://docs.n8n.io/integrations/#community-nodes)
34
+ * [AsyncAI Documentation](https://docs.async.ai)
@@ -0,0 +1,9 @@
1
+ import { IAuthenticateGeneric, ICredentialTestRequest, ICredentialType, INodeProperties } from 'n8n-workflow';
2
+ export declare class AsyncAIApi implements ICredentialType {
3
+ name: string;
4
+ displayName: string;
5
+ documentationUrl: string;
6
+ properties: INodeProperties[];
7
+ authenticate: IAuthenticateGeneric;
8
+ test: ICredentialTestRequest | undefined;
9
+ }
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AsyncAIApi = void 0;
4
+ class AsyncAIApi {
5
+ constructor() {
6
+ this.name = 'asyncAIApi';
7
+ this.displayName = 'AsyncAI API';
8
+ this.documentationUrl = 'https://docs.async.ai/';
9
+ this.properties = [
10
+ {
11
+ displayName: 'AsyncAI API Key',
12
+ name: 'xApiKey',
13
+ type: 'string',
14
+ typeOptions: { password: true },
15
+ default: '',
16
+ },
17
+ ];
18
+ this.authenticate = {
19
+ type: 'generic',
20
+ properties: {
21
+ headers: {
22
+ 'x-api-key': '={{$credentials.xApiKey}}',
23
+ },
24
+ },
25
+ };
26
+ this.test = {
27
+ request: {
28
+ baseURL: 'https://api.async.ai',
29
+ url: '/voices',
30
+ method: 'POST',
31
+ },
32
+ };
33
+ }
34
+ }
35
+ exports.AsyncAIApi = AsyncAIApi;
36
+ //# sourceMappingURL=AsyncAIApi.credentials.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AsyncAIApi.credentials.js","sourceRoot":"","sources":["../../credentials/AsyncAIApi.credentials.ts"],"names":[],"mappings":";;;AAOA,MAAa,UAAU;IAAvB;QACC,SAAI,GAAG,YAAY,CAAC;QACpB,gBAAW,GAAG,aAAa,CAAC;QAC5B,qBAAgB,GAAG,wBAAwB,CAAC;QAC5C,eAAU,GAAsB;YAC/B;gBACC,WAAW,EAAE,iBAAiB;gBAC9B,IAAI,EAAE,SAAS;gBACf,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE;gBAC/B,OAAO,EAAE,EAAE;aACX;SACD,CAAC;QAEF,iBAAY,GAAyB;YACpC,IAAI,EAAE,SAAS;YACf,UAAU,EAAE;gBACX,OAAO,EAAE;oBACR,WAAW,EAAE,2BAA2B;iBACxC;aACD;SACD,CAAC;QAEF,SAAI,GAAuC;YAC1C,OAAO,EAAE;gBACR,OAAO,EAAE,sBAAsB;gBAC/B,GAAG,EAAE,SAAS;gBACd,MAAM,EAAE,MAAM;aACd;SACD,CAAC;IACH,CAAC;CAAA;AA9BD,gCA8BC"}
@@ -0,0 +1,9 @@
1
+ import { INodeType, INodeTypeDescription } from 'n8n-workflow';
2
+ export declare class AsyncAi implements INodeType {
3
+ description: INodeTypeDescription;
4
+ methods: {
5
+ listSearch: {
6
+ listVoices(this: import("n8n-workflow").ILoadOptionsFunctions): Promise<import("n8n-workflow").INodeListSearchResult>;
7
+ };
8
+ };
9
+ }
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AsyncAi = void 0;
4
+ const voice_1 = require("./Descriptions/voice");
5
+ const utils_1 = require("./Descriptions/utils");
6
+ const speech_1 = require("./Descriptions/speech");
7
+ class AsyncAi {
8
+ constructor() {
9
+ this.description = {
10
+ displayName: 'Async',
11
+ name: 'asyncAi',
12
+ icon: 'file:async.svg',
13
+ group: ['transform'],
14
+ version: 1,
15
+ subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
16
+ description: 'Interact with Async API',
17
+ defaults: {
18
+ name: 'Async',
19
+ },
20
+ usableAsTool: true,
21
+ inputs: ['main'],
22
+ outputs: ['main'],
23
+ credentials: [
24
+ {
25
+ name: 'asyncAIApi',
26
+ required: true,
27
+ },
28
+ ],
29
+ requestDefaults: {
30
+ method: 'GET',
31
+ baseURL: 'https://api.async.ai/',
32
+ headers: {
33
+ 'Content-Type': 'application/json',
34
+ },
35
+ },
36
+ properties: [
37
+ {
38
+ displayName: 'Resource',
39
+ name: 'resource',
40
+ type: 'options',
41
+ noDataExpression: true,
42
+ options: [
43
+ {
44
+ name: 'Voice',
45
+ value: 'voice',
46
+ },
47
+ {
48
+ name: 'Speech',
49
+ value: 'speech',
50
+ },
51
+ ],
52
+ default: 'voice',
53
+ },
54
+ ...voice_1.VoiceOperations,
55
+ ...voice_1.VoiceFields,
56
+ ...speech_1.SpeechOperations,
57
+ ...speech_1.SpeechFields,
58
+ ]
59
+ };
60
+ this.methods = {
61
+ listSearch: utils_1.listSearch,
62
+ };
63
+ }
64
+ }
65
+ exports.AsyncAi = AsyncAi;
66
+ //# sourceMappingURL=AsyncAi.node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AsyncAi.node.js","sourceRoot":"","sources":["../../../nodes/asyncai/AsyncAi.node.ts"],"names":[],"mappings":";;;AACA,gDAAoE;AACpE,gDAAkD;AAClD,kDAAuE;AAEvE,MAAa,OAAO;IAApB;QACC,gBAAW,GAAyB;YACnC,WAAW,EAAE,OAAO;YACpB,IAAI,EAAE,SAAS;YACf,IAAI,EAAE,gBAAgB;YACtB,KAAK,EAAE,CAAC,WAAW,CAAC;YACpB,OAAO,EAAE,CAAC;YACV,QAAQ,EAAE,8DAA8D;YACxE,WAAW,EAAE,yBAAyB;YACtC,QAAQ,EAAE;gBACT,IAAI,EAAE,OAAO;aACb;YACD,YAAY,EAAE,IAAI;YAClB,MAAM,EAAE,CAAC,MAAM,CAAC;YAChB,OAAO,EAAE,CAAC,MAAM,CAAC;YACjB,WAAW,EAAE;gBACZ;oBACC,IAAI,EAAE,YAAY;oBAClB,QAAQ,EAAE,IAAI;iBACd;aACD;YACD,eAAe,EAAE;gBAChB,MAAM,EAAE,KAAK;gBACb,OAAO,EAAE,uBAAuB;gBAChC,OAAO,EAAE;oBACR,cAAc,EAAE,kBAAkB;iBAClC;aACD;YACD,UAAU,EAAE;gBACX;oBACC,WAAW,EAAE,UAAU;oBACvB,IAAI,EAAE,UAAU;oBAChB,IAAI,EAAE,SAAS;oBACf,gBAAgB,EAAE,IAAI;oBACtB,OAAO,EAAE;wBACR;4BACC,IAAI,EAAE,OAAO;4BACb,KAAK,EAAE,OAAO;yBACd;wBACD;4BACC,IAAI,EAAE,QAAQ;4BACd,KAAK,EAAE,QAAQ;yBACf;qBACD;oBACD,OAAO,EAAE,OAAO;iBAChB;gBACD,GAAG,uBAAe;gBAClB,GAAG,mBAAW;gBACd,GAAG,yBAAgB;gBACnB,GAAG,qBAAY;aACf;SACD,CAAC;QAEF,YAAO,GAAG;YACT,UAAU,EAAV,kBAAU;SACV,CAAC;IACH,CAAC;CAAA;AAxDD,0BAwDC"}
@@ -0,0 +1,3 @@
1
+ import { INodeProperties } from "n8n-workflow";
2
+ export declare const SpeechOperations: INodeProperties[];
3
+ export declare const SpeechFields: INodeProperties[];
@@ -0,0 +1,215 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SpeechFields = exports.SpeechOperations = void 0;
4
+ exports.SpeechOperations = [
5
+ {
6
+ displayName: 'Operation',
7
+ name: 'operation',
8
+ type: 'options',
9
+ noDataExpression: true,
10
+ options: [
11
+ {
12
+ name: 'Text to Speech',
13
+ value: 'textToSpeech',
14
+ description: 'Converts text into speech and returns audio',
15
+ action: 'Convert text to speech',
16
+ routing: {
17
+ request: {
18
+ method: 'POST',
19
+ url: '={{"/text_to_speech"}}',
20
+ headers: { 'content-type': 'application/json' },
21
+ returnFullResponse: true,
22
+ encoding: 'arraybuffer',
23
+ },
24
+ send: {
25
+ preSend: [preSendTexttoSpeech],
26
+ },
27
+ output: {
28
+ postReceive: [returnBinaryData],
29
+ }
30
+ }
31
+ },
32
+ ],
33
+ default: 'textToSpeech',
34
+ displayOptions: {
35
+ show: {
36
+ resource: ['speech'],
37
+ },
38
+ },
39
+ }
40
+ ];
41
+ exports.SpeechFields = [
42
+ {
43
+ displayName: 'Voice',
44
+ description: 'Select the voice to use for the conversion',
45
+ name: 'voice',
46
+ type: 'resourceLocator',
47
+ default: { mode: 'list', value: null },
48
+ displayOptions: {
49
+ show: {
50
+ resource: ['speech'],
51
+ operation: ['textToSpeech'],
52
+ },
53
+ },
54
+ modes: [
55
+ {
56
+ displayName: 'From list',
57
+ name: 'list',
58
+ type: 'list',
59
+ typeOptions: {
60
+ searchListMethod: 'listVoices',
61
+ searchable: true,
62
+ },
63
+ },
64
+ {
65
+ displayName: 'ID',
66
+ name: 'id',
67
+ type: 'string',
68
+ placeholder: 'e0f39dc4-f691-4e78-bba5-5c636692cc04',
69
+ },
70
+ ],
71
+ routing: {
72
+ send: {
73
+ type: 'body',
74
+ property: 'voice',
75
+ value: '={{ (function(v){ return { mode: "id", id: (typeof v==="string" ? v : (v && v.id) || (v && v.value && (v.value.id || v.value)) || v) }; })($parameter["voice"]) }}',
76
+ },
77
+ },
78
+ required: true,
79
+ },
80
+ {
81
+ displayName: 'Text',
82
+ description: 'The text that will get converted into speech',
83
+ placeholder: 'e.g. The archaeologists discovery would rewrite history.',
84
+ name: 'text',
85
+ type: 'string',
86
+ default: '',
87
+ displayOptions: {
88
+ show: {
89
+ resource: ['speech'],
90
+ operation: ['textToSpeech'],
91
+ },
92
+ },
93
+ required: true,
94
+ routing: {
95
+ send: { type: 'body', property: 'transcript' },
96
+ },
97
+ },
98
+ {
99
+ displayName: 'Additional Options',
100
+ name: 'additionalOptions',
101
+ type: 'collection',
102
+ placeholder: 'Add Option',
103
+ default: {},
104
+ displayOptions: {
105
+ show: {
106
+ resource: ['speech'],
107
+ operation: ['textToSpeech'],
108
+ },
109
+ },
110
+ options: [
111
+ {
112
+ displayName: 'Bit Rate',
113
+ name: 'bitRate',
114
+ type: 'number',
115
+ typeOptions: { minValue: 32000, maxValue: 320000, numberStepSize: 1000 },
116
+ default: 192000,
117
+ description: 'Only used with MP3',
118
+ displayOptions: {
119
+ show: { outputContainer: ['mp3'] },
120
+ },
121
+ },
122
+ {
123
+ displayName: 'Container',
124
+ name: 'outputContainer',
125
+ description: 'Output audio format',
126
+ type: 'options',
127
+ options: [
128
+ { name: 'MP3', value: 'mp3' },
129
+ { name: 'WAV', value: 'wav' },
130
+ ],
131
+ default: 'mp3',
132
+ },
133
+ {
134
+ displayName: 'Encoding',
135
+ name: 'encoding',
136
+ description: 'Only used when container is WAV',
137
+ type: 'options',
138
+ default: 'pcm_s16le',
139
+ displayOptions: {
140
+ show: { outputContainer: ['wav'] },
141
+ },
142
+ options: [
143
+ { name: 'PCM 32bit', value: 'pcm_f32le' },
144
+ { name: 'PSM 16bit', value: 'pcm_s16le' },
145
+ ],
146
+ },
147
+ {
148
+ displayName: 'Model',
149
+ description: 'Select the model to use for the conversion',
150
+ name: 'model',
151
+ type: 'options',
152
+ default: 'asyncflow_multilingual_v1.0',
153
+ options: [
154
+ { name: 'AsyncFlow V2', value: 'asyncflow_v2.0', description: 'English only' },
155
+ { name: 'AsyncFlow Multilingual V1', value: 'asyncflow_multilingual_v1.0', description: 'Multilingual' },
156
+ ],
157
+ routing: {
158
+ send: {
159
+ type: 'body',
160
+ property: 'model_id',
161
+ },
162
+ },
163
+ },
164
+ {
165
+ displayName: 'Sample Rate',
166
+ name: 'sampleRate',
167
+ type: 'number',
168
+ typeOptions: { minValue: 8000, maxValue: 48000, numberStepSize: 1000 },
169
+ default: 44100,
170
+ description: 'Output audio sample rate (Hz)',
171
+ },
172
+ ],
173
+ },
174
+ ];
175
+ async function returnBinaryData(items, responseData) {
176
+ var _a, _b;
177
+ const op = this.getNodeParameter('operation');
178
+ const contentType = (((_a = responseData.headers) === null || _a === void 0 ? void 0 : _a['content-type']) || ((_b = responseData.headers) === null || _b === void 0 ? void 0 : _b['Content-Type']) || '').toString();
179
+ const buf = responseData.body;
180
+ if (contentType.includes('application/json') || ((buf === null || buf === void 0 ? void 0 : buf.length) && buf[0] === 0x7B)) {
181
+ try {
182
+ const text = buf.toString('utf8');
183
+ const json = JSON.parse(text);
184
+ throw new Error(`Async TTS returned JSON instead of audio: ${json.message || text}`);
185
+ }
186
+ catch {
187
+ throw new Error(`Async TTS returned non-audio response: ${buf.toString('utf8').slice(0, 400)}...`);
188
+ }
189
+ }
190
+ const isMp3 = contentType.includes('audio/mpeg') || contentType.includes('audio/mp3');
191
+ const ext = isMp3 ? 'mp3' : (contentType.includes('audio') ? 'wav' : 'bin');
192
+ const mime = isMp3 ? 'audio/mpeg' : (contentType.includes('audio') ? contentType : 'application/octet-stream');
193
+ const binaryData = await this.helpers.prepareBinaryData(buf, `audio.${op}.${ext}`, mime);
194
+ return items.map(() => ({ json: responseData.headers, binary: { data: binaryData } }));
195
+ }
196
+ async function preSendTexttoSpeech(requestOptions) {
197
+ var _a, _b, _c, _d, _e, _f;
198
+ const opts = (this.getNodeParameter('additionalOptions', 0, {}) || {});
199
+ const body = (_a = requestOptions.body) !== null && _a !== void 0 ? _a : (requestOptions.body = {});
200
+ if (!body.model_id) {
201
+ body.model_id = (_b = opts.model) !== null && _b !== void 0 ? _b : 'asyncflow_multilingual_v1.0';
202
+ }
203
+ const container = (_c = opts.outputContainer) !== null && _c !== void 0 ? _c : 'mp3';
204
+ const output_format = { container };
205
+ output_format.sample_rate = (_d = opts.sampleRate) !== null && _d !== void 0 ? _d : 44100;
206
+ if (container === 'wav') {
207
+ output_format.encoding = (_e = opts.encoding) !== null && _e !== void 0 ? _e : 'pcm_s16le';
208
+ }
209
+ else if (container === 'mp3') {
210
+ output_format.bit_rate = (_f = opts.bitRate) !== null && _f !== void 0 ? _f : 192000;
211
+ }
212
+ body.output_format = output_format;
213
+ return requestOptions;
214
+ }
215
+ //# sourceMappingURL=speech.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"speech.js","sourceRoot":"","sources":["../../../../nodes/asyncai/Descriptions/speech.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { ILoadOptionsFunctions, INodeListSearchResult } from "n8n-workflow";
2
+ export declare const listSearch: {
3
+ listVoices(this: ILoadOptionsFunctions): Promise<INodeListSearchResult>;
4
+ };
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.listSearch = void 0;
4
+ exports.listSearch = {
5
+ async listVoices() {
6
+ const voicesResponse = await this.helpers.httpRequestWithAuthentication.call(this, 'asyncAIApi', {
7
+ method: 'POST',
8
+ url: 'https://api.async.ai/voices',
9
+ });
10
+ const returnData = voicesResponse.voices.map((voice) => ({
11
+ name: voice.name,
12
+ value: voice.voice_id,
13
+ }));
14
+ return {
15
+ results: returnData,
16
+ };
17
+ },
18
+ };
19
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../nodes/asyncai/Descriptions/utils.ts"],"names":[],"mappings":";;;AASa,QAAA,UAAU,GAAG;IACzB,KAAK,CAAC,UAAU;QACf,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,6BAA6B,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,EAAE;YAChG,MAAM,EAAE,MAAM;YACd,GAAG,EAAE,6BAA6B;SAClC,CAAyB,CAAC;QAE3B,MAAM,UAAU,GAA2B,cAAc,CAAC,MAAM,CAAC,GAAG,CACnE,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YACX,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,KAAK,EAAE,KAAK,CAAC,QAAQ;SACrB,CAAC,CACF,CAAC;QACF,OAAO;YACN,OAAO,EAAE,UAAU;SACnB,CAAC;IACH,CAAC;CACD,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { INodeProperties } from 'n8n-workflow';
2
+ export declare const VoiceOperations: INodeProperties[];
3
+ export declare const VoiceFields: INodeProperties[];
@@ -0,0 +1,218 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.VoiceFields = exports.VoiceOperations = void 0;
4
+ exports.VoiceOperations = [
5
+ {
6
+ displayName: 'Operation',
7
+ name: 'operation',
8
+ type: 'options',
9
+ noDataExpression: true,
10
+ options: [
11
+ {
12
+ name: 'Get',
13
+ value: 'get',
14
+ action: 'Get a voice',
15
+ description: 'Returns metadata about a specific voice',
16
+ routing: {
17
+ request: {
18
+ method: 'GET',
19
+ url: '={{"/voices/" + $parameter["voice"] }}',
20
+ },
21
+ output: {
22
+ postReceive: [
23
+ {
24
+ type: 'setKeyValue',
25
+ enabled: '={{$parameter["simplify"]}}',
26
+ properties: {
27
+ voice_id: '={{$responseItem.voice_id}}',
28
+ name: '={{$responseItem.name}}',
29
+ category: '={{$responseItem.category}}',
30
+ labels: '={{$responseItem.labels}}',
31
+ description: '={{$responseItem.description}}',
32
+ preview_url: '={{$responseItem.preview_url}}',
33
+ },
34
+ },
35
+ ],
36
+ },
37
+ },
38
+ },
39
+ {
40
+ name: 'Create Clone',
41
+ value: 'createClone',
42
+ action: 'Create a voice clone',
43
+ description: 'Create a voice clone from audio files',
44
+ routing: {
45
+ send: {
46
+ preSend: [preSendAudioFiles],
47
+ },
48
+ request: {
49
+ url: '/voices/clone',
50
+ returnFullResponse: true,
51
+ method: 'POST',
52
+ headers: {
53
+ 'Content-Type': 'multipart/form-data',
54
+ },
55
+ },
56
+ },
57
+ },
58
+ {
59
+ name: 'Delete',
60
+ value: 'delete',
61
+ action: 'Delete a voice',
62
+ description: 'Delete a specific voice',
63
+ routing: {
64
+ request: {
65
+ url: '={{"/voices/" + $parameter["voice"]}}',
66
+ method: 'DELETE',
67
+ },
68
+ },
69
+ },
70
+ ],
71
+ default: 'get',
72
+ displayOptions: {
73
+ show: {
74
+ resource: ['voice'],
75
+ },
76
+ },
77
+ }
78
+ ];
79
+ exports.VoiceFields = [
80
+ {
81
+ displayName: 'Voice',
82
+ description: 'The voice you want to use',
83
+ name: 'voice',
84
+ type: 'resourceLocator',
85
+ default: { mode: 'list', value: null },
86
+ displayOptions: {
87
+ show: {
88
+ resource: ['voice'],
89
+ operation: ['delete', 'get'],
90
+ },
91
+ },
92
+ modes: [
93
+ {
94
+ displayName: 'From list',
95
+ name: 'list',
96
+ type: 'list',
97
+ typeOptions: {
98
+ searchListMethod: 'listVoices',
99
+ searchable: true,
100
+ },
101
+ },
102
+ {
103
+ displayName: 'ID',
104
+ name: 'id',
105
+ type: 'string',
106
+ placeholder: 'e0f39dc4-f691-4e78-bba5-5c636692cc04',
107
+ },
108
+ ],
109
+ required: true,
110
+ },
111
+ {
112
+ displayName: 'Name',
113
+ name: 'name',
114
+ type: 'string',
115
+ default: '',
116
+ placeholder: 'e.g. Anthony',
117
+ description: 'The name of the cloned voice',
118
+ displayOptions: {
119
+ show: {
120
+ resource: ['voice'],
121
+ operation: ['createClone'],
122
+ },
123
+ },
124
+ },
125
+ {
126
+ displayName: 'Audio Files',
127
+ name: 'audioFiles',
128
+ type: 'string',
129
+ default: '',
130
+ placeholder: 'data',
131
+ description: 'The audio files to be used for voice cloning',
132
+ displayOptions: {
133
+ show: {
134
+ resource: ['voice'],
135
+ operation: ['createClone'],
136
+ },
137
+ },
138
+ },
139
+ {
140
+ displayName: 'Additional Fields',
141
+ name: 'additionalFields',
142
+ type: 'collection',
143
+ default: {},
144
+ placeholder: 'Add Fields',
145
+ displayOptions: {
146
+ show: {
147
+ resource: ['voice'],
148
+ operation: ['createClone'],
149
+ },
150
+ },
151
+ options: [
152
+ {
153
+ displayName: 'Accent',
154
+ description: 'An accent of the voice',
155
+ name: 'accent',
156
+ type: 'string',
157
+ default: ``,
158
+ placeholder: 'e.g. American (US)',
159
+ },
160
+ {
161
+ displayName: 'Description',
162
+ description: 'A description of the voice',
163
+ name: 'description',
164
+ type: 'string',
165
+ default: ``,
166
+ placeholder: 'e.g. Calm, neutral-tone female voice',
167
+ },
168
+ {
169
+ displayName: 'Enhance',
170
+ description: 'Whether to enhance (remove background noise of) the audio clip before cloning',
171
+ name: 'enhance',
172
+ type: 'boolean',
173
+ default: false
174
+ },
175
+ {
176
+ displayName: 'Gender',
177
+ description: 'Gender of the voice',
178
+ name: 'gender',
179
+ type: 'options',
180
+ default: 'Male',
181
+ options: [
182
+ { name: 'Male', value: 'Male' },
183
+ { name: 'Female', value: 'Female' },
184
+ { name: 'Neutral', value: 'Neutral' },
185
+ ],
186
+ },
187
+ {
188
+ displayName: 'Style',
189
+ description: 'Voice style(s), comma-separated',
190
+ name: 'style',
191
+ type: 'string',
192
+ default: ``,
193
+ placeholder: 'Voice style(s), comma-separated',
194
+ },
195
+ ],
196
+ },
197
+ ];
198
+ async function preSendAudioFiles(requestOptions) {
199
+ const formData = new FormData();
200
+ const binaryData = this.getNodeParameter('audioFiles', '');
201
+ const fileBuffer = await this.helpers.getBinaryDataBuffer(binaryData);
202
+ const name = this.getNodeParameter('name');
203
+ const description = this.getNodeParameter('additionalFields.description', '');
204
+ const accent = this.getNodeParameter('additionalFields.accent', '');
205
+ const style = this.getNodeParameter('additionalFields.style', '');
206
+ const enhance = this.getNodeParameter('additionalFields.enhance', false);
207
+ const gender = this.getNodeParameter('additionalFields.gender', '');
208
+ formData.append('name', name);
209
+ formData.append('description', description);
210
+ formData.append('accent', accent);
211
+ formData.append('style', style);
212
+ formData.append('enhance', enhance);
213
+ formData.append('gender', gender);
214
+ formData.append('files', new Blob([fileBuffer]));
215
+ requestOptions.body = formData;
216
+ return requestOptions;
217
+ }
218
+ //# sourceMappingURL=voice.js.map