@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 CHANGED
@@ -175,7 +175,7 @@
175
175
 
176
176
  END OF TERMS AND CONDITIONS
177
177
 
178
- Copyright 2025 Neosapience Inc.
178
+ Copyright 2025 Neosapience, Inc.
179
179
 
180
180
  Licensed under the Apache License, Version 2.0 (the "License");
181
181
  you may not use this file except in compliance with the License.
package/README.md CHANGED
@@ -1,15 +1,38 @@
1
- # Typecast Node.js SDK
1
+ <div align="center">
2
2
 
3
- [![npm version](https://img.shields.io/npm/v/@neosapience/typecast-js.svg)](https://www.npmjs.com/package/@neosapience/typecast-js)
4
- [![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE)
5
- [![TypeScript](https://img.shields.io/badge/TypeScript-5.7-blue.svg)](https://www.typescriptlang.org/)
6
- [![Node.js](https://img.shields.io/badge/Node.js-%3E%3D16.0.0-green.svg)](https://nodejs.org/)
3
+ # Typecast SDK for JavaScript
7
4
 
8
- The official Node.js library for the [Typecast API](https://typecast.ai). Convert text to lifelike speech using AI-powered voices.
5
+ **The official JavaScript/TypeScript SDK for the Typecast Text-to-Speech API**
9
6
 
10
- Works with both JavaScript and TypeScript. Full TypeScript types included.
7
+ Convert text to lifelike speech using AI-powered voices
11
8
 
12
- ESM & CommonJS supported. This SDK targets Node.js environments only (browser usage is not supported).
9
+ [![npm version](https://img.shields.io/npm/v/@neosapience/typecast-js.svg?style=flat-square)](https://www.npmjs.com/package/@neosapience/typecast-js)
10
+ [![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg?style=flat-square)](LICENSE)
11
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.7-3178c6.svg?style=flat-square&logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
12
+ [![Node.js](https://img.shields.io/badge/Node.js-%3E%3D16.0.0-339933.svg?style=flat-square&logo=node.js&logoColor=white)](https://nodejs.org/)
13
+
14
+ [Documentation](https://typecast.ai/docs) | [API Reference](https://typecast.ai/docs/api-reference) | [Get API Key](https://typecast.ai/developers/api/api-key)
15
+
16
+ </div>
17
+
18
+ ---
19
+
20
+ ## Table of Contents
21
+
22
+ - [Installation](#installation)
23
+ - [Quick Start](#quick-start)
24
+ - [Features](#features)
25
+ - [Usage](#usage)
26
+ - [Configuration](#configuration)
27
+ - [Text to Speech](#text-to-speech)
28
+ - [Voice Discovery](#voice-discovery)
29
+ - [Emotion Control](#emotion-control)
30
+ - [Supported Languages](#supported-languages)
31
+ - [Error Handling](#error-handling)
32
+ - [TypeScript Support](#typescript-support)
33
+ - [License](#license)
34
+
35
+ ---
13
36
 
14
37
  ## Installation
15
38
 
@@ -17,29 +40,47 @@ ESM & CommonJS supported. This SDK targets Node.js environments only (browser us
17
40
  npm install @neosapience/typecast-js
18
41
  ```
19
42
 
20
- ## Quick Start
43
+ <details>
44
+ <summary><strong>Node.js 16/17 Users</strong></summary>
21
45
 
22
- ### TypeScript (ESM)
46
+ This SDK uses the native `fetch` API. Node.js 18+ has built-in fetch support, but if you're using Node.js 16 or 17, you need to install a fetch polyfill:
47
+
48
+ ```bash
49
+ npm install isomorphic-fetch
50
+ ```
51
+
52
+ Then import it once at your application's entry point:
53
+
54
+ ```javascript
55
+ import 'isomorphic-fetch'; // ESM
56
+ // or
57
+ require('isomorphic-fetch'); // CommonJS
58
+ ```
59
+
60
+ </details>
61
+
62
+ ---
63
+
64
+ ## Quick Start
23
65
 
24
66
  ```typescript
25
67
  import { TypecastClient } from '@neosapience/typecast-js';
26
68
  import fs from 'fs';
27
69
 
28
- async function main() {
29
- const client = new TypecastClient({ apiKey: 'YOUR_API_KEY' });
30
- const audio = await client.textToSpeech({
31
- text: "Hello there! I'm your friendly text-to-speech agent.",
32
- model: "ssfm-v21",
33
- voice_id: "tc_62a8975e695ad26f7fb514d1"
34
- });
35
- await fs.promises.writeFile(`output.${audio.format}`, Buffer.from(audio.audioData));
36
- console.log(`Audio saved! Duration: ${audio.duration}s, Format: ${audio.format}`);
37
- }
70
+ const client = new TypecastClient({ apiKey: 'YOUR_API_KEY' });
38
71
 
39
- main();
72
+ const audio = await client.textToSpeech({
73
+ text: "Hello! I'm your friendly text-to-speech assistant.",
74
+ model: "ssfm-v30",
75
+ voice_id: "tc_672c5f5ce59fac2a48faeaee"
76
+ });
77
+
78
+ await fs.promises.writeFile(`output.${audio.format}`, Buffer.from(audio.audioData));
79
+ console.log(`Saved: output.${audio.format} (${audio.duration}s)`);
40
80
  ```
41
81
 
42
- ### JavaScript (CommonJS)
82
+ <details>
83
+ <summary><strong>CommonJS Example</strong></summary>
43
84
 
44
85
  ```javascript
45
86
  const { TypecastClient } = require('@neosapience/typecast-js');
@@ -48,296 +89,240 @@ const fs = require('fs');
48
89
  async function main() {
49
90
  const client = new TypecastClient({ apiKey: 'YOUR_API_KEY' });
50
91
  const audio = await client.textToSpeech({
51
- text: "Hello there! I'm your friendly text-to-speech agent.",
52
- model: "ssfm-v21",
53
- voice_id: "tc_62a8975e695ad26f7fb514d1"
92
+ text: "Hello! I'm your friendly text-to-speech assistant.",
93
+ model: "ssfm-v30",
94
+ voice_id: "tc_672c5f5ce59fac2a48faeaee"
54
95
  });
55
96
  await fs.promises.writeFile(`output.${audio.format}`, Buffer.from(audio.audioData));
56
- console.log(`Audio saved! Duration: ${audio.duration}s, Format: ${audio.format}`);
57
97
  }
58
98
 
59
99
  main();
60
100
  ```
61
101
 
62
- ## Configuration
102
+ </details>
63
103
 
64
- The client can be configured using environment variables or constructor options:
104
+ ---
65
105
 
66
- ```typescript
67
- // Using environment variables
68
- // export TYPECAST_API_KEY=your_api_key
69
- const client = new TypecastClient({
70
- apiKey: process.env.TYPECAST_API_KEY!
71
- });
106
+ ## Features
72
107
 
73
- // Or pass API key directly
74
- const client = new TypecastClient({
75
- apiKey: 'your_api_key'
76
- });
77
- ```
108
+ | Feature | Description |
109
+ |---------|-------------|
110
+ | **Multiple Models** | Support for `ssfm-v21` and `ssfm-v30` AI voice models |
111
+ | **37 Languages** | English, Korean, Japanese, Chinese, Spanish, and 32 more |
112
+ | **Emotion Control** | Preset emotions or smart context-aware inference |
113
+ | **Audio Customization** | Volume, pitch, tempo, and format (WAV/MP3) |
114
+ | **Voice Discovery** | Filter voices by model, gender, age, and use cases |
115
+ | **TypeScript** | Full type definitions included |
116
+ | **Zero Dependencies** | Uses native `fetch` API |
78
117
 
79
- ## API Reference
118
+ ---
80
119
 
81
- ### Text-to-Speech
120
+ ## Usage
82
121
 
83
- Generate speech from text using a specified voice model.
122
+ ### Configuration
84
123
 
85
124
  ```typescript
86
- const response = await client.textToSpeech({
87
- text: "Hello. How are you?",
88
- voice_id: "tc_62a8975e695ad26f7fb514d1",
89
- model: "ssfm-v21",
90
- language: "eng", // optional, auto-detected if not provided
91
- prompt: {
92
- emotion_preset: "happy",
93
- emotion_intensity: 1.5
94
- },
95
- output: {
96
- audio_format: "mp3",
97
- volume: 100,
98
- audio_pitch: 0,
99
- audio_tempo: 1.0
100
- },
101
- seed: 42 // for reproducible results
102
- });
103
- ```
104
-
105
- #### Parameters
125
+ import { TypecastClient } from '@neosapience/typecast-js';
106
126
 
107
- - **text** (required): Text to convert to speech (max 5000 characters)
108
- - **voice_id** (required): Voice ID (format: `tc_*` for Typecast voices, `uc_*` for user-created voices)
109
- - **model** (required): Voice model (`ssfm-v21`)
110
- - **language** (optional): Language code (see supported languages below)
111
- - **prompt** (optional): Emotion and style settings
112
- - `emotion_preset`: Emotion type for the voice. Available options include `'happy' | 'sad' | 'normal' | 'angry' | 'tonemid' | 'toneup'` (default: `'normal'`). Note: Each voice supports different emotions - check the voice's `emotions` array using `getVoices()` to see which emotions are supported.
113
- - `emotion_intensity`: 0.0 - 2.0 (default: 1.0)
114
- - **output** (optional): Audio output settings
115
- - `audio_format`: `'wav' | 'mp3'` (default: `'wav'`)
116
- - `volume`: 0 - 200 (default: 100)
117
- - `audio_pitch`: -12 - 12 semitones (default: 0)
118
- - `audio_tempo`: 0.5 - 2.0 (default: 1.0)
119
- - **seed** (optional): Random seed for reproducible results
127
+ // Using environment variable (recommended)
128
+ // export TYPECAST_API_KEY="your-api-key"
129
+ const client = new TypecastClient();
120
130
 
121
- ### Get Voices
131
+ // Or pass directly
132
+ const client = new TypecastClient({
133
+ apiKey: 'your-api-key',
134
+ baseHost: 'https://api.typecast.ai' // optional
135
+ });
136
+ ```
122
137
 
123
- List all available voices, optionally filtered by model.
138
+ ### Text to Speech
124
139
 
125
- **Signature:** `getVoices(model?: string): Promise<Voice[]>`
140
+ #### Basic Usage
126
141
 
127
142
  ```typescript
128
- // Get all voices
129
- const voices = await client.getVoices();
130
-
131
- // Get voices for specific model
132
- const voices = await client.getVoices("ssfm-v21");
133
-
134
- voices.forEach(voice => {
135
- console.log(`${voice.voice_name} (${voice.voice_id})`);
136
- console.log(`Emotions: ${voice.emotions.join(', ')}`);
143
+ const audio = await client.textToSpeech({
144
+ text: "Hello, world!",
145
+ voice_id: "tc_672c5f5ce59fac2a48faeaee",
146
+ model: "ssfm-v30"
137
147
  });
138
148
  ```
139
149
 
140
- For detailed Voice object fields, see the [API Reference](https://typecast.ai/docs/api-reference).
141
-
142
- ### Get Voice by ID
143
-
144
- Get information about a specific voice.
145
-
146
- **Signature:** `getVoiceById(voiceId: string, model?: string): Promise<Voice[]>`
150
+ #### With Audio Options
147
151
 
148
152
  ```typescript
149
- const voiceInfo = await client.getVoiceById("tc_62a8975e695ad26f7fb514d1");
150
- console.log(`Voice: ${voiceInfo[0].voice_name}`);
151
- console.log(`Model: ${voiceInfo[0].model}`);
152
- console.log(`Supported emotions: ${voiceInfo[0].emotions.join(', ')}`);
153
+ const audio = await client.textToSpeech({
154
+ text: "Hello, world!",
155
+ voice_id: "tc_672c5f5ce59fac2a48faeaee",
156
+ model: "ssfm-v30",
157
+ language: "eng",
158
+ output: {
159
+ volume: 120, // 0-200 (default: 100)
160
+ audio_pitch: 2, // -12 to +12 semitones
161
+ audio_tempo: 1.2, // 0.5x to 2.0x
162
+ audio_format: "mp3" // "wav" or "mp3"
163
+ },
164
+ seed: 42 // for reproducible results
165
+ });
153
166
  ```
154
167
 
155
- **Voice Object Fields:**
156
- - `voice_id`: Unique identifier (format: `tc_*` or `uc_*`)
157
- - `voice_name`: Human-readable name of the voice
158
- - `model`: Voice model type (`ssfm-v21`)
159
- - `emotions`: Array of supported emotion presets for this voice
160
-
161
- ## Supported Languages
162
-
163
- The SDK supports 27 languages with automatic language detection:
164
-
165
- | Code | Language | Code | Language | Code | Language |
166
- |------|------------|------|------------|------|------------|
167
- | eng | English | jpn | Japanese | ukr | Ukrainian |
168
- | kor | Korean | ell | Greek | ind | Indonesian |
169
- | spa | Spanish | tam | Tamil | dan | Danish |
170
- | deu | German | tgl | Tagalog | swe | Swedish |
171
- | fra | French | fin | Finnish | msa | Malay |
172
- | ita | Italian | zho | Chinese | ces | Czech |
173
- | pol | Polish | slk | Slovak | por | Portuguese |
174
- | nld | Dutch | ara | Arabic | bul | Bulgarian |
175
- | rus | Russian | hrv | Croatian | ron | Romanian |
176
-
177
- If not specified, the language will be automatically detected from the input text.
178
-
179
- ## Advanced Examples
180
-
181
- ### Working with Voice Emotions
182
-
183
- Each voice supports different emotion presets. Check which emotions a voice supports before using them:
168
+ ### Voice Discovery
184
169
 
185
170
  ```typescript
186
- // Get voice information
187
- const voices = await client.getVoices("ssfm-v21");
188
- const myVoice = voices.find(v => v.voice_id === "tc_62a8975e695ad26f7fb514d1");
189
-
190
- console.log(`${myVoice.voice_name} supports: ${myVoice.emotions.join(', ')}`);
191
- // Example output: "Olivia supports: tonemid, toneup, normal, happy, sad, angry"
171
+ // Get all voices (V2 API - recommended)
172
+ const voices = await client.getVoicesV2();
173
+
174
+ // Filter by criteria
175
+ const filtered = await client.getVoicesV2({
176
+ model: 'ssfm-v30',
177
+ gender: 'female',
178
+ age: 'young_adult'
179
+ });
192
180
 
193
- // Use a supported emotion
194
- if (myVoice.emotions.includes('happy')) {
195
- const audio = await client.textToSpeech({
196
- text: "This voice supports the happy emotion!",
197
- voice_id: myVoice.voice_id,
198
- model: "ssfm-v21",
199
- prompt: {
200
- emotion_preset: "happy",
201
- emotion_intensity: 1.5
202
- }
203
- });
204
- // Save: await fs.promises.writeFile(`happy.${audio.format}`, Buffer.from(audio.audioData));
205
- }
181
+ // Display voice info
182
+ console.log(`Name: ${voices[0].voice_name}`);
183
+ console.log(`Gender: ${voices[0].gender}, Age: ${voices[0].age}`);
184
+ console.log(`Models: ${voices[0].models.map(m => m.version).join(', ')}`);
206
185
  ```
207
186
 
208
187
  ### Emotion Control
209
188
 
189
+ #### ssfm-v21: Basic Emotion
190
+
210
191
  ```typescript
211
- // Happy and energetic voice
212
- const happyAudio = await client.textToSpeech({
213
- text: "Great to see you!",
192
+ const audio = await client.textToSpeech({
193
+ text: "I'm so excited!",
214
194
  voice_id: "tc_62a8975e695ad26f7fb514d1",
215
195
  model: "ssfm-v21",
216
196
  prompt: {
217
- emotion_preset: "happy",
218
- emotion_intensity: 1.8
219
- },
220
- output: {
221
- audio_tempo: 1.2
197
+ emotion_preset: "happy", // normal, happy, sad, angry
198
+ emotion_intensity: 1.5 // 0.0 to 2.0
222
199
  }
223
200
  });
224
- // Save: await fs.promises.writeFile(`happy.${happyAudio.format}`, Buffer.from(happyAudio.audioData));
201
+ ```
225
202
 
226
- // Calm and professional voice
227
- const calmAudio = await client.textToSpeech({
228
- text: "Welcome to our presentation.",
229
- voice_id: "tc_62a8975e695ad26f7fb514d1",
230
- model: "ssfm-v21",
203
+ #### ssfm-v30: Preset Mode
204
+
205
+ ```typescript
206
+ import { PresetPrompt } from '@neosapience/typecast-js';
207
+
208
+ const audio = await client.textToSpeech({
209
+ text: "I'm so excited!",
210
+ voice_id: "tc_672c5f5ce59fac2a48faeaee",
211
+ model: "ssfm-v30",
231
212
  prompt: {
232
- emotion_preset: "normal",
233
- emotion_intensity: 0.8
234
- },
235
- output: {
236
- audio_tempo: 0.9
237
- }
213
+ emotion_type: "preset",
214
+ emotion_preset: "happy", // normal, happy, sad, angry, whisper, toneup, tonedown
215
+ emotion_intensity: 1.5
216
+ } as PresetPrompt
238
217
  });
239
- // Save: await fs.promises.writeFile(`calm.${calmAudio.format}`, Buffer.from(calmAudio.audioData));
240
218
  ```
241
219
 
242
- ### Audio Customization
220
+ #### ssfm-v30: Smart Mode (Context-Aware)
243
221
 
244
222
  ```typescript
245
- // Generate louder audio with higher pitch
246
- const customAudio = await client.textToSpeech({
247
- text: "This is a test with custom settings.",
248
- voice_id: "tc_62a8975e695ad26f7fb514d1",
249
- model: "ssfm-v21",
250
- output: {
251
- volume: 150,
252
- audio_pitch: 3,
253
- audio_tempo: 1.1,
254
- audio_format: "mp3"
255
- }
223
+ import { SmartPrompt } from '@neosapience/typecast-js';
224
+
225
+ const audio = await client.textToSpeech({
226
+ text: "Everything is perfect.",
227
+ voice_id: "tc_672c5f5ce59fac2a48faeaee",
228
+ model: "ssfm-v30",
229
+ prompt: {
230
+ emotion_type: "smart",
231
+ previous_text: "I just got the best news!",
232
+ next_text: "I can't wait to celebrate!"
233
+ } as SmartPrompt
256
234
  });
257
- // Save: await fs.promises.writeFile(`custom.${customAudio.format}`, Buffer.from(customAudio.audioData));
258
235
  ```
259
236
 
260
- ### Multilingual Content
237
+ ---
238
+
239
+ ## Supported Languages
240
+
241
+ <details>
242
+ <summary><strong>View all 37 supported languages</strong></summary>
243
+
244
+ | Code | Language | Code | Language | Code | Language |
245
+ |------|----------|------|----------|------|----------|
246
+ | `eng` | English | `jpn` | Japanese | `ukr` | Ukrainian |
247
+ | `kor` | Korean | `ell` | Greek | `ind` | Indonesian |
248
+ | `spa` | Spanish | `tam` | Tamil | `dan` | Danish |
249
+ | `deu` | German | `tgl` | Tagalog | `swe` | Swedish |
250
+ | `fra` | French | `fin` | Finnish | `msa` | Malay |
251
+ | `ita` | Italian | `zho` | Chinese | `ces` | Czech |
252
+ | `pol` | Polish | `slk` | Slovak | `por` | Portuguese |
253
+ | `nld` | Dutch | `ara` | Arabic | `bul` | Bulgarian |
254
+ | `rus` | Russian | `hrv` | Croatian | `ron` | Romanian |
255
+ | `ben` | Bengali | `hin` | Hindi | `hun` | Hungarian |
256
+ | `nan` | Hokkien | `nor` | Norwegian | `pan` | Punjabi |
257
+ | `tha` | Thai | `tur` | Turkish | `vie` | Vietnamese |
258
+ | `yue` | Cantonese | | | | |
259
+
260
+ </details>
261
261
 
262
262
  ```typescript
263
- // Korean text
264
- const koreanAudio = await client.textToSpeech({
265
- text: "안녕하세요. 반갑습니다.",
266
- voice_id: "tc_62a8975e695ad26f7fb514d1",
267
- model: "ssfm-v21",
268
- language: "kor"
263
+ // Auto-detect (recommended)
264
+ const audio = await client.textToSpeech({
265
+ text: "こんにちは",
266
+ voice_id: "...",
267
+ model: "ssfm-v30"
269
268
  });
270
- // Save: await fs.promises.writeFile(`korean.${koreanAudio.format}`, Buffer.from(koreanAudio.audioData));
271
269
 
272
- // Japanese text
273
- const japaneseAudio = await client.textToSpeech({
274
- text: "こんにちは。お元気ですか。",
275
- voice_id: "tc_62a8975e695ad26f7fb514d1",
276
- model: "ssfm-v21",
277
- language: "jpn"
270
+ // Explicit language
271
+ const audio = await client.textToSpeech({
272
+ text: "안녕하세요",
273
+ voice_id: "...",
274
+ model: "ssfm-v30",
275
+ language: "kor"
278
276
  });
279
- // Save: await fs.promises.writeFile(`japanese.${japaneseAudio.format}`, Buffer.from(japaneseAudio.audioData));
280
277
  ```
281
278
 
282
- ### Error Handling
279
+ ---
280
+
281
+ ## Error Handling
283
282
 
284
283
  ```typescript
285
284
  import { TypecastClient, TypecastAPIError } from '@neosapience/typecast-js';
286
285
 
287
- async function main() {
288
- const client = new TypecastClient({ apiKey: 'YOUR_API_KEY' });
289
-
290
- try {
291
- const audio = await client.textToSpeech({
292
- text: "Hello world",
293
- voice_id: "tc_62a8975e695ad26f7fb514d1",
294
- model: "ssfm-v21"
295
- });
296
- } catch (error) {
297
- if (error instanceof TypecastAPIError) {
298
- // TypecastAPIError exposes: statusCode (number), message (string), response (unknown)
299
- switch (error.statusCode) {
300
- case 401:
301
- console.error('Invalid API key');
302
- break;
303
- case 402:
304
- console.error('Insufficient credits');
305
- break;
306
- case 422:
307
- console.error('Validation error:', error.response);
308
- break;
309
- default:
310
- console.error(`API error (${error.statusCode}):`, error.message);
311
- }
312
- } else {
313
- console.error('Unexpected error:', error);
286
+ try {
287
+ const audio = await client.textToSpeech({ ... });
288
+ } catch (error) {
289
+ if (error instanceof TypecastAPIError) {
290
+ console.error(`Error ${error.statusCode}: ${error.message}`);
291
+
292
+ // Handle specific errors
293
+ switch (error.statusCode) {
294
+ case 401: // Invalid API key
295
+ case 402: // Insufficient credits
296
+ case 422: // Validation error
297
+ case 429: // Rate limit exceeded
314
298
  }
315
299
  }
316
300
  }
317
-
318
- main();
319
301
  ```
320
302
 
303
+ ---
304
+
321
305
  ## TypeScript Support
322
306
 
323
- This SDK is written in TypeScript and provides full type definitions:
307
+ Full type definitions are included:
324
308
 
325
309
  ```typescript
326
- import type {
327
- TTSRequest,
328
- TTSResponse,
310
+ import type {
311
+ TTSRequest,
312
+ TTSResponse,
313
+ TTSModel,
329
314
  LanguageCode,
330
315
  Prompt,
331
- Output
316
+ PresetPrompt,
317
+ SmartPrompt,
318
+ Output,
319
+ VoiceV2Response,
320
+ VoicesV2Filter
332
321
  } from '@neosapience/typecast-js';
333
322
  ```
334
323
 
335
- ## Documentation
336
-
337
- - [Typecast API Documentation](https://typecast.ai/docs)
338
- - [API Reference](https://typecast.ai/docs/api-reference)
339
- - [Quickstart Guide](https://typecast.ai/docs/quickstart)
324
+ ---
340
325
 
341
326
  ## License
342
327
 
343
- Apache-2.0 License
328
+ [Apache-2.0](LICENSE) © [Neosapience](https://typecast.ai/?lang=en)