@neosapience/n8n-nodes-typecast 1.0.2 → 1.0.4
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/README.md +7 -8
- package/credentials/TypecastApi.credentials.ts +37 -36
- package/dist/credentials/TypecastApi.credentials.js.map +1 -1
- package/dist/nodes/Typecast/Typecast.node.d.ts +6 -1
- package/dist/nodes/Typecast/Typecast.node.js +139 -19
- package/dist/nodes/Typecast/Typecast.node.js.map +1 -1
- package/dist/nodes/Typecast/resources/speech/index.js +367 -55
- package/dist/nodes/Typecast/resources/speech/index.js.map +1 -1
- package/dist/nodes/Typecast/resources/voice/index.js +152 -48
- package/dist/nodes/Typecast/resources/voice/index.js.map +1 -1
- package/dist/nodes/Typecast/shared/transport.d.ts +2 -2
- package/dist/nodes/Typecast/shared/transport.js +20 -6
- package/dist/nodes/Typecast/shared/transport.js.map +1 -1
- package/dist/package.json +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/nodes/Typecast/Typecast.node.ts +358 -199
- package/nodes/Typecast/resources/speech/index.ts +563 -228
- package/nodes/Typecast/resources/voice/index.ts +189 -88
- package/nodes/Typecast/shared/transport.ts +72 -44
- package/package.json +1 -1
|
@@ -1,95 +1,196 @@
|
|
|
1
1
|
import type { INodeProperties } from 'n8n-workflow';
|
|
2
2
|
|
|
3
3
|
const showOnlyForVoice = {
|
|
4
|
-
|
|
4
|
+
resource: ['voice'],
|
|
5
5
|
};
|
|
6
6
|
|
|
7
7
|
export const voiceDescription: INodeProperties[] = [
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
8
|
+
{
|
|
9
|
+
displayName: 'Operation',
|
|
10
|
+
name: 'operation',
|
|
11
|
+
type: 'options',
|
|
12
|
+
noDataExpression: true,
|
|
13
|
+
displayOptions: {
|
|
14
|
+
show: showOnlyForVoice,
|
|
15
|
+
},
|
|
16
|
+
options: [
|
|
17
|
+
{
|
|
18
|
+
name: 'Get All Voices',
|
|
19
|
+
value: 'getMany',
|
|
20
|
+
description: 'Get all available voice models',
|
|
21
|
+
action: 'Get all voices',
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
default: 'getMany',
|
|
25
|
+
},
|
|
26
|
+
// ----------------------------------
|
|
27
|
+
// voice:getMany
|
|
28
|
+
// ----------------------------------
|
|
29
|
+
{
|
|
30
|
+
displayName: 'Filters',
|
|
31
|
+
name: 'filters',
|
|
32
|
+
type: 'collection',
|
|
33
|
+
placeholder: 'Add Filter',
|
|
34
|
+
default: {},
|
|
35
|
+
displayOptions: {
|
|
36
|
+
show: {
|
|
37
|
+
resource: ['voice'],
|
|
38
|
+
operation: ['getMany'],
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
options: [
|
|
42
|
+
{
|
|
43
|
+
displayName: 'Model',
|
|
44
|
+
name: 'model',
|
|
45
|
+
type: 'options',
|
|
46
|
+
options: [
|
|
47
|
+
{
|
|
48
|
+
name: 'All',
|
|
49
|
+
value: '',
|
|
50
|
+
description: 'List all available voices for all models',
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: 'SSFM-V30 (Latest)',
|
|
54
|
+
value: 'ssfm-v30',
|
|
55
|
+
description: 'Latest model with improved prosody and additional emotion presets',
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
name: 'SSFM-V21',
|
|
59
|
+
value: 'ssfm-v21',
|
|
60
|
+
description: 'Stable production model with proven reliability',
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
default: '',
|
|
64
|
+
description: 'Filter voices by TTS model version',
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
displayName: 'Gender',
|
|
68
|
+
name: 'gender',
|
|
69
|
+
type: 'options',
|
|
70
|
+
options: [
|
|
71
|
+
{
|
|
72
|
+
name: 'Female',
|
|
73
|
+
value: 'female',
|
|
74
|
+
description: 'Female voice',
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
name: 'Male',
|
|
78
|
+
value: 'male',
|
|
79
|
+
description: 'Male voice',
|
|
80
|
+
},
|
|
81
|
+
],
|
|
82
|
+
default: 'female',
|
|
83
|
+
description: 'Filter voices by gender',
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
displayName: 'Age',
|
|
87
|
+
name: 'age',
|
|
88
|
+
type: 'options',
|
|
89
|
+
options: [
|
|
90
|
+
{
|
|
91
|
+
name: 'Child',
|
|
92
|
+
value: 'child',
|
|
93
|
+
description: 'Child voice (under 12 years old)',
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
name: 'Elder',
|
|
97
|
+
value: 'elder',
|
|
98
|
+
description: 'Elder voice (over 60 years old)',
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
name: 'Middle Age',
|
|
102
|
+
value: 'middle_age',
|
|
103
|
+
description: 'Middle-aged voice (36-60 years old)',
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
name: 'Teenager',
|
|
107
|
+
value: 'teenager',
|
|
108
|
+
description: 'Teenage voice (13-19 years old)',
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
name: 'Young Adult',
|
|
112
|
+
value: 'young_adult',
|
|
113
|
+
description: 'Young adult voice (20-35 years old)',
|
|
114
|
+
},
|
|
115
|
+
],
|
|
116
|
+
default: 'child',
|
|
117
|
+
description: 'Filter voices by age group',
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
displayName: 'Use Cases',
|
|
121
|
+
name: 'use_cases',
|
|
122
|
+
type: 'options',
|
|
123
|
+
options: [
|
|
124
|
+
{
|
|
125
|
+
name: 'Ads',
|
|
126
|
+
value: 'Ads',
|
|
127
|
+
description: 'Advertising and promotional content',
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
name: 'Anime',
|
|
131
|
+
value: 'Anime',
|
|
132
|
+
description: 'Animation and character voices',
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
name: 'Announcer',
|
|
136
|
+
value: 'Announcer',
|
|
137
|
+
description: 'Public announcements and presentations',
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
name: 'Audiobook',
|
|
141
|
+
value: 'Audiobook',
|
|
142
|
+
description: 'Long-form narration and storytelling',
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
name: 'Conversational',
|
|
146
|
+
value: 'Conversational',
|
|
147
|
+
description: 'Chatbots and conversational AI',
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
name: 'Documentary',
|
|
151
|
+
value: 'Documentary',
|
|
152
|
+
description: 'Documentary narration and commentary',
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
name: 'E-Learning',
|
|
156
|
+
value: 'E-learning',
|
|
157
|
+
description: 'Educational content and tutorials',
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
name: 'Game',
|
|
161
|
+
value: 'Game',
|
|
162
|
+
description: 'Video game characters and narration',
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
name: 'News',
|
|
166
|
+
value: 'News',
|
|
167
|
+
description: 'News broadcasting',
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
name: 'Podcast',
|
|
171
|
+
value: 'Podcast',
|
|
172
|
+
description: 'Broadcasting and podcast production',
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
name: 'Rapper',
|
|
176
|
+
value: 'Rapper',
|
|
177
|
+
description: 'Rap and music performance',
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
name: 'TikTok/Reels',
|
|
181
|
+
value: 'Tiktok/Reels',
|
|
182
|
+
description: 'Short-form social media content',
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
name: 'Voicemail',
|
|
186
|
+
value: 'Voicemail',
|
|
187
|
+
description: 'IVR systems and voice assistants',
|
|
188
|
+
},
|
|
189
|
+
],
|
|
190
|
+
default: 'Announcer',
|
|
191
|
+
description: 'Filter voices by use case category',
|
|
192
|
+
},
|
|
193
|
+
],
|
|
194
|
+
description: 'Filter voices by model, gender, age, or use cases',
|
|
195
|
+
},
|
|
95
196
|
];
|
|
@@ -1,54 +1,82 @@
|
|
|
1
1
|
import type {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
IExecuteFunctions,
|
|
3
|
+
ILoadOptionsFunctions,
|
|
4
|
+
IHookFunctions,
|
|
5
|
+
IHttpRequestMethods,
|
|
6
|
+
IDataObject,
|
|
7
|
+
IHttpRequestOptions,
|
|
8
8
|
} from 'n8n-workflow';
|
|
9
9
|
|
|
10
10
|
export async function typecastApiRequest(
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
this: IExecuteFunctions | ILoadOptionsFunctions | IHookFunctions,
|
|
12
|
+
method: IHttpRequestMethods,
|
|
13
|
+
endpoint: string,
|
|
14
|
+
body: IDataObject = {},
|
|
15
|
+
qs: IDataObject = {},
|
|
16
|
+
version: string = 'v2',
|
|
16
17
|
) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
18
|
+
const options: IHttpRequestOptions = {
|
|
19
|
+
method,
|
|
20
|
+
body,
|
|
21
|
+
qs,
|
|
22
|
+
url: `https://api.typecast.ai/${version}${endpoint}`,
|
|
23
|
+
json: true,
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
try {
|
|
27
|
+
return await this.helpers.httpRequestWithAuthentication.call(this, 'typecastApi', options);
|
|
28
|
+
} catch (error) {
|
|
29
|
+
const errorData = error as {
|
|
30
|
+
message?: string;
|
|
31
|
+
httpCode?: number;
|
|
32
|
+
errorResponse?: { error_code?: string };
|
|
33
|
+
error_code?: string;
|
|
34
|
+
};
|
|
35
|
+
const errorMessage = errorData.message || 'Unknown error';
|
|
36
|
+
const statusCode = errorData.httpCode;
|
|
37
|
+
const errorCode = errorData.errorResponse?.error_code || errorData.error_code;
|
|
38
|
+
|
|
39
|
+
const statusDetails = statusCode ? `[${statusCode}] ` : '';
|
|
40
|
+
const errorCodeDetails = errorCode ? `(Error Code: ${errorCode}) ` : '';
|
|
41
|
+
|
|
42
|
+
throw new Error(`Typecast API request failed: ${statusDetails}${errorCodeDetails}${errorMessage}`);
|
|
43
|
+
}
|
|
30
44
|
}
|
|
31
45
|
|
|
32
46
|
export async function typecastApiRequestBinary(
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
47
|
+
this: IExecuteFunctions | ILoadOptionsFunctions | IHookFunctions,
|
|
48
|
+
method: IHttpRequestMethods,
|
|
49
|
+
endpoint: string,
|
|
50
|
+
body: IDataObject = {},
|
|
51
|
+
qs: IDataObject = {},
|
|
52
|
+
version: string = 'v1',
|
|
53
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
39
54
|
): Promise<any> {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
55
|
+
const options: IHttpRequestOptions = {
|
|
56
|
+
method,
|
|
57
|
+
body,
|
|
58
|
+
qs,
|
|
59
|
+
url: `https://api.typecast.ai/${version}${endpoint}`,
|
|
60
|
+
json: true,
|
|
61
|
+
encoding: 'arraybuffer',
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
try {
|
|
65
|
+
return await this.helpers.httpRequestWithAuthentication.call(this, 'typecastApi', options);
|
|
66
|
+
} catch (error) {
|
|
67
|
+
const errorData = error as {
|
|
68
|
+
message?: string;
|
|
69
|
+
httpCode?: number;
|
|
70
|
+
errorResponse?: { error_code?: string };
|
|
71
|
+
error_code?: string;
|
|
72
|
+
};
|
|
73
|
+
const errorMessage = errorData.message || 'Unknown error';
|
|
74
|
+
const statusCode = errorData.httpCode;
|
|
75
|
+
const errorCode = errorData.errorResponse?.error_code || errorData.error_code;
|
|
76
|
+
|
|
77
|
+
const statusDetails = statusCode ? `[${statusCode}] ` : '';
|
|
78
|
+
const errorCodeDetails = errorCode ? `(Error Code: ${errorCode}) ` : '';
|
|
79
|
+
|
|
80
|
+
throw new Error(`Typecast API binary request failed: ${statusDetails}${errorCodeDetails}${errorMessage}`);
|
|
81
|
+
}
|
|
54
82
|
}
|