chutes-js 1.0.2 → 1.1.1
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 +555 -310
- package/index.js +13 -4
- package/package.json +52 -50
- package/src/client.js +166 -151
- package/src/converters.js +243 -0
- package/src/errors.js +40 -20
- package/src/models/audio.js +69 -0
- package/src/models/image.js +438 -0
- package/src/models/index.js +20 -0
- package/src/models/video.js +58 -0
- package/src/normalizer.js +265 -0
- package/src/utils.js +5 -5
package/README.md
CHANGED
|
@@ -1,310 +1,555 @@
|
|
|
1
|
-
# chutes-js
|
|
2
|
-
|
|
3
|
-
A lightweight, functional JavaScript SDK for consuming [Chutes.ai](https://chutes.ai) APIs.
|
|
4
|
-
|
|
5
|
-
- **Zero dependencies** – Built on native `fetch` and `AsyncGenerator`
|
|
6
|
-
- **Streaming support** – First-class SSE parsing for chat/LLM responses
|
|
7
|
-
- **Universal** – Works in Node.js 18+, Cloudflare Workers, and browsers
|
|
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
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
|
153
|
-
|
|
154
|
-
| `
|
|
155
|
-
| `
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
|
203
|
-
|
|
204
|
-
| `
|
|
205
|
-
| `
|
|
206
|
-
| `
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
)
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
);
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
1
|
+
# chutes-js
|
|
2
|
+
|
|
3
|
+
A lightweight, functional JavaScript SDK for consuming [Chutes.ai](https://chutes.ai) APIs.
|
|
4
|
+
|
|
5
|
+
- **Zero dependencies** – Built on native `fetch` and `AsyncGenerator`
|
|
6
|
+
- **Streaming support** – First-class SSE parsing for chat/LLM responses
|
|
7
|
+
- **Universal** – Works in Node.js 18+, Cloudflare Workers, and browsers
|
|
8
|
+
- **Unified API** – Normalized parameters across all models with auto-translation
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install chutes-js
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Quick Start
|
|
17
|
+
|
|
18
|
+
```javascript
|
|
19
|
+
import { createClient, saveBlob } from 'chutes-js';
|
|
20
|
+
|
|
21
|
+
const client = createClient({ apiKey: process.env.CHUTES_API_KEY });
|
|
22
|
+
|
|
23
|
+
// 1. Chat Completion (OpenAI-compatible)
|
|
24
|
+
const response = await client.chat({
|
|
25
|
+
model: 'deepseek-ai/DeepSeek-V3-0324',
|
|
26
|
+
messages: [{ role: 'user', content: 'Hello!' }]
|
|
27
|
+
});
|
|
28
|
+
console.log(response.choices[0].message.content);
|
|
29
|
+
|
|
30
|
+
// 2. Image Generation (unified params)
|
|
31
|
+
const image = await client.image({
|
|
32
|
+
model: 'flux', // alias for FLUX.1-schnell
|
|
33
|
+
prompt: 'A beautiful sunset over mountains',
|
|
34
|
+
aspectRatio: '16:9', // auto-converted to width/height
|
|
35
|
+
steps: 25,
|
|
36
|
+
cfgScale: 7
|
|
37
|
+
});
|
|
38
|
+
await saveBlob(image, './sunset.png');
|
|
39
|
+
|
|
40
|
+
// 3. Video Generation (I2V with URL auto-fetch)
|
|
41
|
+
const video = await client.video({
|
|
42
|
+
model: 'wan', // alias for wan-2-2-i2v-14b-fast
|
|
43
|
+
prompt: 'A cat playing piano smoothly',
|
|
44
|
+
image: 'https://example.com/cat.jpg', // URL auto-fetched to base64
|
|
45
|
+
duration: 5, // seconds → frames via fps
|
|
46
|
+
aspectRatio: '16:9'
|
|
47
|
+
});
|
|
48
|
+
await saveBlob(video, './cat-piano.mp4');
|
|
49
|
+
|
|
50
|
+
// 4. Audio Generation (Text-to-Speech)
|
|
51
|
+
const audio = await client.audio({
|
|
52
|
+
model: 'tts', // alias for kokoro
|
|
53
|
+
text: 'Hello, welcome to Chutes!',
|
|
54
|
+
voice: 'af_heart',
|
|
55
|
+
speed: 1.0
|
|
56
|
+
});
|
|
57
|
+
await saveBlob(audio, './welcome.wav');
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## API Reference
|
|
61
|
+
|
|
62
|
+
### `createClient(config)`
|
|
63
|
+
|
|
64
|
+
Creates a new Chutes client.
|
|
65
|
+
|
|
66
|
+
| Option | Type | Default | Description |
|
|
67
|
+
|--------|------|---------|-------------|
|
|
68
|
+
| `apiKey` | `string` | *required* | Your Chutes API key |
|
|
69
|
+
| `timeout` | `number` | `60000` | Default timeout in ms (Video: 5min, Audio: 2min) |
|
|
70
|
+
|
|
71
|
+
> [!TIP]
|
|
72
|
+
> You can access `client.endpoints` to see the base URLs being used by the client.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
### LLM Methods (via `llm.chutes.ai`)
|
|
77
|
+
|
|
78
|
+
#### `client.chat(options)`
|
|
79
|
+
|
|
80
|
+
OpenAI-compatible chat completion.
|
|
81
|
+
|
|
82
|
+
```javascript
|
|
83
|
+
const response = await client.chat({
|
|
84
|
+
model: 'deepseek-ai/DeepSeek-V3-0324',
|
|
85
|
+
messages: [{ role: 'user', content: 'Explain quantum computing' }]
|
|
86
|
+
});
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
#### `client.chatStream(options)`
|
|
90
|
+
|
|
91
|
+
Streaming chat completion. Returns an async generator.
|
|
92
|
+
|
|
93
|
+
```javascript
|
|
94
|
+
for await (const chunk of client.chatStream({ model, messages })) {
|
|
95
|
+
process.stdout.write(chunk.choices[0]?.delta?.content || '');
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
### Image Methods
|
|
102
|
+
|
|
103
|
+
The SDK provides a **unified API** for image generation. Parameters are automatically translated to each model's native format.
|
|
104
|
+
|
|
105
|
+
#### `client.image(options)`
|
|
106
|
+
|
|
107
|
+
Generate an image using unified parameters.
|
|
108
|
+
|
|
109
|
+
```javascript
|
|
110
|
+
import { saveBlob } from 'chutes-js';
|
|
111
|
+
|
|
112
|
+
// Basic usage
|
|
113
|
+
const blob = await client.image({
|
|
114
|
+
model: 'flux',
|
|
115
|
+
prompt: 'A cyberpunk city at night'
|
|
116
|
+
});
|
|
117
|
+
await saveBlob(blob, './cyberpunk.png');
|
|
118
|
+
|
|
119
|
+
// With all options
|
|
120
|
+
const blob2 = await client.image({
|
|
121
|
+
model: 'qwen-image',
|
|
122
|
+
prompt: 'A serene Japanese garden',
|
|
123
|
+
aspectRatio: '16:9', // or use width/height directly
|
|
124
|
+
steps: 50,
|
|
125
|
+
cfgScale: 7.5,
|
|
126
|
+
negativePrompt: 'blurry, low quality',
|
|
127
|
+
seed: 42
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
// Image editing (requires reference images)
|
|
131
|
+
const edited = await client.image({
|
|
132
|
+
model: 'qwen-edit',
|
|
133
|
+
prompt: 'Add a rainbow to the sky',
|
|
134
|
+
images: ['https://example.com/photo.jpg'], // URLs auto-fetched
|
|
135
|
+
aspectRatio: '1:1'
|
|
136
|
+
});
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
> [!IMPORTANT]
|
|
140
|
+
> `saveBlob` is a Node.js utility. In browsers or Cloudflare Workers, handle the `Blob` using platform APIs.
|
|
141
|
+
|
|
142
|
+
#### Parameters
|
|
143
|
+
|
|
144
|
+
| Parameter | Type | Description |
|
|
145
|
+
|-----------|------|-------------|
|
|
146
|
+
| `model` | `string` | **Required.** Model ID or alias (e.g., `'flux'`, `'qwen-image'`, `'hidream'`) |
|
|
147
|
+
| `prompt` | `string` | **Required.** Image generation prompt |
|
|
148
|
+
| `aspectRatio` | `string` | Aspect ratio (e.g., `'16:9'`, `'1:1'`, `'9:16'`). Auto-converts to width/height. Conflicts with `width`/`height`. |
|
|
149
|
+
| `width` | `number` | Image width in pixels (default: 1024) |
|
|
150
|
+
| `height` | `number` | Image height in pixels (default: 1024) |
|
|
151
|
+
| `steps` | `number` | Number of inference steps (default varies by model: 25-50) |
|
|
152
|
+
| `cfgScale` | `number` | Guidance scale (default varies by model: 4-7.5) |
|
|
153
|
+
| `negativePrompt` | `string` | Negative prompt for content to avoid |
|
|
154
|
+
| `seed` | `number\|null` | Random seed for reproducibility |
|
|
155
|
+
| `images` | `string\|string[]` | Reference images for editing models (base64 or URL). URLs are auto-fetched. |
|
|
156
|
+
|
|
157
|
+
#### Alternative: Using `invoke()` for Raw API Access
|
|
158
|
+
|
|
159
|
+
For direct API access without parameter normalization:
|
|
160
|
+
|
|
161
|
+
```javascript
|
|
162
|
+
// Subdomain model (HiDream)
|
|
163
|
+
const image = await client.invoke(
|
|
164
|
+
{ name: 'hidream', username: 'chutes' },
|
|
165
|
+
'/generate',
|
|
166
|
+
{ prompt: 'Cyberpunk city', resolution: '1024x1024', guidance_scale: 5 }
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
// Centralized model (requires model in payload)
|
|
170
|
+
const image2 = await client.invoke(
|
|
171
|
+
'image.chutes.ai',
|
|
172
|
+
'/generate',
|
|
173
|
+
{ model: 'qwen-image', prompt: 'A sunset', width: 1024, height: 1024 }
|
|
174
|
+
);
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
<details>
|
|
178
|
+
<summary><strong>Supported Image Models (18 models)</strong></summary>
|
|
179
|
+
|
|
180
|
+
#### Centralized API Models (`image.chutes.ai`)
|
|
181
|
+
|
|
182
|
+
| Model | Aliases | Notes |
|
|
183
|
+
|-------|---------|-------|
|
|
184
|
+
| `qwen-image` | `qwen` | Qwen image generation |
|
|
185
|
+
| `Qwen-Image-2512` | `qwen-2512` | Qwen 2512 variant |
|
|
186
|
+
| `FLUX.1-schnell` | `flux`, `flux-schnell` | Fast FLUX model |
|
|
187
|
+
| `JuggernautXL` | `juggernaut` | Juggernaut XL |
|
|
188
|
+
| `JuggernautXL-Ragnarok` | `juggernaut-ragnarok` | Ragnarok variant |
|
|
189
|
+
| `iLustMix` | - | Illustration style |
|
|
190
|
+
| `chroma` | - | Chroma model |
|
|
191
|
+
| `Illustrij` | - | Illustration focused |
|
|
192
|
+
| `Animij` | - | Anime style |
|
|
193
|
+
| `HassakuXL` | - | Hassaku XL |
|
|
194
|
+
| `NovaFurryXL` | - | Furry art style |
|
|
195
|
+
| `stabilityai/stable-diffusion-xl-base-1.0` | `sdxl` | Stable Diffusion XL |
|
|
196
|
+
| `Lykon/dreamshaper-xl-1-0` | `dreamshaper` | DreamShaper XL |
|
|
197
|
+
| `diagonalge/Booba` | - | Community model |
|
|
198
|
+
| `diagonalge/ConstShaper` | - | Community model |
|
|
199
|
+
|
|
200
|
+
#### Subdomain API Models
|
|
201
|
+
|
|
202
|
+
| Model | Aliases | Notes |
|
|
203
|
+
|-------|---------|-------|
|
|
204
|
+
| `hidream` | - | HiDream (uses resolution enum) |
|
|
205
|
+
| `hunyuan-image-3` | `hunyuan` | Hunyuan Image 3 (uses size string) |
|
|
206
|
+
| `z-image-turbo` | `z-turbo` | Z-Image Turbo (fast generation) |
|
|
207
|
+
|
|
208
|
+
#### Image Editing Models (require `images` parameter)
|
|
209
|
+
|
|
210
|
+
| Model | Aliases | Notes |
|
|
211
|
+
|-------|---------|-------|
|
|
212
|
+
| `Qwen-Image-Edit-2511` | `qwen-edit-2511` | Qwen image editing (latest) |
|
|
213
|
+
| `qwen-image-edit-2509` | `qwen-edit` | Qwen image editing |
|
|
214
|
+
|
|
215
|
+
</details>
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
### Video Methods
|
|
220
|
+
|
|
221
|
+
Generate videos with unified parameters. The SDK handles image URL fetching and frame calculation automatically.
|
|
222
|
+
|
|
223
|
+
#### `client.video(options)`
|
|
224
|
+
|
|
225
|
+
Generate a video using unified parameters.
|
|
226
|
+
|
|
227
|
+
```javascript
|
|
228
|
+
import { readFileSync } from 'fs';
|
|
229
|
+
import { saveBlob } from 'chutes-js';
|
|
230
|
+
|
|
231
|
+
// Using image URL (auto-fetched to base64)
|
|
232
|
+
const video = await client.video({
|
|
233
|
+
model: 'wan', // alias for wan-2-2-i2v-14b-fast
|
|
234
|
+
prompt: 'A cat playing piano elegantly',
|
|
235
|
+
image: 'https://example.com/cat.jpg', // URL auto-fetched
|
|
236
|
+
duration: 5, // 5 seconds
|
|
237
|
+
aspectRatio: '16:9'
|
|
238
|
+
});
|
|
239
|
+
await saveBlob(video, './output.mp4');
|
|
240
|
+
|
|
241
|
+
// Using local file (base64)
|
|
242
|
+
const imageBase64 = readFileSync('./input.png').toString('base64');
|
|
243
|
+
const video2 = await client.video({
|
|
244
|
+
model: 'i2v',
|
|
245
|
+
prompt: 'Ocean waves crashing on rocks',
|
|
246
|
+
image: imageBase64,
|
|
247
|
+
frames: 81, // or use duration in seconds
|
|
248
|
+
fps: 16,
|
|
249
|
+
cfgScale: 1,
|
|
250
|
+
cfgScale2: 1,
|
|
251
|
+
negativePrompt: 'blurry, static',
|
|
252
|
+
seed: 12345
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
// Check for async job (some models return job ID)
|
|
256
|
+
if (video2 instanceof Blob) {
|
|
257
|
+
await saveBlob(video2, './ocean.mp4');
|
|
258
|
+
} else {
|
|
259
|
+
console.log('Job started:', video2.job_id);
|
|
260
|
+
// Poll with client.getJobStatus(video2.job_id)
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
#### Parameters
|
|
265
|
+
|
|
266
|
+
| Parameter | Type | Description |
|
|
267
|
+
|-----------|------|-------------|
|
|
268
|
+
| `model` | `string` | **Required.** Model ID or alias (e.g., `'wan'`, `'i2v'`) |
|
|
269
|
+
| `prompt` | `string` | **Required.** Video generation prompt |
|
|
270
|
+
| `image` | `string` | **Required.** Reference image (base64 or URL). URLs are auto-fetched. |
|
|
271
|
+
| `aspectRatio` | `string` | Aspect ratio, converts to resolution (e.g., `'16:9'` → `'480p'`) |
|
|
272
|
+
| `resolution` | `string` | Video resolution (`'480p'`, `'720p'`) |
|
|
273
|
+
| `duration` | `number` | Duration in seconds. Converted to frames via fps. Conflicts with `frames`. |
|
|
274
|
+
| `frames` | `number` | Number of frames (default: 81, range: 21-140) |
|
|
275
|
+
| `fps` | `number` | Frames per second (default: 16, range: 16-24) |
|
|
276
|
+
| `cfgScale` | `number` | Primary guidance scale (default: 1) |
|
|
277
|
+
| `cfgScale2` | `number` | Secondary guidance scale (default: 1) |
|
|
278
|
+
| `negativePrompt` | `string` | Negative prompt (has sensible default) |
|
|
279
|
+
| `seed` | `number\|null` | Random seed for reproducibility |
|
|
280
|
+
| `fast` | `boolean` | Use fast generation mode (default: true) |
|
|
281
|
+
|
|
282
|
+
> [!NOTE]
|
|
283
|
+
> Video generation has a default timeout of **5 minutes** (300,000ms).
|
|
284
|
+
|
|
285
|
+
#### Alternative: Using `invoke()` for Raw API Access
|
|
286
|
+
|
|
287
|
+
```javascript
|
|
288
|
+
const video = await client.invoke(
|
|
289
|
+
{ name: 'wan-2-2-i2v-14b-fast', username: 'chutes' },
|
|
290
|
+
'/generate',
|
|
291
|
+
{
|
|
292
|
+
prompt: 'A dog running',
|
|
293
|
+
image: imageBase64,
|
|
294
|
+
resolution: '480p',
|
|
295
|
+
fps: 16,
|
|
296
|
+
frames: 81,
|
|
297
|
+
guidance_scale: 1,
|
|
298
|
+
guidance_scale_2: 1
|
|
299
|
+
}
|
|
300
|
+
);
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
<details>
|
|
304
|
+
<summary><strong>Supported Video Models (1 model)</strong></summary>
|
|
305
|
+
|
|
306
|
+
| Model | Aliases | Type | Notes |
|
|
307
|
+
|-------|---------|------|-------|
|
|
308
|
+
| `wan-2-2-i2v-14b-fast` | `wan`, `i2v`, `wan-i2v` | Image-to-Video | Requires reference image |
|
|
309
|
+
|
|
310
|
+
</details>
|
|
311
|
+
|
|
312
|
+
---
|
|
313
|
+
|
|
314
|
+
### Audio Methods
|
|
315
|
+
|
|
316
|
+
Generate audio (Text-to-Speech) with unified parameters.
|
|
317
|
+
|
|
318
|
+
#### `client.audio(options)`
|
|
319
|
+
|
|
320
|
+
Generate audio using unified parameters.
|
|
321
|
+
|
|
322
|
+
```javascript
|
|
323
|
+
import { saveBlob } from 'chutes-js';
|
|
324
|
+
|
|
325
|
+
// Kokoro TTS (50+ voices)
|
|
326
|
+
const audio = await client.audio({
|
|
327
|
+
model: 'tts', // alias for kokoro
|
|
328
|
+
text: 'Hello, welcome to Chutes AI!',
|
|
329
|
+
voice: 'af_heart', // American female
|
|
330
|
+
speed: 1.0
|
|
331
|
+
});
|
|
332
|
+
await saveBlob(audio, './welcome.wav');
|
|
333
|
+
|
|
334
|
+
// CSM-1B (conversational)
|
|
335
|
+
const audio2 = await client.audio({
|
|
336
|
+
model: 'csm',
|
|
337
|
+
text: 'This is a test of the CSM model.',
|
|
338
|
+
speaker: 0,
|
|
339
|
+
maxDuration: 15 // 15 seconds (auto-converted to ms)
|
|
340
|
+
});
|
|
341
|
+
await saveBlob(audio2, './csm-test.wav');
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
#### Parameters
|
|
345
|
+
|
|
346
|
+
**Common:**
|
|
347
|
+
|
|
348
|
+
| Parameter | Type | Description |
|
|
349
|
+
|-----------|------|-------------|
|
|
350
|
+
| `model` | `string` | **Required.** Model ID or alias (e.g., `'tts'`, `'kokoro'`, `'csm'`) |
|
|
351
|
+
| `text` | `string` | **Required.** Text to speak |
|
|
352
|
+
|
|
353
|
+
**Kokoro-specific:**
|
|
354
|
+
|
|
355
|
+
| Parameter | Type | Description |
|
|
356
|
+
|-----------|------|-------------|
|
|
357
|
+
| `voice` | `string` | Voice ID (default: `'af_heart'`). See voice list below. |
|
|
358
|
+
| `speed` | `number` | Playback speed (default: 1.0, range: 0.1-3.0) |
|
|
359
|
+
|
|
360
|
+
**CSM-specific:**
|
|
361
|
+
|
|
362
|
+
| Parameter | Type | Description |
|
|
363
|
+
|-----------|------|-------------|
|
|
364
|
+
| `speaker` | `number` | Speaker ID (0 or 1) |
|
|
365
|
+
| `maxDuration` | `number` | Max duration in **seconds** (auto-converted to ms) |
|
|
366
|
+
| `maxDurationMs` | `number` | Max duration in milliseconds directly |
|
|
367
|
+
| `context` | `array` | Conversation context for multi-turn |
|
|
368
|
+
|
|
369
|
+
> [!NOTE]
|
|
370
|
+
> Audio generation has a default timeout of **2 minutes** (120,000ms).
|
|
371
|
+
|
|
372
|
+
#### Alternative: Using `invoke()` for Raw API Access
|
|
373
|
+
|
|
374
|
+
```javascript
|
|
375
|
+
// Kokoro via invoke
|
|
376
|
+
const audio = await client.invoke(
|
|
377
|
+
{ name: 'kokoro', username: 'chutes' },
|
|
378
|
+
'/speak',
|
|
379
|
+
{ text: 'Hello world', voice: 'af_heart', speed: 1.0 }
|
|
380
|
+
);
|
|
381
|
+
|
|
382
|
+
// CSM via invoke
|
|
383
|
+
const audio2 = await client.invoke(
|
|
384
|
+
{ name: 'csm-1b', username: 'chutes' },
|
|
385
|
+
'/speak',
|
|
386
|
+
{ text: 'Hello', speaker: 0, max_duration_ms: 10000 }
|
|
387
|
+
);
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
<details>
|
|
391
|
+
<summary><strong>Supported Audio Models (2 models)</strong></summary>
|
|
392
|
+
|
|
393
|
+
| Model | Aliases | Notes |
|
|
394
|
+
|-------|---------|-------|
|
|
395
|
+
| `kokoro` | `tts` | 50+ voices, fast TTS |
|
|
396
|
+
| `csm-1b` | `csm` | Conversational speech model |
|
|
397
|
+
|
|
398
|
+
</details>
|
|
399
|
+
|
|
400
|
+
<details>
|
|
401
|
+
<summary><strong>Kokoro Voice List (50+ voices)</strong></summary>
|
|
402
|
+
|
|
403
|
+
**American English - Female (`af_*`)**
|
|
404
|
+
- `af_heart` (default), `af_alloy`, `af_aoede`, `af_bella`, `af_jessica`, `af_kore`, `af_nicole`, `af_nova`, `af_river`, `af_sarah`, `af_sky`
|
|
405
|
+
|
|
406
|
+
**American English - Male (`am_*`)**
|
|
407
|
+
- `am_adam`, `am_echo`, `am_eric`, `am_fenrir`, `am_liam`, `am_michael`, `am_onyx`, `am_puck`, `am_santa`
|
|
408
|
+
|
|
409
|
+
**British English - Female (`bf_*`)**
|
|
410
|
+
- `bf_alice`, `bf_emma`, `bf_isabella`, `bf_lily`
|
|
411
|
+
|
|
412
|
+
**British English - Male (`bm_*`)**
|
|
413
|
+
- `bm_daniel`, `bm_fable`, `bm_george`, `bm_lewis`
|
|
414
|
+
|
|
415
|
+
**Spanish (`ef_*`, `em_*`)**
|
|
416
|
+
- `ef_dora`, `em_alex`, `em_santa`
|
|
417
|
+
|
|
418
|
+
**French (`ff_*`)**
|
|
419
|
+
- `ff_siwis`
|
|
420
|
+
|
|
421
|
+
**Hindi (`hf_*`, `hm_*`)**
|
|
422
|
+
- `hf_alpha`, `hf_beta`, `hm_omega`, `hm_psi`
|
|
423
|
+
|
|
424
|
+
**Italian (`if_*`, `im_*`)**
|
|
425
|
+
- `if_sara`, `im_nicola`
|
|
426
|
+
|
|
427
|
+
**Japanese (`jf_*`, `jm_*`)**
|
|
428
|
+
- `jf_alpha`, `jf_gongitsune`, `jf_nezumi`, `jf_tebukuro`, `jm_kumo`
|
|
429
|
+
|
|
430
|
+
**Portuguese (`pf_*`, `pm_*`)**
|
|
431
|
+
- `pf_dora`, `pm_alex`, `pm_santa`
|
|
432
|
+
|
|
433
|
+
**Chinese (`zf_*`, `zm_*`)**
|
|
434
|
+
- `zf_xiaobei`, `zf_xiaoni`, `zf_xiaoxiao`, `zf_xiaoyi`, `zm_yunjian`, `zm_yunxi`, `zm_yunxia`, `zm_yunyang`
|
|
435
|
+
|
|
436
|
+
</details>
|
|
437
|
+
|
|
438
|
+
---
|
|
439
|
+
|
|
440
|
+
### Invoke Methods (Advanced)
|
|
441
|
+
|
|
442
|
+
For models not covered by built-in methods, or when you need raw API access.
|
|
443
|
+
|
|
444
|
+
#### `client.invoke(target, path, payload)`
|
|
445
|
+
|
|
446
|
+
```javascript
|
|
447
|
+
// Pattern: https://{name}-{username}.chutes.ai/{path}
|
|
448
|
+
|
|
449
|
+
// Subdomain model
|
|
450
|
+
const result = await client.invoke(
|
|
451
|
+
{ name: 'custom-model', username: 'myuser' },
|
|
452
|
+
'/generate',
|
|
453
|
+
{ prompt: 'Hello', ...otherParams }
|
|
454
|
+
);
|
|
455
|
+
|
|
456
|
+
// Direct URL
|
|
457
|
+
const result2 = await client.invoke(
|
|
458
|
+
'https://custom-endpoint.chutes.ai',
|
|
459
|
+
'/api/v1/generate',
|
|
460
|
+
{ prompt: 'Hello' }
|
|
461
|
+
);
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
Returns: `Blob` (if image/video/audio), `Object` (if JSON), or `string` otherwise.
|
|
465
|
+
|
|
466
|
+
#### `client.invokeStream(target, path, payload)`
|
|
467
|
+
|
|
468
|
+
For streaming responses. Returns an `AsyncGenerator`.
|
|
469
|
+
|
|
470
|
+
#### `parseSSE(stream)`
|
|
471
|
+
|
|
472
|
+
The internal SSE parser is exported for custom streaming implementations.
|
|
473
|
+
|
|
474
|
+
---
|
|
475
|
+
|
|
476
|
+
### Job Methods (via `api.chutes.ai`)
|
|
477
|
+
|
|
478
|
+
For long-running async jobs.
|
|
479
|
+
|
|
480
|
+
#### `client.getJobStatus(jobId)`
|
|
481
|
+
|
|
482
|
+
```javascript
|
|
483
|
+
const status = await client.getJobStatus('job_abc123');
|
|
484
|
+
// { state: 'completed', result: {...} }
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
#### `client.deleteJob(jobId)`
|
|
488
|
+
|
|
489
|
+
Cancel or delete a job.
|
|
490
|
+
|
|
491
|
+
---
|
|
492
|
+
|
|
493
|
+
## Error Handling
|
|
494
|
+
|
|
495
|
+
```javascript
|
|
496
|
+
import { createClient, ChutesError, ValidationError } from 'chutes-js';
|
|
497
|
+
|
|
498
|
+
try {
|
|
499
|
+
await client.image({
|
|
500
|
+
model: 'flux',
|
|
501
|
+
prompt: 'A sunset',
|
|
502
|
+
steps: 500 // exceeds max
|
|
503
|
+
});
|
|
504
|
+
} catch (e) {
|
|
505
|
+
if (e instanceof ValidationError) {
|
|
506
|
+
// Parameter validation failed
|
|
507
|
+
console.log('Validation error:', e.message);
|
|
508
|
+
// e.g., "steps exceeds maximum value of 100"
|
|
509
|
+
} else if (e instanceof ChutesError) {
|
|
510
|
+
// API error
|
|
511
|
+
console.log('Status:', e.status); // 429 = rate limited
|
|
512
|
+
console.log('Body:', e.body); // Raw error response
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
| Error Class | When |
|
|
518
|
+
|-------------|------|
|
|
519
|
+
| `ValidationError` | Invalid parameters (missing required, out of range, conflicts) |
|
|
520
|
+
| `ChutesError` | API returned an error (auth, rate limit, server error) |
|
|
521
|
+
|
|
522
|
+
---
|
|
523
|
+
|
|
524
|
+
## Exports
|
|
525
|
+
|
|
526
|
+
```javascript
|
|
527
|
+
import {
|
|
528
|
+
// Client
|
|
529
|
+
createClient,
|
|
530
|
+
|
|
531
|
+
// Errors
|
|
532
|
+
ChutesError,
|
|
533
|
+
ValidationError,
|
|
534
|
+
|
|
535
|
+
// Utilities
|
|
536
|
+
parseSSE,
|
|
537
|
+
saveBlob,
|
|
538
|
+
|
|
539
|
+
// Model configs (advanced)
|
|
540
|
+
IMAGE_MODELS,
|
|
541
|
+
IMAGE_MODEL_ALIASES,
|
|
542
|
+
VIDEO_MODELS,
|
|
543
|
+
VIDEO_MODEL_ALIASES,
|
|
544
|
+
AUDIO_MODELS,
|
|
545
|
+
AUDIO_MODEL_ALIASES,
|
|
546
|
+
ALL_MODELS,
|
|
547
|
+
ALL_ALIASES
|
|
548
|
+
} from 'chutes-js';
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
---
|
|
552
|
+
|
|
553
|
+
## License
|
|
554
|
+
|
|
555
|
+
MIT
|