@neosapience/typecast-js 0.1.3 → 0.1.5
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 +219 -184
- package/lib/index.cjs +109 -41
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +142 -19
- package/lib/index.d.ts +142 -19
- package/lib/index.js +109 -37
- package/lib/index.js.map +1 -1
- package/package.json +3 -5
package/README.md
CHANGED
|
@@ -1,13 +1,38 @@
|
|
|
1
|
-
|
|
1
|
+
<div align="center">
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
[](LICENSE)
|
|
5
|
-
[](https://www.typescriptlang.org/)
|
|
6
|
-
[](https://nodejs.org/)
|
|
3
|
+
# Typecast SDK for JavaScript
|
|
7
4
|
|
|
8
|
-
The official
|
|
5
|
+
**The official JavaScript/TypeScript SDK for the Typecast Text-to-Speech API**
|
|
9
6
|
|
|
10
|
-
|
|
7
|
+
Convert text to lifelike speech using AI-powered voices
|
|
8
|
+
|
|
9
|
+
[](https://www.npmjs.com/package/@neosapience/typecast-js)
|
|
10
|
+
[](LICENSE)
|
|
11
|
+
[](https://www.typescriptlang.org/)
|
|
12
|
+
[](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
|
+
---
|
|
11
36
|
|
|
12
37
|
## Installation
|
|
13
38
|
|
|
@@ -15,279 +40,289 @@ Works with both JavaScript and TypeScript. TypeScript types included.
|
|
|
15
40
|
npm install @neosapience/typecast-js
|
|
16
41
|
```
|
|
17
42
|
|
|
18
|
-
|
|
43
|
+
<details>
|
|
44
|
+
<summary><strong>Node.js 16/17 Users</strong></summary>
|
|
45
|
+
|
|
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
|
+
```
|
|
19
51
|
|
|
20
|
-
|
|
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
|
|
21
65
|
|
|
22
66
|
```typescript
|
|
23
67
|
import { TypecastClient } from '@neosapience/typecast-js';
|
|
24
68
|
import fs from 'fs';
|
|
25
69
|
|
|
26
|
-
|
|
27
|
-
const client = new TypecastClient({
|
|
28
|
-
apiKey: 'YOUR_API_KEY'
|
|
29
|
-
});
|
|
70
|
+
const client = new TypecastClient({ apiKey: 'YOUR_API_KEY' });
|
|
30
71
|
|
|
31
|
-
// Convert text to speech
|
|
32
72
|
const audio = await client.textToSpeech({
|
|
33
|
-
text: "Hello
|
|
34
|
-
model: "ssfm-
|
|
35
|
-
voice_id: "
|
|
73
|
+
text: "Hello! I'm your friendly text-to-speech assistant.",
|
|
74
|
+
model: "ssfm-v30",
|
|
75
|
+
voice_id: "tc_672c5f5ce59fac2a48faeaee"
|
|
36
76
|
});
|
|
37
77
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
console.log(`Audio saved! Duration: ${audio.duration}s, Format: ${audio.format}`);
|
|
78
|
+
await fs.promises.writeFile(`output.${audio.format}`, Buffer.from(audio.audioData));
|
|
79
|
+
console.log(`Saved: output.${audio.format} (${audio.duration}s)`);
|
|
41
80
|
```
|
|
42
81
|
|
|
43
|
-
|
|
82
|
+
<details>
|
|
83
|
+
<summary><strong>CommonJS Example</strong></summary>
|
|
44
84
|
|
|
45
85
|
```javascript
|
|
46
86
|
const { TypecastClient } = require('@neosapience/typecast-js');
|
|
47
87
|
const fs = require('fs');
|
|
48
88
|
|
|
49
89
|
async function main() {
|
|
50
|
-
const client = new TypecastClient({
|
|
51
|
-
apiKey: 'YOUR_API_KEY'
|
|
52
|
-
});
|
|
53
|
-
|
|
90
|
+
const client = new TypecastClient({ apiKey: 'YOUR_API_KEY' });
|
|
54
91
|
const audio = await client.textToSpeech({
|
|
55
|
-
text: "Hello
|
|
56
|
-
model: "ssfm-
|
|
57
|
-
voice_id: "
|
|
92
|
+
text: "Hello! I'm your friendly text-to-speech assistant.",
|
|
93
|
+
model: "ssfm-v30",
|
|
94
|
+
voice_id: "tc_672c5f5ce59fac2a48faeaee"
|
|
58
95
|
});
|
|
59
|
-
|
|
60
|
-
await fs.promises.writeFile('output.wav', Buffer.from(audio.audioData));
|
|
61
|
-
console.log(`Audio saved! Duration: ${audio.duration}s, Format: ${audio.format}`);
|
|
96
|
+
await fs.promises.writeFile(`output.${audio.format}`, Buffer.from(audio.audioData));
|
|
62
97
|
}
|
|
63
98
|
|
|
64
99
|
main();
|
|
65
100
|
```
|
|
66
101
|
|
|
67
|
-
|
|
102
|
+
</details>
|
|
68
103
|
|
|
69
|
-
|
|
104
|
+
---
|
|
70
105
|
|
|
71
|
-
|
|
72
|
-
// Using environment variables
|
|
73
|
-
// TYPECAST_API_KEY=your_api_key
|
|
74
|
-
// TYPECAST_API_HOST=https://api.typecast.ai (optional)
|
|
75
|
-
const client = new TypecastClient();
|
|
106
|
+
## Features
|
|
76
107
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
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 |
|
|
83
117
|
|
|
84
|
-
|
|
118
|
+
---
|
|
85
119
|
|
|
86
|
-
|
|
120
|
+
## Usage
|
|
87
121
|
|
|
88
|
-
|
|
122
|
+
### Configuration
|
|
89
123
|
|
|
90
124
|
```typescript
|
|
91
|
-
|
|
92
|
-
text: "Hello. How are you?",
|
|
93
|
-
voice_id: "tc_62a8975e695ad26f7fb514d1",
|
|
94
|
-
model: "ssfm-v21",
|
|
95
|
-
language: "eng", // optional, auto-detected if not provided
|
|
96
|
-
prompt: {
|
|
97
|
-
emotion_preset: "happy",
|
|
98
|
-
emotion_intensity: 1.5
|
|
99
|
-
},
|
|
100
|
-
output: {
|
|
101
|
-
audio_format: "mp3",
|
|
102
|
-
volume: 100,
|
|
103
|
-
audio_pitch: 0,
|
|
104
|
-
audio_tempo: 1.0
|
|
105
|
-
},
|
|
106
|
-
seed: 42 // for reproducible results
|
|
107
|
-
});
|
|
108
|
-
```
|
|
125
|
+
import { TypecastClient } from '@neosapience/typecast-js';
|
|
109
126
|
|
|
110
|
-
|
|
127
|
+
// Using environment variable (recommended)
|
|
128
|
+
// export TYPECAST_API_KEY="your-api-key"
|
|
129
|
+
const client = new TypecastClient();
|
|
111
130
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
- `emotion_intensity`: 0.0 - 2.0 (default: 1.0)
|
|
119
|
-
- `speed`: 0.5 - 2.0 (default: 1.0)
|
|
120
|
-
- `intonation`: -2 - 2 (default: 0)
|
|
121
|
-
- **output** (optional): Audio output settings
|
|
122
|
-
- `audio_format`: `'wav' | 'mp3'` (default: `'wav'`)
|
|
123
|
-
- `volume`: 0 - 200 (default: 100)
|
|
124
|
-
- `audio_pitch`: -12 - 12 semitones (default: 0)
|
|
125
|
-
- `audio_tempo`: 0.5 - 2.0 (default: 1.0)
|
|
126
|
-
- **seed** (optional): Random seed for reproducible results
|
|
131
|
+
// Or pass directly
|
|
132
|
+
const client = new TypecastClient({
|
|
133
|
+
apiKey: 'your-api-key',
|
|
134
|
+
baseHost: 'https://api.typecast.ai' // optional
|
|
135
|
+
});
|
|
136
|
+
```
|
|
127
137
|
|
|
128
|
-
###
|
|
138
|
+
### Text to Speech
|
|
129
139
|
|
|
130
|
-
|
|
140
|
+
#### Basic Usage
|
|
131
141
|
|
|
132
142
|
```typescript
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
const voices = await client.getVoices("ssfm-v21");
|
|
138
|
-
|
|
139
|
-
voices.forEach(voice => {
|
|
140
|
-
console.log(`${voice.voice_name} (${voice.voice_id})`);
|
|
141
|
-
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"
|
|
142
147
|
});
|
|
143
148
|
```
|
|
144
149
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
Get information about a specific voice.
|
|
150
|
+
#### With Audio Options
|
|
148
151
|
|
|
149
152
|
```typescript
|
|
150
|
-
const
|
|
151
|
-
|
|
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
|
+
});
|
|
152
166
|
```
|
|
153
167
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
The SDK supports 27 languages with automatic language detection:
|
|
157
|
-
|
|
158
|
-
| Code | Language | Code | Language | Code | Language |
|
|
159
|
-
|------|------------|------|------------|------|------------|
|
|
160
|
-
| eng | English | jpn | Japanese | ukr | Ukrainian |
|
|
161
|
-
| kor | Korean | ell | Greek | ind | Indonesian |
|
|
162
|
-
| spa | Spanish | tam | Tamil | dan | Danish |
|
|
163
|
-
| deu | German | tgl | Tagalog | swe | Swedish |
|
|
164
|
-
| fra | French | fin | Finnish | msa | Malay |
|
|
165
|
-
| ita | Italian | zho | Chinese | ces | Czech |
|
|
166
|
-
| pol | Polish | slk | Slovak | por | Portuguese |
|
|
167
|
-
| nld | Dutch | ara | Arabic | bul | Bulgarian |
|
|
168
|
-
| rus | Russian | hrv | Croatian | ron | Romanian |
|
|
168
|
+
### Voice Discovery
|
|
169
169
|
|
|
170
|
-
|
|
170
|
+
```typescript
|
|
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
|
+
});
|
|
171
180
|
|
|
172
|
-
|
|
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(', ')}`);
|
|
185
|
+
```
|
|
173
186
|
|
|
174
187
|
### Emotion Control
|
|
175
188
|
|
|
189
|
+
#### ssfm-v21: Basic Emotion
|
|
190
|
+
|
|
176
191
|
```typescript
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
text: "Great to see you!",
|
|
192
|
+
const audio = await client.textToSpeech({
|
|
193
|
+
text: "I'm so excited!",
|
|
180
194
|
voice_id: "tc_62a8975e695ad26f7fb514d1",
|
|
181
195
|
model: "ssfm-v21",
|
|
182
196
|
prompt: {
|
|
183
|
-
emotion_preset: "happy",
|
|
184
|
-
emotion_intensity: 1.
|
|
185
|
-
speed: 1.2
|
|
197
|
+
emotion_preset: "happy", // normal, happy, sad, angry
|
|
198
|
+
emotion_intensity: 1.5 // 0.0 to 2.0
|
|
186
199
|
}
|
|
187
200
|
});
|
|
201
|
+
```
|
|
188
202
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
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",
|
|
194
212
|
prompt: {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
}
|
|
213
|
+
emotion_type: "preset",
|
|
214
|
+
emotion_preset: "happy", // normal, happy, sad, angry, whisper, toneup, tonedown
|
|
215
|
+
emotion_intensity: 1.5
|
|
216
|
+
} as PresetPrompt
|
|
199
217
|
});
|
|
200
218
|
```
|
|
201
219
|
|
|
202
|
-
|
|
220
|
+
#### ssfm-v30: Smart Mode (Context-Aware)
|
|
203
221
|
|
|
204
222
|
```typescript
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
}
|
|
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
|
|
216
234
|
});
|
|
217
235
|
```
|
|
218
236
|
|
|
219
|
-
|
|
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>
|
|
220
261
|
|
|
221
262
|
```typescript
|
|
222
|
-
//
|
|
223
|
-
const
|
|
224
|
-
text: "
|
|
225
|
-
voice_id: "
|
|
226
|
-
model: "ssfm-
|
|
227
|
-
language: "kor"
|
|
263
|
+
// Auto-detect (recommended)
|
|
264
|
+
const audio = await client.textToSpeech({
|
|
265
|
+
text: "こんにちは",
|
|
266
|
+
voice_id: "...",
|
|
267
|
+
model: "ssfm-v30"
|
|
228
268
|
});
|
|
229
269
|
|
|
230
|
-
//
|
|
231
|
-
const
|
|
232
|
-
text: "
|
|
233
|
-
voice_id: "
|
|
234
|
-
model: "ssfm-
|
|
235
|
-
language: "
|
|
270
|
+
// Explicit language
|
|
271
|
+
const audio = await client.textToSpeech({
|
|
272
|
+
text: "안녕하세요",
|
|
273
|
+
voice_id: "...",
|
|
274
|
+
model: "ssfm-v30",
|
|
275
|
+
language: "kor"
|
|
236
276
|
});
|
|
237
277
|
```
|
|
238
278
|
|
|
239
|
-
|
|
279
|
+
---
|
|
280
|
+
|
|
281
|
+
## Error Handling
|
|
240
282
|
|
|
241
283
|
```typescript
|
|
242
284
|
import { TypecastClient, TypecastAPIError } from '@neosapience/typecast-js';
|
|
243
285
|
|
|
244
286
|
try {
|
|
245
|
-
const audio = await client.textToSpeech({
|
|
246
|
-
text: "Hello world",
|
|
247
|
-
voice_id: "tc_62a8975e695ad26f7fb514d1",
|
|
248
|
-
model: "ssfm-v21"
|
|
249
|
-
});
|
|
287
|
+
const audio = await client.textToSpeech({ ... });
|
|
250
288
|
} catch (error) {
|
|
251
289
|
if (error instanceof TypecastAPIError) {
|
|
290
|
+
console.error(`Error ${error.statusCode}: ${error.message}`);
|
|
291
|
+
|
|
292
|
+
// Handle specific errors
|
|
252
293
|
switch (error.statusCode) {
|
|
253
|
-
case 401:
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
case
|
|
257
|
-
console.error('Insufficient credits');
|
|
258
|
-
break;
|
|
259
|
-
case 422:
|
|
260
|
-
console.error('Validation error:', error.response);
|
|
261
|
-
break;
|
|
262
|
-
default:
|
|
263
|
-
console.error(`API error (${error.statusCode}):`, error.message);
|
|
294
|
+
case 401: // Invalid API key
|
|
295
|
+
case 402: // Insufficient credits
|
|
296
|
+
case 422: // Validation error
|
|
297
|
+
case 429: // Rate limit exceeded
|
|
264
298
|
}
|
|
265
|
-
} else {
|
|
266
|
-
console.error('Unexpected error:', error);
|
|
267
299
|
}
|
|
268
300
|
}
|
|
269
301
|
```
|
|
270
302
|
|
|
303
|
+
---
|
|
304
|
+
|
|
271
305
|
## TypeScript Support
|
|
272
306
|
|
|
273
|
-
|
|
307
|
+
Full type definitions are included:
|
|
274
308
|
|
|
275
309
|
```typescript
|
|
276
|
-
import type {
|
|
277
|
-
TTSRequest,
|
|
278
|
-
TTSResponse,
|
|
310
|
+
import type {
|
|
311
|
+
TTSRequest,
|
|
312
|
+
TTSResponse,
|
|
313
|
+
TTSModel,
|
|
279
314
|
LanguageCode,
|
|
280
315
|
Prompt,
|
|
281
|
-
|
|
316
|
+
PresetPrompt,
|
|
317
|
+
SmartPrompt,
|
|
318
|
+
Output,
|
|
319
|
+
VoiceV2Response,
|
|
320
|
+
VoicesV2Filter
|
|
282
321
|
} from '@neosapience/typecast-js';
|
|
283
322
|
```
|
|
284
323
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
- [Typecast API Documentation](https://typecast.ai/docs)
|
|
288
|
-
- [API Reference](https://typecast.ai/docs/api-reference)
|
|
289
|
-
- [Quickstart Guide](https://typecast.ai/docs/quickstart)
|
|
324
|
+
---
|
|
290
325
|
|
|
291
326
|
## License
|
|
292
327
|
|
|
293
|
-
Apache-2.0
|
|
328
|
+
[Apache-2.0](LICENSE) © [Neosapience](https://typecast.ai)
|