@neosapience/typecast-js 0.1.4 → 0.1.6
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 +1 -1
- package/README.md +221 -236
- package/lib/index.cjs +109 -41
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +154 -9
- package/lib/index.d.ts +154 -9
- package/lib/index.js +109 -37
- package/lib/index.js.map +1 -1
- package/package.json +6 -7
package/lib/index.cjs
CHANGED
|
@@ -1,13 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var axios = require('axios');
|
|
4
|
-
|
|
5
|
-
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
6
|
-
|
|
7
|
-
var axios__default = /*#__PURE__*/_interopDefault(axios);
|
|
8
|
-
|
|
9
|
-
// src/client.ts
|
|
10
|
-
|
|
11
3
|
// src/errors.ts
|
|
12
4
|
var TypecastAPIError = class _TypecastAPIError extends Error {
|
|
13
5
|
constructor(message, statusCode, response) {
|
|
@@ -54,58 +46,134 @@ var TypecastAPIError = class _TypecastAPIError extends Error {
|
|
|
54
46
|
// src/client.ts
|
|
55
47
|
var TypecastClient = class {
|
|
56
48
|
constructor(config = {}) {
|
|
57
|
-
|
|
49
|
+
const finalConfig = {
|
|
58
50
|
baseHost: process.env.TYPECAST_API_HOST || "https://api.typecast.ai",
|
|
59
51
|
apiKey: process.env.TYPECAST_API_KEY || "",
|
|
60
52
|
...config
|
|
61
53
|
};
|
|
62
|
-
this.
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
54
|
+
this.baseHost = finalConfig.baseHost;
|
|
55
|
+
this.headers = {
|
|
56
|
+
"X-API-KEY": finalConfig.apiKey,
|
|
57
|
+
"Content-Type": "application/json"
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Handle HTTP error responses
|
|
62
|
+
*/
|
|
63
|
+
async handleResponse(response) {
|
|
64
|
+
if (!response.ok) {
|
|
65
|
+
let errorData;
|
|
66
|
+
try {
|
|
67
|
+
errorData = await response.json();
|
|
68
|
+
} catch {
|
|
67
69
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
70
|
+
throw TypecastAPIError.fromResponse(
|
|
71
|
+
response.status,
|
|
72
|
+
response.statusText,
|
|
73
|
+
errorData
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
return response.json();
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Build URL with query parameters
|
|
80
|
+
*/
|
|
81
|
+
buildUrl(path, params) {
|
|
82
|
+
const url = new URL(path, this.baseHost);
|
|
83
|
+
if (params) {
|
|
84
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
85
|
+
if (value !== void 0 && value !== null) {
|
|
86
|
+
url.searchParams.append(key, String(value));
|
|
78
87
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
);
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
return url.toString();
|
|
82
91
|
}
|
|
92
|
+
/**
|
|
93
|
+
* Convert text to speech
|
|
94
|
+
* @param request - TTS request parameters including text, voice_id, model, and optional settings
|
|
95
|
+
* @returns TTSResponse containing audio data, duration, and format
|
|
96
|
+
*/
|
|
83
97
|
async textToSpeech(request) {
|
|
84
|
-
const response = await this.
|
|
85
|
-
|
|
98
|
+
const response = await fetch(this.buildUrl("/v1/text-to-speech"), {
|
|
99
|
+
method: "POST",
|
|
100
|
+
headers: this.headers,
|
|
101
|
+
body: JSON.stringify(request)
|
|
86
102
|
});
|
|
87
|
-
|
|
103
|
+
if (!response.ok) {
|
|
104
|
+
let errorData;
|
|
105
|
+
try {
|
|
106
|
+
errorData = await response.json();
|
|
107
|
+
} catch {
|
|
108
|
+
}
|
|
109
|
+
throw TypecastAPIError.fromResponse(
|
|
110
|
+
response.status,
|
|
111
|
+
response.statusText,
|
|
112
|
+
errorData
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
const contentType = response.headers.get("content-type") || "audio/wav";
|
|
88
116
|
const formatFromHeader = contentType.split("/")[1] || "wav";
|
|
89
117
|
const format = formatFromHeader === "mp3" ? "mp3" : "wav";
|
|
90
|
-
const durationHeader = response.headers
|
|
91
|
-
const duration =
|
|
118
|
+
const durationHeader = response.headers.get("x-audio-duration");
|
|
119
|
+
const duration = durationHeader ? Number(durationHeader) : 0;
|
|
120
|
+
const audioData = await response.arrayBuffer();
|
|
92
121
|
return {
|
|
93
|
-
audioData
|
|
122
|
+
audioData,
|
|
94
123
|
duration,
|
|
95
124
|
format
|
|
96
125
|
};
|
|
97
126
|
}
|
|
127
|
+
/**
|
|
128
|
+
* Get available voices (V1 API)
|
|
129
|
+
* @param model - Optional model filter (e.g., 'ssfm-v21', 'ssfm-v30')
|
|
130
|
+
* @returns List of available voices with their emotions
|
|
131
|
+
* @deprecated Use getVoicesV2() for enhanced metadata and filtering options
|
|
132
|
+
*/
|
|
98
133
|
async getVoices(model) {
|
|
99
|
-
const response = await
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
134
|
+
const response = await fetch(
|
|
135
|
+
this.buildUrl("/v1/voices", model ? { model } : void 0),
|
|
136
|
+
{ headers: this.headers }
|
|
137
|
+
);
|
|
138
|
+
return this.handleResponse(response);
|
|
103
139
|
}
|
|
140
|
+
/**
|
|
141
|
+
* Get voice by ID (V1 API)
|
|
142
|
+
* @param voiceId - The voice ID (e.g., 'tc_62a8975e695ad26f7fb514d1')
|
|
143
|
+
* @param model - Optional model filter
|
|
144
|
+
* @returns Voice information including available emotions
|
|
145
|
+
* @deprecated Use getVoicesV2() for enhanced metadata
|
|
146
|
+
*/
|
|
104
147
|
async getVoiceById(voiceId, model) {
|
|
105
|
-
const response = await
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
148
|
+
const response = await fetch(
|
|
149
|
+
this.buildUrl(`/v1/voices/${voiceId}`, model ? { model } : void 0),
|
|
150
|
+
{ headers: this.headers }
|
|
151
|
+
);
|
|
152
|
+
return this.handleResponse(response);
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Get voices with enhanced metadata (V2 API)
|
|
156
|
+
* Returns voices with model-grouped emotions and additional metadata
|
|
157
|
+
* @param filter - Optional filter options (model, gender, age, use_cases)
|
|
158
|
+
*/
|
|
159
|
+
async getVoicesV2(filter) {
|
|
160
|
+
const response = await fetch(
|
|
161
|
+
this.buildUrl("/v2/voices", filter),
|
|
162
|
+
{ headers: this.headers }
|
|
163
|
+
);
|
|
164
|
+
return this.handleResponse(response);
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Get a specific voice by ID with enhanced metadata (V2 API)
|
|
168
|
+
* @param voiceId - The voice ID (e.g., 'tc_62a8975e695ad26f7fb514d1')
|
|
169
|
+
* @returns Voice information with model-grouped emotions and metadata
|
|
170
|
+
*/
|
|
171
|
+
async getVoiceV2(voiceId) {
|
|
172
|
+
const response = await fetch(
|
|
173
|
+
this.buildUrl(`/v2/voices/${voiceId}`),
|
|
174
|
+
{ headers: this.headers }
|
|
175
|
+
);
|
|
176
|
+
return this.handleResponse(response);
|
|
109
177
|
}
|
|
110
178
|
};
|
|
111
179
|
|
package/lib/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/client.ts"],"names":["axios"],"mappings":"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","file":"index.cjs","sourcesContent":["import { ApiErrorResponse } from './types';\n\nexport class TypecastAPIError extends Error {\n public readonly statusCode: number;\n public readonly response?: ApiErrorResponse;\n\n constructor(message: string, statusCode: number, response?: ApiErrorResponse) {\n super(message);\n this.name = 'TypecastAPIError';\n this.statusCode = statusCode;\n this.response = response;\n\n // Maintains proper stack trace for where our error was thrown (only available on V8)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, TypecastAPIError);\n }\n }\n\n static fromResponse(statusCode: number, statusText: string, data?: ApiErrorResponse): TypecastAPIError {\n let message: string;\n\n switch (statusCode) {\n case 400:\n message = 'Bad Request - The request was invalid or cannot be served';\n break;\n case 401:\n message = 'Unauthorized - Invalid or missing API key';\n break;\n case 402:\n message = 'Payment Required - Insufficient credits to complete the request';\n break;\n case 404:\n message = 'Not Found - The requested resource does not exist';\n break;\n case 422:\n message = 'Validation Error - The request data failed validation';\n break;\n case 500:\n message = 'Internal Server Error - Something went wrong on the server';\n break;\n default:\n message = `API request failed with status ${statusCode}: ${statusText}`;\n }\n\n if (data?.detail) {\n const detailStr = typeof data.detail === 'string' \n ? data.detail \n : JSON.stringify(data.detail);\n message += ` - ${detailStr}`;\n }\n\n return new TypecastAPIError(message, statusCode, data);\n }\n}\n\n","import axios, { AxiosInstance, AxiosError } from 'axios';\nimport { ClientConfig, TTSRequest, TTSResponse, ApiErrorResponse } from './types';\nimport { VoicesResponse } from './types/Voices';\nimport { TypecastAPIError } from './errors';\n\nexport class TypecastClient {\n private client: AxiosInstance;\n private config: ClientConfig;\n\n constructor(config: Partial<ClientConfig> = {}) {\n this.config = {\n baseHost: process.env.TYPECAST_API_HOST || 'https://api.typecast.ai',\n apiKey: process.env.TYPECAST_API_KEY || '',\n ...config,\n };\n this.client = axios.create({\n baseURL: this.config.baseHost,\n headers: {\n 'X-API-KEY': this.config.apiKey,\n 'Content-Type': 'application/json',\n },\n });\n\n // Add response interceptor for error handling\n this.client.interceptors.response.use(\n (response) => response,\n (error: AxiosError<ApiErrorResponse>) => {\n if (error.response) {\n throw TypecastAPIError.fromResponse(\n error.response.status,\n error.response.statusText,\n error.response.data\n );\n }\n throw error;\n }\n );\n }\n\n async textToSpeech(request: TTSRequest): Promise<TTSResponse> {\n const response = await this.client.post<ArrayBuffer>('/v1/text-to-speech', request, {\n responseType: 'arraybuffer',\n });\n\n const contentType = String(response.headers['content-type'] || 'audio/wav');\n const formatFromHeader = contentType.split('/')[1] || 'wav';\n const format: 'wav' | 'mp3' = formatFromHeader === 'mp3' ? 'mp3' : 'wav';\n\n const durationHeader: unknown = response.headers['x-audio-duration'];\n const duration = typeof durationHeader === 'string' ? Number(durationHeader) : 0;\n\n return {\n audioData: response.data,\n duration,\n format,\n };\n }\n\n async getVoices(model?: string): Promise<VoicesResponse[]> {\n const response = await this.client.get<VoicesResponse[]>('/v1/voices', {\n params: model ? { model } : undefined,\n });\n return response.data;\n }\n\n async getVoiceById(voiceId: string, model?: string): Promise<VoicesResponse[]> {\n const response = await this.client.get<VoicesResponse[]>(`/v1/voices/${voiceId}`, {\n params: model ? { model } : undefined,\n });\n return response.data;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/client.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["import { ApiErrorResponse } from './types';\n\nexport class TypecastAPIError extends Error {\n public readonly statusCode: number;\n public readonly response?: ApiErrorResponse;\n\n constructor(message: string, statusCode: number, response?: ApiErrorResponse) {\n super(message);\n this.name = 'TypecastAPIError';\n this.statusCode = statusCode;\n this.response = response;\n\n // Maintains proper stack trace for where our error was thrown (only available on V8)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, TypecastAPIError);\n }\n }\n\n static fromResponse(statusCode: number, statusText: string, data?: ApiErrorResponse): TypecastAPIError {\n let message: string;\n\n switch (statusCode) {\n case 400:\n message = 'Bad Request - The request was invalid or cannot be served';\n break;\n case 401:\n message = 'Unauthorized - Invalid or missing API key';\n break;\n case 402:\n message = 'Payment Required - Insufficient credits to complete the request';\n break;\n case 404:\n message = 'Not Found - The requested resource does not exist';\n break;\n case 422:\n message = 'Validation Error - The request data failed validation';\n break;\n case 500:\n message = 'Internal Server Error - Something went wrong on the server';\n break;\n default:\n message = `API request failed with status ${statusCode}: ${statusText}`;\n }\n\n if (data?.detail) {\n const detailStr = typeof data.detail === 'string' \n ? data.detail \n : JSON.stringify(data.detail);\n message += ` - ${detailStr}`;\n }\n\n return new TypecastAPIError(message, statusCode, data);\n }\n}\n\n","import { ClientConfig, TTSRequest, TTSResponse, ApiErrorResponse } from './types';\nimport { VoicesResponse, VoiceV2Response, VoicesV2Filter } from './types/Voices';\nimport { TypecastAPIError } from './errors';\n\nexport class TypecastClient {\n private baseHost: string;\n private headers: Record<string, string>;\n\n constructor(config: Partial<ClientConfig> = {}) {\n const finalConfig: ClientConfig = {\n baseHost: process.env.TYPECAST_API_HOST || 'https://api.typecast.ai',\n apiKey: process.env.TYPECAST_API_KEY || '',\n ...config,\n };\n this.baseHost = finalConfig.baseHost;\n this.headers = {\n 'X-API-KEY': finalConfig.apiKey,\n 'Content-Type': 'application/json',\n };\n }\n\n /**\n * Handle HTTP error responses\n */\n private async handleResponse<T>(response: Response): Promise<T> {\n if (!response.ok) {\n let errorData: ApiErrorResponse | undefined;\n try {\n errorData = (await response.json()) as ApiErrorResponse;\n } catch {\n // Response body is not JSON\n }\n throw TypecastAPIError.fromResponse(\n response.status,\n response.statusText,\n errorData\n );\n }\n return response.json() as Promise<T>;\n }\n\n /**\n * Build URL with query parameters\n */\n private buildUrl(path: string, params?: Record<string, unknown>): string {\n const url = new URL(path, this.baseHost);\n if (params) {\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n url.searchParams.append(key, String(value));\n }\n });\n }\n return url.toString();\n }\n\n /**\n * Convert text to speech\n * @param request - TTS request parameters including text, voice_id, model, and optional settings\n * @returns TTSResponse containing audio data, duration, and format\n */\n async textToSpeech(request: TTSRequest): Promise<TTSResponse> {\n const response = await fetch(this.buildUrl('/v1/text-to-speech'), {\n method: 'POST',\n headers: this.headers,\n body: JSON.stringify(request),\n });\n\n if (!response.ok) {\n let errorData: ApiErrorResponse | undefined;\n try {\n errorData = (await response.json()) as ApiErrorResponse;\n } catch {\n // Response body is not JSON\n }\n throw TypecastAPIError.fromResponse(\n response.status,\n response.statusText,\n errorData\n );\n }\n\n const contentType = response.headers.get('content-type') || 'audio/wav';\n const formatFromHeader = contentType.split('/')[1] || 'wav';\n const format: 'wav' | 'mp3' = formatFromHeader === 'mp3' ? 'mp3' : 'wav';\n\n const durationHeader = response.headers.get('x-audio-duration');\n const duration = durationHeader ? Number(durationHeader) : 0;\n\n const audioData = await response.arrayBuffer();\n\n return {\n audioData,\n duration,\n format,\n };\n }\n\n /**\n * Get available voices (V1 API)\n * @param model - Optional model filter (e.g., 'ssfm-v21', 'ssfm-v30')\n * @returns List of available voices with their emotions\n * @deprecated Use getVoicesV2() for enhanced metadata and filtering options\n */\n async getVoices(model?: string): Promise<VoicesResponse[]> {\n const response = await fetch(\n this.buildUrl('/v1/voices', model ? { model } : undefined),\n { headers: this.headers }\n );\n return this.handleResponse<VoicesResponse[]>(response);\n }\n\n /**\n * Get voice by ID (V1 API)\n * @param voiceId - The voice ID (e.g., 'tc_62a8975e695ad26f7fb514d1')\n * @param model - Optional model filter\n * @returns Voice information including available emotions\n * @deprecated Use getVoicesV2() for enhanced metadata\n */\n async getVoiceById(voiceId: string, model?: string): Promise<VoicesResponse[]> {\n const response = await fetch(\n this.buildUrl(`/v1/voices/${voiceId}`, model ? { model } : undefined),\n { headers: this.headers }\n );\n return this.handleResponse<VoicesResponse[]>(response);\n }\n\n /**\n * Get voices with enhanced metadata (V2 API)\n * Returns voices with model-grouped emotions and additional metadata\n * @param filter - Optional filter options (model, gender, age, use_cases)\n */\n async getVoicesV2(filter?: VoicesV2Filter): Promise<VoiceV2Response[]> {\n const response = await fetch(\n this.buildUrl('/v2/voices', filter as Record<string, unknown>),\n { headers: this.headers }\n );\n return this.handleResponse<VoiceV2Response[]>(response);\n }\n\n /**\n * Get a specific voice by ID with enhanced metadata (V2 API)\n * @param voiceId - The voice ID (e.g., 'tc_62a8975e695ad26f7fb514d1')\n * @returns Voice information with model-grouped emotions and metadata\n */\n async getVoiceV2(voiceId: string): Promise<VoiceV2Response> {\n const response = await fetch(\n this.buildUrl(`/v2/voices/${voiceId}`),\n { headers: this.headers }\n );\n return this.handleResponse<VoiceV2Response>(response);\n }\n}\n"]}
|
package/lib/index.d.cts
CHANGED
|
@@ -25,18 +25,44 @@ interface ClientConfig {
|
|
|
25
25
|
apiKey: string;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
type TTSModel = 'ssfm-v21';
|
|
28
|
+
type TTSModel = 'ssfm-v21' | 'ssfm-v30';
|
|
29
29
|
/**
|
|
30
30
|
* Language code following ISO 639-3 standard
|
|
31
31
|
* Supported languages for text-to-speech conversion
|
|
32
|
+
*
|
|
33
|
+
* ssfm-v21: 27 languages
|
|
34
|
+
* ssfm-v30: 37 languages (includes all v21 languages plus additional ones)
|
|
32
35
|
*/
|
|
33
|
-
type LanguageCode = 'eng' | 'kor' | 'jpn' | 'spa' | 'deu' | 'fra' | 'ita' | 'pol' | 'nld' | 'rus' | 'ell' | 'tam' | 'tgl' | 'fin' | 'zho' | 'slk' | 'ara' | 'hrv' | 'ukr' | 'ind' | 'dan' | 'swe' | 'msa' | 'ces' | 'por' | 'bul' | 'ron';
|
|
36
|
+
type LanguageCode = 'eng' | 'kor' | 'jpn' | 'spa' | 'deu' | 'fra' | 'ita' | 'pol' | 'nld' | 'rus' | 'ell' | 'tam' | 'tgl' | 'fin' | 'zho' | 'slk' | 'ara' | 'hrv' | 'ukr' | 'ind' | 'dan' | 'swe' | 'msa' | 'ces' | 'por' | 'bul' | 'ron' | 'ben' | 'hin' | 'hun' | 'nan' | 'nor' | 'pan' | 'tha' | 'tur' | 'vie' | 'yue';
|
|
34
37
|
/**
|
|
35
|
-
* Emotion
|
|
38
|
+
* Emotion preset types
|
|
39
|
+
* ssfm-v21: normal, happy, sad, angry
|
|
40
|
+
* ssfm-v30: normal, happy, sad, angry, whisper, toneup, tonedown
|
|
41
|
+
*/
|
|
42
|
+
type EmotionPreset = 'normal' | 'happy' | 'sad' | 'angry' | 'whisper' | 'toneup' | 'tonedown';
|
|
43
|
+
/**
|
|
44
|
+
* Emotion and style settings for ssfm-v21 model
|
|
36
45
|
*/
|
|
37
46
|
interface Prompt {
|
|
38
47
|
/** Emotion preset for the voice (default: 'normal') */
|
|
39
|
-
emotion_preset?:
|
|
48
|
+
emotion_preset?: EmotionPreset;
|
|
49
|
+
/**
|
|
50
|
+
* Emotion intensity
|
|
51
|
+
* @min 0.0
|
|
52
|
+
* @max 2.0
|
|
53
|
+
* @default 1.0
|
|
54
|
+
*/
|
|
55
|
+
emotion_intensity?: number;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Preset-based emotion control for ssfm-v30 model
|
|
59
|
+
* Use this when you want to specify a specific emotion preset
|
|
60
|
+
*/
|
|
61
|
+
interface PresetPrompt {
|
|
62
|
+
/** Must be 'preset' for preset-based emotion control */
|
|
63
|
+
emotion_type: 'preset';
|
|
64
|
+
/** Emotion preset to apply (default: 'normal') */
|
|
65
|
+
emotion_preset?: EmotionPreset;
|
|
40
66
|
/**
|
|
41
67
|
* Emotion intensity
|
|
42
68
|
* @min 0.0
|
|
@@ -45,17 +71,44 @@ interface Prompt {
|
|
|
45
71
|
*/
|
|
46
72
|
emotion_intensity?: number;
|
|
47
73
|
}
|
|
74
|
+
/**
|
|
75
|
+
* Context-aware emotion inference for ssfm-v30 model
|
|
76
|
+
* The model analyzes surrounding context to infer appropriate emotion
|
|
77
|
+
*/
|
|
78
|
+
interface SmartPrompt {
|
|
79
|
+
/** Must be 'smart' for context-aware emotion inference */
|
|
80
|
+
emotion_type: 'smart';
|
|
81
|
+
/** Text that comes BEFORE the main text (max 2000 chars) */
|
|
82
|
+
previous_text?: string;
|
|
83
|
+
/** Text that comes AFTER the main text (max 2000 chars) */
|
|
84
|
+
next_text?: string;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Union type for all prompt types
|
|
88
|
+
* - Prompt: Basic emotion control (ssfm-v21 compatible)
|
|
89
|
+
* - PresetPrompt: Explicit preset emotion control (ssfm-v30)
|
|
90
|
+
* - SmartPrompt: Context-aware emotion inference (ssfm-v30)
|
|
91
|
+
*/
|
|
92
|
+
type TTSPrompt = Prompt | PresetPrompt | SmartPrompt;
|
|
48
93
|
/**
|
|
49
94
|
* Audio output settings for controlling the final audio characteristics
|
|
50
95
|
*/
|
|
51
96
|
interface Output {
|
|
52
97
|
/**
|
|
53
|
-
*
|
|
98
|
+
* Relative volume scaling of the output audio.
|
|
99
|
+
* Cannot be used simultaneously with target_lufs.
|
|
54
100
|
* @min 0
|
|
55
101
|
* @max 200
|
|
56
102
|
* @default 100
|
|
57
103
|
*/
|
|
58
104
|
volume?: number;
|
|
105
|
+
/**
|
|
106
|
+
* Target loudness in LUFS for absolute loudness normalization.
|
|
107
|
+
* Cannot be used simultaneously with volume.
|
|
108
|
+
* @min -70
|
|
109
|
+
* @max 0
|
|
110
|
+
*/
|
|
111
|
+
target_lufs?: number;
|
|
59
112
|
/**
|
|
60
113
|
* Audio pitch adjustment in semitones
|
|
61
114
|
* @min -12
|
|
@@ -92,7 +145,7 @@ interface TTSRequest {
|
|
|
92
145
|
/** Language code (ISO 639-3). If not provided, will be auto-detected based on text content */
|
|
93
146
|
language?: LanguageCode;
|
|
94
147
|
/** Emotion and style settings for the generated speech */
|
|
95
|
-
prompt?:
|
|
148
|
+
prompt?: TTSPrompt;
|
|
96
149
|
/** Audio output settings */
|
|
97
150
|
output?: Output;
|
|
98
151
|
/** Random seed for reproducible results (same seed + same parameters = same output) */
|
|
@@ -110,20 +163,112 @@ interface TTSResponse {
|
|
|
110
163
|
format: 'wav' | 'mp3';
|
|
111
164
|
}
|
|
112
165
|
|
|
166
|
+
/**
|
|
167
|
+
* V1 Voices response (deprecated, use VoiceV2Response instead)
|
|
168
|
+
*/
|
|
113
169
|
interface VoicesResponse {
|
|
114
170
|
voice_id: string;
|
|
115
171
|
voice_name: string;
|
|
116
172
|
model: TTSModel;
|
|
117
173
|
emotions: string[];
|
|
118
174
|
}
|
|
175
|
+
/**
|
|
176
|
+
* Gender classification for voices
|
|
177
|
+
*/
|
|
178
|
+
type GenderEnum = 'male' | 'female';
|
|
179
|
+
/**
|
|
180
|
+
* Age group classification for voices
|
|
181
|
+
*/
|
|
182
|
+
type AgeEnum = 'child' | 'teenager' | 'young_adult' | 'middle_age' | 'elder';
|
|
183
|
+
/**
|
|
184
|
+
* Use case categories for voices
|
|
185
|
+
*/
|
|
186
|
+
type UseCaseEnum = 'Announcer' | 'Anime' | 'Audiobook' | 'Conversational' | 'Documentary' | 'E-learning' | 'Rapper' | 'Game' | 'Tiktok/Reels' | 'News' | 'Podcast' | 'Voicemail' | 'Ads';
|
|
187
|
+
/**
|
|
188
|
+
* Model information with supported emotions
|
|
189
|
+
*/
|
|
190
|
+
interface ModelInfo {
|
|
191
|
+
/** TTS model version (e.g., ssfm-v21, ssfm-v30) */
|
|
192
|
+
version: TTSModel;
|
|
193
|
+
/** List of supported emotions for this model */
|
|
194
|
+
emotions: string[];
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* V2 Voice response with enhanced metadata
|
|
198
|
+
*/
|
|
199
|
+
interface VoiceV2Response {
|
|
200
|
+
/** Unique voice identifier */
|
|
201
|
+
voice_id: string;
|
|
202
|
+
/** Human-readable name of the voice */
|
|
203
|
+
voice_name: string;
|
|
204
|
+
/** List of supported TTS models with their available emotions */
|
|
205
|
+
models: ModelInfo[];
|
|
206
|
+
/** Voice gender classification */
|
|
207
|
+
gender?: GenderEnum | null;
|
|
208
|
+
/** Voice age group classification */
|
|
209
|
+
age?: AgeEnum | null;
|
|
210
|
+
/** List of use case categories this voice is suitable for */
|
|
211
|
+
use_cases?: string[];
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Filter options for V2 voices endpoint
|
|
215
|
+
*/
|
|
216
|
+
interface VoicesV2Filter {
|
|
217
|
+
/** Filter by TTS model */
|
|
218
|
+
model?: TTSModel;
|
|
219
|
+
/** Filter by gender */
|
|
220
|
+
gender?: GenderEnum;
|
|
221
|
+
/** Filter by age group */
|
|
222
|
+
age?: AgeEnum;
|
|
223
|
+
/** Filter by use case */
|
|
224
|
+
use_cases?: UseCaseEnum;
|
|
225
|
+
}
|
|
119
226
|
|
|
120
227
|
declare class TypecastClient {
|
|
121
|
-
private
|
|
122
|
-
private
|
|
228
|
+
private baseHost;
|
|
229
|
+
private headers;
|
|
123
230
|
constructor(config?: Partial<ClientConfig>);
|
|
231
|
+
/**
|
|
232
|
+
* Handle HTTP error responses
|
|
233
|
+
*/
|
|
234
|
+
private handleResponse;
|
|
235
|
+
/**
|
|
236
|
+
* Build URL with query parameters
|
|
237
|
+
*/
|
|
238
|
+
private buildUrl;
|
|
239
|
+
/**
|
|
240
|
+
* Convert text to speech
|
|
241
|
+
* @param request - TTS request parameters including text, voice_id, model, and optional settings
|
|
242
|
+
* @returns TTSResponse containing audio data, duration, and format
|
|
243
|
+
*/
|
|
124
244
|
textToSpeech(request: TTSRequest): Promise<TTSResponse>;
|
|
245
|
+
/**
|
|
246
|
+
* Get available voices (V1 API)
|
|
247
|
+
* @param model - Optional model filter (e.g., 'ssfm-v21', 'ssfm-v30')
|
|
248
|
+
* @returns List of available voices with their emotions
|
|
249
|
+
* @deprecated Use getVoicesV2() for enhanced metadata and filtering options
|
|
250
|
+
*/
|
|
125
251
|
getVoices(model?: string): Promise<VoicesResponse[]>;
|
|
252
|
+
/**
|
|
253
|
+
* Get voice by ID (V1 API)
|
|
254
|
+
* @param voiceId - The voice ID (e.g., 'tc_62a8975e695ad26f7fb514d1')
|
|
255
|
+
* @param model - Optional model filter
|
|
256
|
+
* @returns Voice information including available emotions
|
|
257
|
+
* @deprecated Use getVoicesV2() for enhanced metadata
|
|
258
|
+
*/
|
|
126
259
|
getVoiceById(voiceId: string, model?: string): Promise<VoicesResponse[]>;
|
|
260
|
+
/**
|
|
261
|
+
* Get voices with enhanced metadata (V2 API)
|
|
262
|
+
* Returns voices with model-grouped emotions and additional metadata
|
|
263
|
+
* @param filter - Optional filter options (model, gender, age, use_cases)
|
|
264
|
+
*/
|
|
265
|
+
getVoicesV2(filter?: VoicesV2Filter): Promise<VoiceV2Response[]>;
|
|
266
|
+
/**
|
|
267
|
+
* Get a specific voice by ID with enhanced metadata (V2 API)
|
|
268
|
+
* @param voiceId - The voice ID (e.g., 'tc_62a8975e695ad26f7fb514d1')
|
|
269
|
+
* @returns Voice information with model-grouped emotions and metadata
|
|
270
|
+
*/
|
|
271
|
+
getVoiceV2(voiceId: string): Promise<VoiceV2Response>;
|
|
127
272
|
}
|
|
128
273
|
|
|
129
274
|
declare class TypecastAPIError extends Error {
|
|
@@ -133,4 +278,4 @@ declare class TypecastAPIError extends Error {
|
|
|
133
278
|
static fromResponse(statusCode: number, statusText: string, data?: ApiErrorResponse): TypecastAPIError;
|
|
134
279
|
}
|
|
135
280
|
|
|
136
|
-
export { type ApiErrorResponse, type ClientConfig, type LanguageCode, type Output, type Prompt, type TTSModel, type TTSRequest, type TTSResponse, TypecastAPIError, TypecastClient, type ValidationError, type ValidationErrorResponse, type VoicesResponse };
|
|
281
|
+
export { type AgeEnum, type ApiErrorResponse, type ClientConfig, type EmotionPreset, type GenderEnum, type LanguageCode, type ModelInfo, type Output, type PresetPrompt, type Prompt, type SmartPrompt, type TTSModel, type TTSPrompt, type TTSRequest, type TTSResponse, TypecastAPIError, TypecastClient, type UseCaseEnum, type ValidationError, type ValidationErrorResponse, type VoiceV2Response, type VoicesResponse, type VoicesV2Filter };
|
package/lib/index.d.ts
CHANGED
|
@@ -25,18 +25,44 @@ interface ClientConfig {
|
|
|
25
25
|
apiKey: string;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
type TTSModel = 'ssfm-v21';
|
|
28
|
+
type TTSModel = 'ssfm-v21' | 'ssfm-v30';
|
|
29
29
|
/**
|
|
30
30
|
* Language code following ISO 639-3 standard
|
|
31
31
|
* Supported languages for text-to-speech conversion
|
|
32
|
+
*
|
|
33
|
+
* ssfm-v21: 27 languages
|
|
34
|
+
* ssfm-v30: 37 languages (includes all v21 languages plus additional ones)
|
|
32
35
|
*/
|
|
33
|
-
type LanguageCode = 'eng' | 'kor' | 'jpn' | 'spa' | 'deu' | 'fra' | 'ita' | 'pol' | 'nld' | 'rus' | 'ell' | 'tam' | 'tgl' | 'fin' | 'zho' | 'slk' | 'ara' | 'hrv' | 'ukr' | 'ind' | 'dan' | 'swe' | 'msa' | 'ces' | 'por' | 'bul' | 'ron';
|
|
36
|
+
type LanguageCode = 'eng' | 'kor' | 'jpn' | 'spa' | 'deu' | 'fra' | 'ita' | 'pol' | 'nld' | 'rus' | 'ell' | 'tam' | 'tgl' | 'fin' | 'zho' | 'slk' | 'ara' | 'hrv' | 'ukr' | 'ind' | 'dan' | 'swe' | 'msa' | 'ces' | 'por' | 'bul' | 'ron' | 'ben' | 'hin' | 'hun' | 'nan' | 'nor' | 'pan' | 'tha' | 'tur' | 'vie' | 'yue';
|
|
34
37
|
/**
|
|
35
|
-
* Emotion
|
|
38
|
+
* Emotion preset types
|
|
39
|
+
* ssfm-v21: normal, happy, sad, angry
|
|
40
|
+
* ssfm-v30: normal, happy, sad, angry, whisper, toneup, tonedown
|
|
41
|
+
*/
|
|
42
|
+
type EmotionPreset = 'normal' | 'happy' | 'sad' | 'angry' | 'whisper' | 'toneup' | 'tonedown';
|
|
43
|
+
/**
|
|
44
|
+
* Emotion and style settings for ssfm-v21 model
|
|
36
45
|
*/
|
|
37
46
|
interface Prompt {
|
|
38
47
|
/** Emotion preset for the voice (default: 'normal') */
|
|
39
|
-
emotion_preset?:
|
|
48
|
+
emotion_preset?: EmotionPreset;
|
|
49
|
+
/**
|
|
50
|
+
* Emotion intensity
|
|
51
|
+
* @min 0.0
|
|
52
|
+
* @max 2.0
|
|
53
|
+
* @default 1.0
|
|
54
|
+
*/
|
|
55
|
+
emotion_intensity?: number;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Preset-based emotion control for ssfm-v30 model
|
|
59
|
+
* Use this when you want to specify a specific emotion preset
|
|
60
|
+
*/
|
|
61
|
+
interface PresetPrompt {
|
|
62
|
+
/** Must be 'preset' for preset-based emotion control */
|
|
63
|
+
emotion_type: 'preset';
|
|
64
|
+
/** Emotion preset to apply (default: 'normal') */
|
|
65
|
+
emotion_preset?: EmotionPreset;
|
|
40
66
|
/**
|
|
41
67
|
* Emotion intensity
|
|
42
68
|
* @min 0.0
|
|
@@ -45,17 +71,44 @@ interface Prompt {
|
|
|
45
71
|
*/
|
|
46
72
|
emotion_intensity?: number;
|
|
47
73
|
}
|
|
74
|
+
/**
|
|
75
|
+
* Context-aware emotion inference for ssfm-v30 model
|
|
76
|
+
* The model analyzes surrounding context to infer appropriate emotion
|
|
77
|
+
*/
|
|
78
|
+
interface SmartPrompt {
|
|
79
|
+
/** Must be 'smart' for context-aware emotion inference */
|
|
80
|
+
emotion_type: 'smart';
|
|
81
|
+
/** Text that comes BEFORE the main text (max 2000 chars) */
|
|
82
|
+
previous_text?: string;
|
|
83
|
+
/** Text that comes AFTER the main text (max 2000 chars) */
|
|
84
|
+
next_text?: string;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Union type for all prompt types
|
|
88
|
+
* - Prompt: Basic emotion control (ssfm-v21 compatible)
|
|
89
|
+
* - PresetPrompt: Explicit preset emotion control (ssfm-v30)
|
|
90
|
+
* - SmartPrompt: Context-aware emotion inference (ssfm-v30)
|
|
91
|
+
*/
|
|
92
|
+
type TTSPrompt = Prompt | PresetPrompt | SmartPrompt;
|
|
48
93
|
/**
|
|
49
94
|
* Audio output settings for controlling the final audio characteristics
|
|
50
95
|
*/
|
|
51
96
|
interface Output {
|
|
52
97
|
/**
|
|
53
|
-
*
|
|
98
|
+
* Relative volume scaling of the output audio.
|
|
99
|
+
* Cannot be used simultaneously with target_lufs.
|
|
54
100
|
* @min 0
|
|
55
101
|
* @max 200
|
|
56
102
|
* @default 100
|
|
57
103
|
*/
|
|
58
104
|
volume?: number;
|
|
105
|
+
/**
|
|
106
|
+
* Target loudness in LUFS for absolute loudness normalization.
|
|
107
|
+
* Cannot be used simultaneously with volume.
|
|
108
|
+
* @min -70
|
|
109
|
+
* @max 0
|
|
110
|
+
*/
|
|
111
|
+
target_lufs?: number;
|
|
59
112
|
/**
|
|
60
113
|
* Audio pitch adjustment in semitones
|
|
61
114
|
* @min -12
|
|
@@ -92,7 +145,7 @@ interface TTSRequest {
|
|
|
92
145
|
/** Language code (ISO 639-3). If not provided, will be auto-detected based on text content */
|
|
93
146
|
language?: LanguageCode;
|
|
94
147
|
/** Emotion and style settings for the generated speech */
|
|
95
|
-
prompt?:
|
|
148
|
+
prompt?: TTSPrompt;
|
|
96
149
|
/** Audio output settings */
|
|
97
150
|
output?: Output;
|
|
98
151
|
/** Random seed for reproducible results (same seed + same parameters = same output) */
|
|
@@ -110,20 +163,112 @@ interface TTSResponse {
|
|
|
110
163
|
format: 'wav' | 'mp3';
|
|
111
164
|
}
|
|
112
165
|
|
|
166
|
+
/**
|
|
167
|
+
* V1 Voices response (deprecated, use VoiceV2Response instead)
|
|
168
|
+
*/
|
|
113
169
|
interface VoicesResponse {
|
|
114
170
|
voice_id: string;
|
|
115
171
|
voice_name: string;
|
|
116
172
|
model: TTSModel;
|
|
117
173
|
emotions: string[];
|
|
118
174
|
}
|
|
175
|
+
/**
|
|
176
|
+
* Gender classification for voices
|
|
177
|
+
*/
|
|
178
|
+
type GenderEnum = 'male' | 'female';
|
|
179
|
+
/**
|
|
180
|
+
* Age group classification for voices
|
|
181
|
+
*/
|
|
182
|
+
type AgeEnum = 'child' | 'teenager' | 'young_adult' | 'middle_age' | 'elder';
|
|
183
|
+
/**
|
|
184
|
+
* Use case categories for voices
|
|
185
|
+
*/
|
|
186
|
+
type UseCaseEnum = 'Announcer' | 'Anime' | 'Audiobook' | 'Conversational' | 'Documentary' | 'E-learning' | 'Rapper' | 'Game' | 'Tiktok/Reels' | 'News' | 'Podcast' | 'Voicemail' | 'Ads';
|
|
187
|
+
/**
|
|
188
|
+
* Model information with supported emotions
|
|
189
|
+
*/
|
|
190
|
+
interface ModelInfo {
|
|
191
|
+
/** TTS model version (e.g., ssfm-v21, ssfm-v30) */
|
|
192
|
+
version: TTSModel;
|
|
193
|
+
/** List of supported emotions for this model */
|
|
194
|
+
emotions: string[];
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* V2 Voice response with enhanced metadata
|
|
198
|
+
*/
|
|
199
|
+
interface VoiceV2Response {
|
|
200
|
+
/** Unique voice identifier */
|
|
201
|
+
voice_id: string;
|
|
202
|
+
/** Human-readable name of the voice */
|
|
203
|
+
voice_name: string;
|
|
204
|
+
/** List of supported TTS models with their available emotions */
|
|
205
|
+
models: ModelInfo[];
|
|
206
|
+
/** Voice gender classification */
|
|
207
|
+
gender?: GenderEnum | null;
|
|
208
|
+
/** Voice age group classification */
|
|
209
|
+
age?: AgeEnum | null;
|
|
210
|
+
/** List of use case categories this voice is suitable for */
|
|
211
|
+
use_cases?: string[];
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Filter options for V2 voices endpoint
|
|
215
|
+
*/
|
|
216
|
+
interface VoicesV2Filter {
|
|
217
|
+
/** Filter by TTS model */
|
|
218
|
+
model?: TTSModel;
|
|
219
|
+
/** Filter by gender */
|
|
220
|
+
gender?: GenderEnum;
|
|
221
|
+
/** Filter by age group */
|
|
222
|
+
age?: AgeEnum;
|
|
223
|
+
/** Filter by use case */
|
|
224
|
+
use_cases?: UseCaseEnum;
|
|
225
|
+
}
|
|
119
226
|
|
|
120
227
|
declare class TypecastClient {
|
|
121
|
-
private
|
|
122
|
-
private
|
|
228
|
+
private baseHost;
|
|
229
|
+
private headers;
|
|
123
230
|
constructor(config?: Partial<ClientConfig>);
|
|
231
|
+
/**
|
|
232
|
+
* Handle HTTP error responses
|
|
233
|
+
*/
|
|
234
|
+
private handleResponse;
|
|
235
|
+
/**
|
|
236
|
+
* Build URL with query parameters
|
|
237
|
+
*/
|
|
238
|
+
private buildUrl;
|
|
239
|
+
/**
|
|
240
|
+
* Convert text to speech
|
|
241
|
+
* @param request - TTS request parameters including text, voice_id, model, and optional settings
|
|
242
|
+
* @returns TTSResponse containing audio data, duration, and format
|
|
243
|
+
*/
|
|
124
244
|
textToSpeech(request: TTSRequest): Promise<TTSResponse>;
|
|
245
|
+
/**
|
|
246
|
+
* Get available voices (V1 API)
|
|
247
|
+
* @param model - Optional model filter (e.g., 'ssfm-v21', 'ssfm-v30')
|
|
248
|
+
* @returns List of available voices with their emotions
|
|
249
|
+
* @deprecated Use getVoicesV2() for enhanced metadata and filtering options
|
|
250
|
+
*/
|
|
125
251
|
getVoices(model?: string): Promise<VoicesResponse[]>;
|
|
252
|
+
/**
|
|
253
|
+
* Get voice by ID (V1 API)
|
|
254
|
+
* @param voiceId - The voice ID (e.g., 'tc_62a8975e695ad26f7fb514d1')
|
|
255
|
+
* @param model - Optional model filter
|
|
256
|
+
* @returns Voice information including available emotions
|
|
257
|
+
* @deprecated Use getVoicesV2() for enhanced metadata
|
|
258
|
+
*/
|
|
126
259
|
getVoiceById(voiceId: string, model?: string): Promise<VoicesResponse[]>;
|
|
260
|
+
/**
|
|
261
|
+
* Get voices with enhanced metadata (V2 API)
|
|
262
|
+
* Returns voices with model-grouped emotions and additional metadata
|
|
263
|
+
* @param filter - Optional filter options (model, gender, age, use_cases)
|
|
264
|
+
*/
|
|
265
|
+
getVoicesV2(filter?: VoicesV2Filter): Promise<VoiceV2Response[]>;
|
|
266
|
+
/**
|
|
267
|
+
* Get a specific voice by ID with enhanced metadata (V2 API)
|
|
268
|
+
* @param voiceId - The voice ID (e.g., 'tc_62a8975e695ad26f7fb514d1')
|
|
269
|
+
* @returns Voice information with model-grouped emotions and metadata
|
|
270
|
+
*/
|
|
271
|
+
getVoiceV2(voiceId: string): Promise<VoiceV2Response>;
|
|
127
272
|
}
|
|
128
273
|
|
|
129
274
|
declare class TypecastAPIError extends Error {
|
|
@@ -133,4 +278,4 @@ declare class TypecastAPIError extends Error {
|
|
|
133
278
|
static fromResponse(statusCode: number, statusText: string, data?: ApiErrorResponse): TypecastAPIError;
|
|
134
279
|
}
|
|
135
280
|
|
|
136
|
-
export { type ApiErrorResponse, type ClientConfig, type LanguageCode, type Output, type Prompt, type TTSModel, type TTSRequest, type TTSResponse, TypecastAPIError, TypecastClient, type ValidationError, type ValidationErrorResponse, type VoicesResponse };
|
|
281
|
+
export { type AgeEnum, type ApiErrorResponse, type ClientConfig, type EmotionPreset, type GenderEnum, type LanguageCode, type ModelInfo, type Output, type PresetPrompt, type Prompt, type SmartPrompt, type TTSModel, type TTSPrompt, type TTSRequest, type TTSResponse, TypecastAPIError, TypecastClient, type UseCaseEnum, type ValidationError, type ValidationErrorResponse, type VoiceV2Response, type VoicesResponse, type VoicesV2Filter };
|