@howells/motif-sdk 0.5.0 → 0.6.0
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 +8 -2
- package/dist/index.cjs +1355 -1160
- package/dist/index.d.cts +506 -503
- package/dist/index.d.ts +506 -503
- package/dist/index.js +1355 -1160
- package/package.json +21 -21
package/dist/index.cjs
CHANGED
|
@@ -81,62 +81,80 @@ var ASPECT_RATIOS = [
|
|
|
81
81
|
var RESOLUTIONS = ["0.5K", "1K", "2K", "4K"];
|
|
82
82
|
function aspectToGptSize(aspect) {
|
|
83
83
|
switch (aspect) {
|
|
84
|
-
case "auto":
|
|
84
|
+
case "auto": {
|
|
85
85
|
return "auto";
|
|
86
|
+
}
|
|
86
87
|
case "9:16":
|
|
87
88
|
case "1:8":
|
|
88
89
|
case "1:4":
|
|
89
90
|
case "2:3":
|
|
90
91
|
case "4:5":
|
|
91
|
-
case "3:4":
|
|
92
|
+
case "3:4": {
|
|
92
93
|
return "1024x1536";
|
|
94
|
+
}
|
|
93
95
|
case "16:9":
|
|
94
96
|
case "8:1":
|
|
95
97
|
case "4:1":
|
|
96
98
|
case "3:2":
|
|
97
99
|
case "5:4":
|
|
98
100
|
case "4:3":
|
|
99
|
-
case "21:9":
|
|
101
|
+
case "21:9": {
|
|
100
102
|
return "1536x1024";
|
|
101
|
-
|
|
103
|
+
}
|
|
104
|
+
case "1:1": {
|
|
102
105
|
return "1024x1024";
|
|
106
|
+
}
|
|
107
|
+
default: {
|
|
108
|
+
return "1024x1024";
|
|
109
|
+
}
|
|
103
110
|
}
|
|
104
111
|
}
|
|
105
112
|
function aspectToFalImageSize(aspect) {
|
|
106
113
|
switch (aspect) {
|
|
107
|
-
case "auto":
|
|
114
|
+
case "auto": {
|
|
108
115
|
return "auto";
|
|
116
|
+
}
|
|
109
117
|
case "16:9":
|
|
110
118
|
case "21:9":
|
|
111
119
|
case "4:1":
|
|
112
|
-
case "8:1":
|
|
120
|
+
case "8:1": {
|
|
113
121
|
return "landscape_16_9";
|
|
122
|
+
}
|
|
114
123
|
case "3:2":
|
|
115
|
-
case "5:4":
|
|
124
|
+
case "5:4": {
|
|
116
125
|
return "landscape_4_3";
|
|
117
|
-
|
|
126
|
+
}
|
|
127
|
+
case "4:3": {
|
|
118
128
|
return "landscape_4_3";
|
|
129
|
+
}
|
|
119
130
|
case "9:16":
|
|
120
131
|
case "1:4":
|
|
121
|
-
case "1:8":
|
|
132
|
+
case "1:8": {
|
|
122
133
|
return "portrait_16_9";
|
|
134
|
+
}
|
|
123
135
|
case "2:3":
|
|
124
|
-
case "4:5":
|
|
136
|
+
case "4:5": {
|
|
125
137
|
return "portrait_4_3";
|
|
126
|
-
|
|
138
|
+
}
|
|
139
|
+
case "3:4": {
|
|
127
140
|
return "portrait_4_3";
|
|
128
|
-
|
|
141
|
+
}
|
|
142
|
+
case "1:1": {
|
|
143
|
+
return "square_hd";
|
|
144
|
+
}
|
|
145
|
+
default: {
|
|
129
146
|
return "square_hd";
|
|
147
|
+
}
|
|
130
148
|
}
|
|
131
149
|
}
|
|
132
150
|
var FORMAT_PRESETS = {
|
|
133
|
-
cover: {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
portrait: {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
wide: {
|
|
151
|
+
cover: { aspect: "2:3", label: "Cover", resolution: "2K" },
|
|
152
|
+
landscape: { aspect: "16:9", label: "Landscape" },
|
|
153
|
+
og: { aspect: "16:9", label: "OG Image" },
|
|
154
|
+
portrait: { aspect: "2:3", label: "Portrait" },
|
|
155
|
+
square: { aspect: "1:1", label: "Square" },
|
|
156
|
+
story: { aspect: "9:16", label: "Story" },
|
|
157
|
+
wide: { aspect: "21:9", label: "Wide" }
|
|
140
158
|
};
|
|
141
159
|
|
|
142
160
|
// src/models.ts
|
|
@@ -150,311 +168,311 @@ var FAL_PRICING_CHECKED_JUL_2026 = "2026-07-11";
|
|
|
150
168
|
var MODELS = {
|
|
151
169
|
// ─── Generation Models ────────────────────────────────────────
|
|
152
170
|
gpt2: {
|
|
153
|
-
name: "GPT Image 2",
|
|
154
|
-
endpoint: "openai/gpt-image-2",
|
|
155
|
-
editEndpoint: "openai/gpt-image-2/image-to-image",
|
|
156
|
-
type: "generation",
|
|
157
|
-
pricing: "$0.211",
|
|
158
|
-
pricePerImageUsd: 0.211,
|
|
159
|
-
falPricing: {
|
|
160
|
-
endpointId: "openai/gpt-image-2",
|
|
161
|
-
unitPrice: 1,
|
|
162
|
-
unit: "units",
|
|
163
|
-
currency: "USD",
|
|
164
|
-
estimatedCostPerImageUsd: 0.211,
|
|
165
|
-
source: "fal-pricing-api",
|
|
166
|
-
checkedAt: FAL_PRICING_CHECKED_AT
|
|
167
|
-
},
|
|
168
171
|
benchmark: {
|
|
169
|
-
|
|
170
|
-
|
|
172
|
+
artificialAnalysis: {
|
|
173
|
+
editing: { elo: 1249, pricePer1k: 211, rank: 3, winRate: 0.66 },
|
|
174
|
+
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
175
|
+
sourceUrls: AA_IMAGE_SOURCES,
|
|
176
|
+
textToImage: { elo: 1337, pricePer1k: 211, rank: 1, winRate: 0.8 }
|
|
177
|
+
},
|
|
171
178
|
speed: {
|
|
172
179
|
medianSeconds: 200.7,
|
|
173
180
|
p95Seconds: 232.6,
|
|
174
181
|
source: "artificial-analysis-models"
|
|
175
182
|
},
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
183
|
+
tiers: { price: "ultra", quality: "frontier", speed: "very_slow" },
|
|
184
|
+
useCase: "Highest-ranked text-to-image quality and transparent PNGs"
|
|
185
|
+
},
|
|
186
|
+
editEndpoint: "openai/gpt-image-2/image-to-image",
|
|
187
|
+
endpoint: "openai/gpt-image-2",
|
|
188
|
+
falPricing: {
|
|
189
|
+
checkedAt: FAL_PRICING_CHECKED_AT,
|
|
190
|
+
currency: "USD",
|
|
191
|
+
endpointId: "openai/gpt-image-2",
|
|
192
|
+
estimatedCostPerImageUsd: 0.211,
|
|
193
|
+
source: "fal-pricing-api",
|
|
194
|
+
unit: "units",
|
|
195
|
+
unitPrice: 1
|
|
182
196
|
},
|
|
197
|
+
maxReferenceImages: 4,
|
|
198
|
+
name: "GPT Image 2",
|
|
199
|
+
pricePerImageUsd: 0.211,
|
|
200
|
+
pricing: "$0.211",
|
|
183
201
|
sizeMode: "image_size_enum",
|
|
184
202
|
supportsAspect: true,
|
|
185
|
-
supportsResolution: false,
|
|
186
203
|
supportsEdit: true,
|
|
204
|
+
supportsMaskImage: true,
|
|
187
205
|
supportsNumImages: true,
|
|
188
206
|
supportsOutputFormat: true,
|
|
189
207
|
supportsQuality: true,
|
|
190
|
-
|
|
208
|
+
supportsResolution: false,
|
|
191
209
|
supportsSyncMode: true,
|
|
192
|
-
|
|
210
|
+
type: "generation",
|
|
193
211
|
useQueue: true
|
|
194
212
|
},
|
|
195
213
|
gpt: {
|
|
196
|
-
name: "GPT Image 1.5",
|
|
197
|
-
endpoint: "fal-ai/gpt-image-1.5",
|
|
198
|
-
editEndpoint: "fal-ai/gpt-image-1.5/edit",
|
|
199
|
-
type: "generation",
|
|
200
|
-
pricing: "$0.133",
|
|
201
|
-
pricePerImageUsd: 0.133,
|
|
202
|
-
falPricing: {
|
|
203
|
-
endpointId: "fal-ai/gpt-image-1.5",
|
|
204
|
-
unitPrice: 1,
|
|
205
|
-
unit: "units",
|
|
206
|
-
currency: "USD",
|
|
207
|
-
estimatedCostPerImageUsd: 0.133,
|
|
208
|
-
source: "fal-pricing-api",
|
|
209
|
-
checkedAt: FAL_PRICING_CHECKED_AT
|
|
210
|
-
},
|
|
211
214
|
benchmark: {
|
|
212
|
-
|
|
213
|
-
|
|
215
|
+
artificialAnalysis: {
|
|
216
|
+
editing: { elo: 1262, pricePer1k: 133, rank: 2, winRate: 0.69 },
|
|
217
|
+
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
218
|
+
sourceUrls: AA_IMAGE_SOURCES,
|
|
219
|
+
textToImage: { elo: 1268, pricePer1k: 133, rank: 2, winRate: 0.73 }
|
|
220
|
+
},
|
|
214
221
|
speed: {
|
|
215
222
|
medianSeconds: 34.6,
|
|
216
223
|
p95Seconds: 38.3,
|
|
217
224
|
source: "artificial-analysis-models"
|
|
218
225
|
},
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
226
|
+
tiers: { price: "ultra", quality: "frontier", speed: "slow" },
|
|
227
|
+
useCase: "Best OpenAI edit quality with transparent PNG support"
|
|
228
|
+
},
|
|
229
|
+
editEndpoint: "fal-ai/gpt-image-1.5/edit",
|
|
230
|
+
endpoint: "fal-ai/gpt-image-1.5",
|
|
231
|
+
falPricing: {
|
|
232
|
+
checkedAt: FAL_PRICING_CHECKED_AT,
|
|
233
|
+
currency: "USD",
|
|
234
|
+
endpointId: "fal-ai/gpt-image-1.5",
|
|
235
|
+
estimatedCostPerImageUsd: 0.133,
|
|
236
|
+
source: "fal-pricing-api",
|
|
237
|
+
unit: "units",
|
|
238
|
+
unitPrice: 1
|
|
225
239
|
},
|
|
240
|
+
maxReferenceImages: 4,
|
|
241
|
+
name: "GPT Image 1.5",
|
|
242
|
+
pricePerImageUsd: 0.133,
|
|
243
|
+
pricing: "$0.133",
|
|
226
244
|
sizeMode: "gpt_size",
|
|
227
245
|
supportsAspect: false,
|
|
228
246
|
supportsBackground: true,
|
|
229
|
-
supportsResolution: false,
|
|
230
247
|
supportsEdit: true,
|
|
248
|
+
supportsMaskImage: true,
|
|
231
249
|
supportsNumImages: true,
|
|
232
250
|
supportsOutputFormat: true,
|
|
233
251
|
supportsQuality: true,
|
|
234
|
-
|
|
252
|
+
supportsResolution: false,
|
|
235
253
|
supportsSyncMode: true,
|
|
236
|
-
|
|
254
|
+
type: "generation"
|
|
237
255
|
},
|
|
238
256
|
banana2: {
|
|
239
|
-
|
|
240
|
-
|
|
257
|
+
benchmark: {
|
|
258
|
+
artificialAnalysis: {
|
|
259
|
+
editing: { elo: 1231, pricePer1k: 67, rank: 5, winRate: 0.63 },
|
|
260
|
+
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
261
|
+
sourceUrls: AA_IMAGE_SOURCES,
|
|
262
|
+
textToImage: { elo: 1263, pricePer1k: 67, rank: 3, winRate: 0.71 }
|
|
263
|
+
},
|
|
264
|
+
tiers: { price: "premium", quality: "frontier", speed: "unknown" },
|
|
265
|
+
useCase: "Best balance of quality, edit support, web search, and cost"
|
|
266
|
+
},
|
|
241
267
|
editEndpoint: "fal-ai/nano-banana-2/edit",
|
|
242
|
-
|
|
243
|
-
pricing: "$0.08",
|
|
244
|
-
pricePerImageUsd: 0.08,
|
|
268
|
+
endpoint: "fal-ai/nano-banana-2",
|
|
245
269
|
falPricing: {
|
|
246
|
-
|
|
247
|
-
unitPrice: 0.08,
|
|
248
|
-
unit: "images",
|
|
270
|
+
checkedAt: FAL_PRICING_CHECKED_AT,
|
|
249
271
|
currency: "USD",
|
|
272
|
+
endpointId: "fal-ai/nano-banana-2",
|
|
250
273
|
estimatedCostPerImageUsd: 0.08,
|
|
251
274
|
source: "fal-pricing-api",
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
benchmark: {
|
|
255
|
-
useCase: "Best balance of quality, edit support, web search, and cost",
|
|
256
|
-
tiers: { quality: "frontier", speed: "unknown", price: "premium" },
|
|
257
|
-
artificialAnalysis: {
|
|
258
|
-
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
259
|
-
sourceUrls: AA_IMAGE_SOURCES,
|
|
260
|
-
textToImage: { rank: 3, elo: 1263, winRate: 0.71, pricePer1k: 67 },
|
|
261
|
-
editing: { rank: 5, elo: 1231, winRate: 0.63, pricePer1k: 67 }
|
|
262
|
-
}
|
|
275
|
+
unit: "images",
|
|
276
|
+
unitPrice: 0.08
|
|
263
277
|
},
|
|
278
|
+
maxReferenceImages: 4,
|
|
279
|
+
name: "Nano Banana 2",
|
|
280
|
+
pricePerImageUsd: 0.08,
|
|
281
|
+
pricing: "$0.08",
|
|
264
282
|
sizeMode: "aspect_ratio",
|
|
265
283
|
supportsAspect: true,
|
|
266
|
-
supportsResolution: true,
|
|
267
284
|
supportsEdit: true,
|
|
285
|
+
supportsGoogleSearch: true,
|
|
286
|
+
supportsLimitGenerations: true,
|
|
268
287
|
supportsNumImages: true,
|
|
269
288
|
supportsOutputFormat: true,
|
|
289
|
+
supportsResolution: true,
|
|
270
290
|
supportsSafetyTolerance: true,
|
|
271
291
|
supportsSeed: true,
|
|
272
|
-
supportsWebSearch: true,
|
|
273
|
-
supportsGoogleSearch: true,
|
|
274
|
-
supportsLimitGenerations: true,
|
|
275
292
|
supportsSyncMode: true,
|
|
276
293
|
supportsThinkingLevel: true,
|
|
277
|
-
|
|
294
|
+
supportsWebSearch: true,
|
|
295
|
+
type: "generation"
|
|
278
296
|
},
|
|
279
297
|
banana: {
|
|
280
|
-
name: "Nano Banana Pro",
|
|
281
|
-
endpoint: "fal-ai/nano-banana-pro",
|
|
282
|
-
editEndpoint: "fal-ai/nano-banana-pro/edit",
|
|
283
|
-
type: "generation",
|
|
284
|
-
pricing: "$0.15",
|
|
285
|
-
pricePerImageUsd: 0.15,
|
|
286
|
-
falPricing: {
|
|
287
|
-
endpointId: "fal-ai/nano-banana-pro",
|
|
288
|
-
unitPrice: 0.15,
|
|
289
|
-
unit: "images",
|
|
290
|
-
currency: "USD",
|
|
291
|
-
estimatedCostPerImageUsd: 0.15,
|
|
292
|
-
source: "fal-pricing-api",
|
|
293
|
-
checkedAt: FAL_PRICING_CHECKED_AT
|
|
294
|
-
},
|
|
295
298
|
benchmark: {
|
|
296
|
-
|
|
297
|
-
|
|
299
|
+
artificialAnalysis: {
|
|
300
|
+
editing: { elo: 1241, pricePer1k: 134, rank: 4, winRate: 0.65 },
|
|
301
|
+
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
302
|
+
sourceUrls: AA_IMAGE_SOURCES,
|
|
303
|
+
textToImage: { elo: 1220, pricePer1k: 134, rank: 5, winRate: 0.66 }
|
|
304
|
+
},
|
|
298
305
|
speed: {
|
|
299
306
|
medianSeconds: 19.2,
|
|
300
307
|
p95Seconds: 30.3,
|
|
301
308
|
source: "artificial-analysis-models"
|
|
302
309
|
},
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
310
|
+
tiers: { price: "ultra", quality: "frontier", speed: "balanced" },
|
|
311
|
+
useCase: "Premium Gemini image generation and multi-reference edits"
|
|
312
|
+
},
|
|
313
|
+
editEndpoint: "fal-ai/nano-banana-pro/edit",
|
|
314
|
+
endpoint: "fal-ai/nano-banana-pro",
|
|
315
|
+
falPricing: {
|
|
316
|
+
checkedAt: FAL_PRICING_CHECKED_AT,
|
|
317
|
+
currency: "USD",
|
|
318
|
+
endpointId: "fal-ai/nano-banana-pro",
|
|
319
|
+
estimatedCostPerImageUsd: 0.15,
|
|
320
|
+
source: "fal-pricing-api",
|
|
321
|
+
unit: "images",
|
|
322
|
+
unitPrice: 0.15
|
|
309
323
|
},
|
|
324
|
+
maxReferenceImages: 14,
|
|
325
|
+
name: "Nano Banana Pro",
|
|
326
|
+
pricePerImageUsd: 0.15,
|
|
327
|
+
pricing: "$0.15",
|
|
310
328
|
sizeMode: "aspect_ratio",
|
|
311
329
|
supportsAspect: true,
|
|
312
|
-
supportsResolution: true,
|
|
313
330
|
supportsEdit: true,
|
|
331
|
+
supportsGoogleSearch: true,
|
|
332
|
+
supportsLimitGenerations: true,
|
|
314
333
|
supportsNumImages: true,
|
|
315
334
|
supportsOutputFormat: true,
|
|
335
|
+
supportsResolution: true,
|
|
316
336
|
supportsSafetyTolerance: true,
|
|
317
337
|
supportsSeed: true,
|
|
318
|
-
supportsWebSearch: true,
|
|
319
|
-
supportsGoogleSearch: true,
|
|
320
|
-
supportsLimitGenerations: true,
|
|
321
338
|
supportsSyncMode: true,
|
|
322
|
-
|
|
339
|
+
supportsWebSearch: true,
|
|
340
|
+
type: "generation"
|
|
323
341
|
},
|
|
324
342
|
gemini: {
|
|
325
|
-
name: "Gemini 2.5 Flash",
|
|
326
|
-
endpoint: "fal-ai/gemini-25-flash-image",
|
|
327
343
|
editEndpoint: "fal-ai/gemini-25-flash-image/edit",
|
|
328
|
-
|
|
329
|
-
pricing: "$0.04",
|
|
330
|
-
pricePerImageUsd: 0.0398,
|
|
344
|
+
endpoint: "fal-ai/gemini-25-flash-image",
|
|
331
345
|
falPricing: {
|
|
332
|
-
|
|
333
|
-
unitPrice: 0.0398,
|
|
334
|
-
unit: "images",
|
|
346
|
+
checkedAt: FAL_PRICING_CHECKED_AT,
|
|
335
347
|
currency: "USD",
|
|
348
|
+
endpointId: "fal-ai/gemini-25-flash-image",
|
|
336
349
|
estimatedCostPerImageUsd: 0.0398,
|
|
337
350
|
source: "fal-pricing-api",
|
|
338
|
-
|
|
351
|
+
unit: "images",
|
|
352
|
+
unitPrice: 0.0398
|
|
339
353
|
},
|
|
354
|
+
maxReferenceImages: 4,
|
|
355
|
+
name: "Gemini 2.5 Flash",
|
|
356
|
+
pricePerImageUsd: 0.0398,
|
|
357
|
+
pricing: "$0.04",
|
|
340
358
|
sizeMode: "aspect_ratio",
|
|
341
359
|
supportsAspect: true,
|
|
342
|
-
supportsResolution: false,
|
|
343
360
|
supportsEdit: true,
|
|
344
361
|
supportsNumImages: true,
|
|
345
362
|
supportsOutputFormat: true,
|
|
363
|
+
supportsResolution: false,
|
|
346
364
|
supportsSafetyTolerance: true,
|
|
347
365
|
supportsSeed: true,
|
|
348
366
|
supportsSyncMode: true,
|
|
349
|
-
|
|
367
|
+
type: "generation"
|
|
350
368
|
},
|
|
351
369
|
gemini3: {
|
|
352
|
-
name: "Gemini 3 Pro",
|
|
353
|
-
endpoint: "fal-ai/gemini-3-pro-image-preview",
|
|
354
370
|
editEndpoint: "fal-ai/gemini-3-pro-image-preview/edit",
|
|
355
|
-
|
|
356
|
-
pricing: "$0.15",
|
|
357
|
-
pricePerImageUsd: 0.15,
|
|
371
|
+
endpoint: "fal-ai/gemini-3-pro-image-preview",
|
|
358
372
|
falPricing: {
|
|
359
|
-
|
|
360
|
-
unitPrice: 0.15,
|
|
361
|
-
unit: "images",
|
|
373
|
+
checkedAt: FAL_PRICING_CHECKED_AT,
|
|
362
374
|
currency: "USD",
|
|
375
|
+
endpointId: "fal-ai/gemini-3-pro-image-preview",
|
|
363
376
|
estimatedCostPerImageUsd: 0.15,
|
|
364
377
|
source: "fal-pricing-api",
|
|
365
|
-
|
|
378
|
+
unit: "images",
|
|
379
|
+
unitPrice: 0.15
|
|
366
380
|
},
|
|
381
|
+
maxReferenceImages: 4,
|
|
382
|
+
name: "Gemini 3 Pro",
|
|
383
|
+
pricePerImageUsd: 0.15,
|
|
384
|
+
pricing: "$0.15",
|
|
367
385
|
sizeMode: "aspect_ratio",
|
|
368
386
|
supportsAspect: true,
|
|
369
|
-
supportsResolution: true,
|
|
370
387
|
supportsEdit: true,
|
|
371
388
|
supportsNumImages: true,
|
|
372
389
|
supportsOutputFormat: true,
|
|
390
|
+
supportsResolution: true,
|
|
373
391
|
supportsSafetyTolerance: true,
|
|
374
392
|
supportsSeed: true,
|
|
375
|
-
supportsWebSearch: true,
|
|
376
393
|
supportsSyncMode: true,
|
|
377
|
-
|
|
394
|
+
supportsWebSearch: true,
|
|
395
|
+
type: "generation"
|
|
378
396
|
},
|
|
379
397
|
seedream4: {
|
|
380
|
-
name: "Seedream 4.0",
|
|
381
|
-
endpoint: "fal-ai/bytedance/seedream/v4/text-to-image",
|
|
382
|
-
editEndpoint: "fal-ai/bytedance/seedream/v4/edit",
|
|
383
|
-
type: "generation",
|
|
384
|
-
pricing: "$0.03",
|
|
385
|
-
pricePerImageUsd: 0.03,
|
|
386
|
-
falPricing: {
|
|
387
|
-
endpointId: "fal-ai/bytedance/seedream/v4/text-to-image",
|
|
388
|
-
unitPrice: 0.03,
|
|
389
|
-
unit: "images",
|
|
390
|
-
currency: "USD",
|
|
391
|
-
estimatedCostPerImageUsd: 0.03,
|
|
392
|
-
source: "fal-pricing-api",
|
|
393
|
-
checkedAt: FAL_PRICING_CHECKED_AT
|
|
394
|
-
},
|
|
395
398
|
benchmark: {
|
|
396
|
-
|
|
397
|
-
|
|
399
|
+
artificialAnalysis: {
|
|
400
|
+
editing: { elo: 1184, pricePer1k: 30, rank: 16, winRate: 0.61 },
|
|
401
|
+
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
402
|
+
sourceUrls: AA_IMAGE_SOURCES,
|
|
403
|
+
textToImage: { elo: 1198, pricePer1k: 30, rank: 6, winRate: 0.59 }
|
|
404
|
+
},
|
|
398
405
|
speed: {
|
|
399
406
|
medianSeconds: 14.3,
|
|
400
407
|
p95Seconds: 21,
|
|
401
408
|
source: "artificial-analysis-models"
|
|
402
409
|
},
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
410
|
+
tiers: { price: "budget", quality: "best", speed: "balanced" },
|
|
411
|
+
useCase: "High-ranked budget generation and large multi-reference edits"
|
|
412
|
+
},
|
|
413
|
+
editEndpoint: "fal-ai/bytedance/seedream/v4/edit",
|
|
414
|
+
endpoint: "fal-ai/bytedance/seedream/v4/text-to-image",
|
|
415
|
+
falPricing: {
|
|
416
|
+
checkedAt: FAL_PRICING_CHECKED_AT,
|
|
417
|
+
currency: "USD",
|
|
418
|
+
endpointId: "fal-ai/bytedance/seedream/v4/text-to-image",
|
|
419
|
+
estimatedCostPerImageUsd: 0.03,
|
|
420
|
+
source: "fal-pricing-api",
|
|
421
|
+
unit: "images",
|
|
422
|
+
unitPrice: 0.03
|
|
409
423
|
},
|
|
424
|
+
maxReferenceImages: 10,
|
|
425
|
+
name: "Seedream 4.0",
|
|
426
|
+
pricePerImageUsd: 0.03,
|
|
427
|
+
pricing: "$0.03",
|
|
410
428
|
sizeMode: "image_size_enum",
|
|
411
429
|
supportsAspect: true,
|
|
412
|
-
supportsResolution: false,
|
|
413
430
|
supportsEdit: true,
|
|
414
431
|
supportsNumImages: true,
|
|
432
|
+
supportsResolution: false,
|
|
415
433
|
supportsSeed: true,
|
|
416
434
|
supportsSyncMode: true,
|
|
417
|
-
|
|
435
|
+
type: "generation"
|
|
418
436
|
},
|
|
419
437
|
seedream45: {
|
|
420
|
-
name: "Seedream 4.5",
|
|
421
|
-
endpoint: "fal-ai/bytedance/seedream/v4.5/text-to-image",
|
|
422
|
-
editEndpoint: "fal-ai/bytedance/seedream/v4.5/edit",
|
|
423
|
-
type: "generation",
|
|
424
|
-
pricing: "$0.04",
|
|
425
|
-
pricePerImageUsd: 0.04,
|
|
426
|
-
falPricing: {
|
|
427
|
-
endpointId: "fal-ai/bytedance/seedream/v4.5/text-to-image",
|
|
428
|
-
unitPrice: 0.04,
|
|
429
|
-
unit: "images",
|
|
430
|
-
currency: "USD",
|
|
431
|
-
estimatedCostPerImageUsd: 0.04,
|
|
432
|
-
source: "fal-pricing-api",
|
|
433
|
-
checkedAt: FAL_PRICING_CHECKED_AT
|
|
434
|
-
},
|
|
435
438
|
benchmark: {
|
|
436
|
-
|
|
437
|
-
|
|
439
|
+
artificialAnalysis: {
|
|
440
|
+
editing: { elo: 1184, pricePer1k: 40, rank: 17, winRate: 0.58 },
|
|
441
|
+
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
442
|
+
sourceUrls: AA_IMAGE_SOURCES,
|
|
443
|
+
textToImage: { elo: 1167, pricePer1k: 40, rank: 17, winRate: 0.63 }
|
|
444
|
+
},
|
|
438
445
|
speed: {
|
|
439
446
|
medianSeconds: 18.2,
|
|
440
447
|
p95Seconds: 43.3,
|
|
441
448
|
source: "artificial-analysis-models"
|
|
442
449
|
},
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
450
|
+
tiers: { price: "standard", quality: "better", speed: "balanced" },
|
|
451
|
+
useCase: "Cheap current Seedream model with good animation/art scores"
|
|
452
|
+
},
|
|
453
|
+
editEndpoint: "fal-ai/bytedance/seedream/v4.5/edit",
|
|
454
|
+
endpoint: "fal-ai/bytedance/seedream/v4.5/text-to-image",
|
|
455
|
+
falPricing: {
|
|
456
|
+
checkedAt: FAL_PRICING_CHECKED_AT,
|
|
457
|
+
currency: "USD",
|
|
458
|
+
endpointId: "fal-ai/bytedance/seedream/v4.5/text-to-image",
|
|
459
|
+
estimatedCostPerImageUsd: 0.04,
|
|
460
|
+
source: "fal-pricing-api",
|
|
461
|
+
unit: "images",
|
|
462
|
+
unitPrice: 0.04
|
|
449
463
|
},
|
|
464
|
+
maxReferenceImages: 10,
|
|
465
|
+
name: "Seedream 4.5",
|
|
466
|
+
pricePerImageUsd: 0.04,
|
|
467
|
+
pricing: "$0.04",
|
|
450
468
|
sizeMode: "image_size_enum",
|
|
451
469
|
supportsAspect: true,
|
|
452
|
-
supportsResolution: false,
|
|
453
470
|
supportsEdit: true,
|
|
454
471
|
supportsNumImages: true,
|
|
472
|
+
supportsResolution: false,
|
|
455
473
|
supportsSeed: true,
|
|
456
474
|
supportsSyncMode: true,
|
|
457
|
-
|
|
475
|
+
type: "generation"
|
|
458
476
|
},
|
|
459
477
|
seedream5: {
|
|
460
478
|
name: "Seedream 5.0 Pro",
|
|
@@ -465,13 +483,13 @@ var MODELS = {
|
|
|
465
483
|
pricing: "$0.0675 (\u22641536\xB2) / $0.135 (\u22642048\xB2)",
|
|
466
484
|
pricePerImageUsd: 0.0675,
|
|
467
485
|
falPricing: {
|
|
468
|
-
|
|
469
|
-
unitPrice: 0.0675,
|
|
470
|
-
unit: "images",
|
|
486
|
+
checkedAt: FAL_PRICING_CHECKED_JUL_2026,
|
|
471
487
|
currency: "USD",
|
|
488
|
+
endpointId: "bytedance/seedream/v5/pro/text-to-image",
|
|
472
489
|
estimatedCostPerImageUsd: 0.0675,
|
|
473
490
|
source: "fal-pricing-api",
|
|
474
|
-
|
|
491
|
+
unit: "images",
|
|
492
|
+
unitPrice: 0.0675
|
|
475
493
|
},
|
|
476
494
|
sizeMode: "image_size_enum",
|
|
477
495
|
supportsAspect: true,
|
|
@@ -491,13 +509,13 @@ var MODELS = {
|
|
|
491
509
|
pricing: "$0.035",
|
|
492
510
|
pricePerImageUsd: 0.035,
|
|
493
511
|
falPricing: {
|
|
494
|
-
|
|
495
|
-
unitPrice: 0.035,
|
|
496
|
-
unit: "images",
|
|
512
|
+
checkedAt: FAL_PRICING_CHECKED_JUL_2026,
|
|
497
513
|
currency: "USD",
|
|
514
|
+
endpointId: "fal-ai/bytedance/seedream/v5/lite/text-to-image",
|
|
498
515
|
estimatedCostPerImageUsd: 0.035,
|
|
499
516
|
source: "fal-pricing-api",
|
|
500
|
-
|
|
517
|
+
unit: "images",
|
|
518
|
+
unitPrice: 0.035
|
|
501
519
|
},
|
|
502
520
|
sizeMode: "image_size_enum",
|
|
503
521
|
supportsAspect: true,
|
|
@@ -509,334 +527,334 @@ var MODELS = {
|
|
|
509
527
|
maxReferenceImages: 10
|
|
510
528
|
},
|
|
511
529
|
"flux2-max": {
|
|
512
|
-
name: "FLUX.2 Max",
|
|
513
|
-
endpoint: "fal-ai/flux-2-max",
|
|
514
|
-
editEndpoint: "fal-ai/flux-2-max/edit",
|
|
515
|
-
type: "generation",
|
|
516
|
-
pricing: "$0.07/MP",
|
|
517
|
-
pricePerImageUsd: 0.07,
|
|
518
|
-
falPricing: {
|
|
519
|
-
endpointId: "fal-ai/flux-2-max",
|
|
520
|
-
unitPrice: 0.07,
|
|
521
|
-
unit: "megapixels",
|
|
522
|
-
currency: "USD",
|
|
523
|
-
estimatedCostPerImageUsd: 0.07,
|
|
524
|
-
source: "fal-pricing-api",
|
|
525
|
-
checkedAt: FAL_PRICING_CHECKED_AT
|
|
526
|
-
},
|
|
527
530
|
benchmark: {
|
|
528
|
-
|
|
529
|
-
|
|
531
|
+
artificialAnalysis: {
|
|
532
|
+
editing: { elo: 1206, pricePer1k: 140, rank: 10, winRate: 0.6 },
|
|
533
|
+
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
534
|
+
sourceUrls: AA_IMAGE_SOURCES,
|
|
535
|
+
textToImage: { elo: 1197, pricePer1k: 70, rank: 8, winRate: 0.67 }
|
|
536
|
+
},
|
|
530
537
|
speed: {
|
|
531
538
|
medianSeconds: 31.6,
|
|
532
539
|
p95Seconds: 41,
|
|
533
540
|
source: "artificial-analysis-models"
|
|
534
541
|
},
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
542
|
+
tiers: { price: "premium", quality: "best", speed: "slow" },
|
|
543
|
+
useCase: "Best FLUX quality and high-end editing"
|
|
544
|
+
},
|
|
545
|
+
editEndpoint: "fal-ai/flux-2-max/edit",
|
|
546
|
+
endpoint: "fal-ai/flux-2-max",
|
|
547
|
+
falPricing: {
|
|
548
|
+
checkedAt: FAL_PRICING_CHECKED_AT,
|
|
549
|
+
currency: "USD",
|
|
550
|
+
endpointId: "fal-ai/flux-2-max",
|
|
551
|
+
estimatedCostPerImageUsd: 0.07,
|
|
552
|
+
source: "fal-pricing-api",
|
|
553
|
+
unit: "megapixels",
|
|
554
|
+
unitPrice: 0.07
|
|
541
555
|
},
|
|
556
|
+
maxReferenceImages: 10,
|
|
557
|
+
name: "FLUX.2 Max",
|
|
558
|
+
pricePerImageUsd: 0.07,
|
|
559
|
+
pricing: "$0.07/MP",
|
|
542
560
|
sizeMode: "image_size_enum",
|
|
543
561
|
supportsAspect: true,
|
|
544
|
-
supportsResolution: false,
|
|
545
562
|
supportsEdit: true,
|
|
546
563
|
supportsNumImages: false,
|
|
547
564
|
supportsOutputFormat: true,
|
|
548
|
-
|
|
565
|
+
supportsResolution: false,
|
|
549
566
|
supportsSafetyChecker: true,
|
|
567
|
+
supportsSafetyTolerance: true,
|
|
550
568
|
supportsSeed: true,
|
|
551
569
|
supportsSyncMode: true,
|
|
552
|
-
|
|
570
|
+
type: "generation"
|
|
553
571
|
},
|
|
554
572
|
"flux2-pro": {
|
|
555
|
-
name: "FLUX.2 Pro",
|
|
556
|
-
endpoint: "fal-ai/flux-2-pro",
|
|
557
|
-
editEndpoint: "fal-ai/flux-2-pro/edit",
|
|
558
|
-
type: "generation",
|
|
559
|
-
pricing: "$0.03/MP",
|
|
560
|
-
pricePerImageUsd: 0.03,
|
|
561
|
-
falPricing: {
|
|
562
|
-
endpointId: "fal-ai/flux-2-pro",
|
|
563
|
-
unitPrice: 0.03,
|
|
564
|
-
unit: "processed megapixels",
|
|
565
|
-
currency: "USD",
|
|
566
|
-
estimatedCostPerImageUsd: 0.03,
|
|
567
|
-
source: "fal-pricing-api",
|
|
568
|
-
checkedAt: FAL_PRICING_CHECKED_AT
|
|
569
|
-
},
|
|
570
573
|
benchmark: {
|
|
571
|
-
|
|
572
|
-
|
|
574
|
+
artificialAnalysis: {
|
|
575
|
+
editing: { elo: 1170, pricePer1k: 30, rank: 21 },
|
|
576
|
+
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
577
|
+
sourceUrls: AA_IMAGE_SOURCES,
|
|
578
|
+
textToImage: { elo: 1186, pricePer1k: 30, rank: 10, winRate: 0.62 }
|
|
579
|
+
},
|
|
573
580
|
speed: {
|
|
574
581
|
medianSeconds: 16.1,
|
|
575
582
|
p95Seconds: 23.9,
|
|
576
583
|
source: "artificial-analysis-models"
|
|
577
584
|
},
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
585
|
+
tiers: { price: "budget", quality: "best", speed: "balanced" },
|
|
586
|
+
useCase: "Production FLUX quality at a low per-megapixel price"
|
|
587
|
+
},
|
|
588
|
+
editEndpoint: "fal-ai/flux-2-pro/edit",
|
|
589
|
+
endpoint: "fal-ai/flux-2-pro",
|
|
590
|
+
falPricing: {
|
|
591
|
+
checkedAt: FAL_PRICING_CHECKED_AT,
|
|
592
|
+
currency: "USD",
|
|
593
|
+
endpointId: "fal-ai/flux-2-pro",
|
|
594
|
+
estimatedCostPerImageUsd: 0.03,
|
|
595
|
+
source: "fal-pricing-api",
|
|
596
|
+
unit: "processed megapixels",
|
|
597
|
+
unitPrice: 0.03
|
|
584
598
|
},
|
|
599
|
+
maxReferenceImages: 10,
|
|
600
|
+
name: "FLUX.2 Pro",
|
|
601
|
+
pricePerImageUsd: 0.03,
|
|
602
|
+
pricing: "$0.03/MP",
|
|
585
603
|
sizeMode: "image_size_enum",
|
|
586
604
|
supportsAspect: true,
|
|
587
|
-
supportsResolution: false,
|
|
588
605
|
supportsEdit: true,
|
|
589
606
|
supportsNumImages: false,
|
|
590
607
|
supportsOutputFormat: true,
|
|
591
|
-
|
|
608
|
+
supportsResolution: false,
|
|
592
609
|
supportsSafetyChecker: true,
|
|
610
|
+
supportsSafetyTolerance: true,
|
|
593
611
|
supportsSeed: true,
|
|
594
612
|
supportsSyncMode: true,
|
|
595
|
-
|
|
613
|
+
type: "generation"
|
|
596
614
|
},
|
|
597
615
|
"flux2-flex": {
|
|
598
|
-
name: "FLUX.2 Flex",
|
|
599
|
-
endpoint: "fal-ai/flux-2-flex",
|
|
600
|
-
editEndpoint: "fal-ai/flux-2-flex/edit",
|
|
601
|
-
type: "generation",
|
|
602
|
-
pricing: "$0.05/MP",
|
|
603
|
-
pricePerImageUsd: 0.05,
|
|
604
|
-
falPricing: {
|
|
605
|
-
endpointId: "fal-ai/flux-2-flex",
|
|
606
|
-
unitPrice: 0.05,
|
|
607
|
-
unit: "processed megapixels",
|
|
608
|
-
currency: "USD",
|
|
609
|
-
estimatedCostPerImageUsd: 0.05,
|
|
610
|
-
source: "fal-pricing-api",
|
|
611
|
-
checkedAt: FAL_PRICING_CHECKED_AT
|
|
612
|
-
},
|
|
613
616
|
benchmark: {
|
|
614
|
-
|
|
615
|
-
|
|
617
|
+
artificialAnalysis: {
|
|
618
|
+
editing: { elo: 1161, pricePer1k: 60, rank: 22 },
|
|
619
|
+
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
620
|
+
sourceUrls: AA_IMAGE_SOURCES,
|
|
621
|
+
textToImage: { elo: 1182, pricePer1k: 60, rank: 13, winRate: 0.61 }
|
|
622
|
+
},
|
|
616
623
|
speed: {
|
|
617
624
|
medianSeconds: 15.3,
|
|
618
625
|
p95Seconds: 22.2,
|
|
619
626
|
source: "artificial-analysis-models"
|
|
620
627
|
},
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
628
|
+
tiers: { price: "standard", quality: "best", speed: "balanced" },
|
|
629
|
+
useCase: "FLUX quality with guidance and step controls"
|
|
630
|
+
},
|
|
631
|
+
editEndpoint: "fal-ai/flux-2-flex/edit",
|
|
632
|
+
endpoint: "fal-ai/flux-2-flex",
|
|
633
|
+
falPricing: {
|
|
634
|
+
checkedAt: FAL_PRICING_CHECKED_AT,
|
|
635
|
+
currency: "USD",
|
|
636
|
+
endpointId: "fal-ai/flux-2-flex",
|
|
637
|
+
estimatedCostPerImageUsd: 0.05,
|
|
638
|
+
source: "fal-pricing-api",
|
|
639
|
+
unit: "processed megapixels",
|
|
640
|
+
unitPrice: 0.05
|
|
627
641
|
},
|
|
642
|
+
maxReferenceImages: 10,
|
|
643
|
+
name: "FLUX.2 Flex",
|
|
644
|
+
pricePerImageUsd: 0.05,
|
|
645
|
+
pricing: "$0.05/MP",
|
|
628
646
|
sizeMode: "image_size_enum",
|
|
647
|
+
supportedOutputFormats: ["jpeg", "png"],
|
|
629
648
|
supportsAspect: true,
|
|
630
|
-
supportsResolution: false,
|
|
631
649
|
supportsEdit: true,
|
|
650
|
+
supportsGuidanceScale: true,
|
|
651
|
+
supportsInferenceSteps: true,
|
|
632
652
|
supportsNumImages: false,
|
|
633
653
|
supportsOutputFormat: true,
|
|
634
|
-
|
|
635
|
-
supportsSafetyTolerance: true,
|
|
654
|
+
supportsResolution: false,
|
|
636
655
|
supportsSafetyChecker: true,
|
|
656
|
+
supportsSafetyTolerance: true,
|
|
637
657
|
supportsSeed: true,
|
|
638
|
-
supportsGuidanceScale: true,
|
|
639
|
-
supportsInferenceSteps: true,
|
|
640
658
|
supportsSyncMode: true,
|
|
641
|
-
|
|
659
|
+
type: "generation"
|
|
642
660
|
},
|
|
643
661
|
"flux2-dev": {
|
|
644
|
-
name: "FLUX.2 [dev]",
|
|
645
|
-
endpoint: "fal-ai/flux-2",
|
|
646
|
-
editEndpoint: "fal-ai/flux-2/edit",
|
|
647
|
-
type: "generation",
|
|
648
|
-
pricing: "$0.00167/sec",
|
|
649
|
-
pricePerImageUsd: 0.012,
|
|
650
|
-
falPricing: {
|
|
651
|
-
endpointId: "fal-ai/flux-2",
|
|
652
|
-
unitPrice: 167e-5,
|
|
653
|
-
unit: "compute seconds",
|
|
654
|
-
currency: "USD",
|
|
655
|
-
estimatedCostPerImageUsd: 0.012,
|
|
656
|
-
source: "fal-pricing-api",
|
|
657
|
-
checkedAt: FAL_PRICING_CHECKED_AT
|
|
658
|
-
},
|
|
659
662
|
benchmark: {
|
|
660
|
-
|
|
661
|
-
|
|
663
|
+
artificialAnalysis: {
|
|
664
|
+
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
665
|
+
sourceUrls: AA_IMAGE_SOURCES,
|
|
666
|
+
textToImage: { elo: 1160, pricePer1k: 12, rank: 19, winRate: 0.57 }
|
|
667
|
+
},
|
|
662
668
|
speed: {
|
|
663
669
|
medianSeconds: 4.6,
|
|
664
670
|
p95Seconds: 69.6,
|
|
665
671
|
source: "artificial-analysis-models"
|
|
666
672
|
},
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
673
|
+
tiers: { price: "variable", quality: "better", speed: "fast" },
|
|
674
|
+
useCase: "Open FLUX.2 quality with low average cost"
|
|
675
|
+
},
|
|
676
|
+
editEndpoint: "fal-ai/flux-2/edit",
|
|
677
|
+
endpoint: "fal-ai/flux-2",
|
|
678
|
+
falPricing: {
|
|
679
|
+
checkedAt: FAL_PRICING_CHECKED_AT,
|
|
680
|
+
currency: "USD",
|
|
681
|
+
endpointId: "fal-ai/flux-2",
|
|
682
|
+
estimatedCostPerImageUsd: 0.012,
|
|
683
|
+
source: "fal-pricing-api",
|
|
684
|
+
unit: "compute seconds",
|
|
685
|
+
unitPrice: 167e-5
|
|
672
686
|
},
|
|
687
|
+
maxReferenceImages: 10,
|
|
688
|
+
name: "FLUX.2 [dev]",
|
|
689
|
+
pricePerImageUsd: 0.012,
|
|
690
|
+
pricing: "$0.00167/sec",
|
|
673
691
|
sizeMode: "image_size_enum",
|
|
674
692
|
supportsAspect: true,
|
|
675
|
-
supportsResolution: false,
|
|
676
693
|
supportsEdit: true,
|
|
694
|
+
supportsGuidanceScale: true,
|
|
695
|
+
supportsInferenceSteps: true,
|
|
677
696
|
supportsNumImages: true,
|
|
678
697
|
supportsOutputFormat: true,
|
|
679
|
-
|
|
698
|
+
supportsResolution: false,
|
|
680
699
|
supportsSafetyChecker: true,
|
|
700
|
+
supportsSafetyTolerance: true,
|
|
681
701
|
supportsSeed: true,
|
|
682
|
-
supportsGuidanceScale: true,
|
|
683
|
-
supportsInferenceSteps: true,
|
|
684
702
|
supportsSyncMode: true,
|
|
685
|
-
|
|
703
|
+
type: "generation"
|
|
686
704
|
},
|
|
687
705
|
"flux2-turbo": {
|
|
688
|
-
name: "FLUX.2 Turbo",
|
|
689
706
|
endpoint: "fal-ai/flux-2/turbo",
|
|
690
|
-
type: "generation",
|
|
691
|
-
pricing: "$0.008/MP",
|
|
692
|
-
pricePerImageUsd: 8e-3,
|
|
693
707
|
falPricing: {
|
|
694
|
-
|
|
695
|
-
unitPrice: 8e-3,
|
|
696
|
-
unit: "megapixels",
|
|
708
|
+
checkedAt: FAL_PRICING_CHECKED_JUL_2026,
|
|
697
709
|
currency: "USD",
|
|
710
|
+
endpointId: "fal-ai/flux-2/turbo",
|
|
698
711
|
estimatedCostPerImageUsd: 8e-3,
|
|
699
712
|
source: "fal-pricing-api",
|
|
700
|
-
|
|
713
|
+
unit: "megapixels",
|
|
714
|
+
unitPrice: 8e-3
|
|
701
715
|
},
|
|
716
|
+
name: "FLUX.2 Turbo",
|
|
717
|
+
pricePerImageUsd: 8e-3,
|
|
718
|
+
pricing: "$0.008/MP",
|
|
702
719
|
sizeMode: "image_size_enum",
|
|
703
720
|
supportsAspect: true,
|
|
704
|
-
supportsResolution: false,
|
|
705
721
|
supportsEdit: false,
|
|
722
|
+
supportsGuidanceScale: true,
|
|
706
723
|
supportsNumImages: true,
|
|
707
724
|
supportsOutputFormat: true,
|
|
725
|
+
supportsResolution: false,
|
|
708
726
|
supportsSafetyChecker: true,
|
|
709
727
|
supportsSeed: true,
|
|
710
|
-
|
|
711
|
-
|
|
728
|
+
supportsSyncMode: true,
|
|
729
|
+
type: "generation"
|
|
712
730
|
},
|
|
713
731
|
flux: {
|
|
714
|
-
name: "FLUX Pro Ultra",
|
|
715
732
|
endpoint: "fal-ai/flux-pro/v1.1-ultra",
|
|
716
|
-
type: "generation",
|
|
717
|
-
pricing: "$0.06",
|
|
718
|
-
pricePerImageUsd: 0.06,
|
|
719
733
|
falPricing: {
|
|
720
|
-
|
|
721
|
-
unitPrice: 0.06,
|
|
722
|
-
unit: "images",
|
|
734
|
+
checkedAt: FAL_PRICING_CHECKED_AT,
|
|
723
735
|
currency: "USD",
|
|
736
|
+
endpointId: "fal-ai/flux-pro/v1.1-ultra",
|
|
724
737
|
estimatedCostPerImageUsd: 0.06,
|
|
725
738
|
source: "fal-pricing-api",
|
|
726
|
-
|
|
739
|
+
unit: "images",
|
|
740
|
+
unitPrice: 0.06
|
|
727
741
|
},
|
|
742
|
+
maxReferenceImages: 1,
|
|
743
|
+
name: "FLUX Pro Ultra",
|
|
744
|
+
pricePerImageUsd: 0.06,
|
|
745
|
+
pricing: "$0.06",
|
|
728
746
|
sizeMode: "aspect_ratio",
|
|
729
747
|
supportsAspect: true,
|
|
730
|
-
supportsResolution: false,
|
|
731
748
|
supportsEdit: true,
|
|
749
|
+
supportsEnhancePrompt: true,
|
|
750
|
+
supportsImagePromptStrength: true,
|
|
732
751
|
supportsNumImages: true,
|
|
733
752
|
supportsOutputFormat: true,
|
|
734
753
|
supportsRaw: true,
|
|
735
|
-
|
|
754
|
+
supportsResolution: false,
|
|
736
755
|
supportsSafetyTolerance: true,
|
|
737
756
|
supportsSeed: true,
|
|
738
|
-
supportsImagePromptStrength: true,
|
|
739
757
|
supportsSyncMode: true,
|
|
740
|
-
|
|
758
|
+
type: "generation"
|
|
741
759
|
},
|
|
742
760
|
"flux-fast": {
|
|
743
|
-
name: "FLUX Schnell",
|
|
744
761
|
endpoint: "fal-ai/flux/schnell",
|
|
745
|
-
type: "generation",
|
|
746
|
-
pricing: "$0.003",
|
|
747
|
-
pricePerImageUsd: 3e-3,
|
|
748
762
|
falPricing: {
|
|
749
|
-
|
|
750
|
-
unitPrice: 3e-3,
|
|
751
|
-
unit: "megapixels",
|
|
763
|
+
checkedAt: FAL_PRICING_CHECKED_AT,
|
|
752
764
|
currency: "USD",
|
|
765
|
+
endpointId: "fal-ai/flux/schnell",
|
|
753
766
|
estimatedCostPerImageUsd: 3e-3,
|
|
754
767
|
source: "fal-pricing-api",
|
|
755
|
-
|
|
768
|
+
unit: "megapixels",
|
|
769
|
+
unitPrice: 3e-3
|
|
756
770
|
},
|
|
771
|
+
name: "FLUX Schnell",
|
|
772
|
+
pricePerImageUsd: 3e-3,
|
|
773
|
+
pricing: "$0.003",
|
|
757
774
|
sizeMode: "image_size_enum",
|
|
758
775
|
supportsAspect: true,
|
|
759
|
-
supportsResolution: false,
|
|
760
776
|
supportsEdit: false,
|
|
761
|
-
supportsNumImages: true,
|
|
762
|
-
supportsOutputFormat: true,
|
|
763
777
|
supportsGuidanceScale: true,
|
|
764
778
|
supportsInferenceSteps: true,
|
|
779
|
+
supportsNumImages: true,
|
|
780
|
+
supportsOutputFormat: true,
|
|
781
|
+
supportsResolution: false,
|
|
765
782
|
supportsSeed: true,
|
|
766
|
-
supportsSyncMode: true
|
|
783
|
+
supportsSyncMode: true,
|
|
784
|
+
type: "generation"
|
|
767
785
|
},
|
|
768
786
|
recraft: {
|
|
769
|
-
name: "Recraft V3",
|
|
770
787
|
endpoint: "fal-ai/recraft-v3",
|
|
771
|
-
type: "generation",
|
|
772
|
-
pricing: "$0.04",
|
|
773
|
-
pricePerImageUsd: 0.04,
|
|
774
788
|
falPricing: {
|
|
775
|
-
|
|
776
|
-
unitPrice: 0.04,
|
|
777
|
-
unit: "images",
|
|
789
|
+
checkedAt: FAL_PRICING_CHECKED_AT,
|
|
778
790
|
currency: "USD",
|
|
791
|
+
endpointId: "fal-ai/recraft-v3",
|
|
779
792
|
estimatedCostPerImageUsd: 0.04,
|
|
780
793
|
source: "fal-pricing-api",
|
|
781
|
-
|
|
794
|
+
unit: "images",
|
|
795
|
+
unitPrice: 0.04
|
|
782
796
|
},
|
|
797
|
+
name: "Recraft V3",
|
|
798
|
+
pricePerImageUsd: 0.04,
|
|
799
|
+
pricing: "$0.04",
|
|
783
800
|
sizeMode: "image_size_enum",
|
|
784
801
|
supportsAspect: true,
|
|
785
|
-
supportsResolution: false,
|
|
786
802
|
supportsEdit: false,
|
|
787
803
|
supportsNumImages: false,
|
|
804
|
+
supportsResolution: false,
|
|
788
805
|
supportsStyle: true,
|
|
789
|
-
supportsSyncMode: true
|
|
806
|
+
supportsSyncMode: true,
|
|
807
|
+
type: "generation"
|
|
790
808
|
},
|
|
791
809
|
recraft4: {
|
|
792
|
-
name: "Recraft V4",
|
|
793
810
|
endpoint: "fal-ai/recraft/v4/text-to-image",
|
|
794
|
-
type: "generation",
|
|
795
|
-
pricing: "$0.04",
|
|
796
|
-
pricePerImageUsd: 0.04,
|
|
797
811
|
falPricing: {
|
|
798
|
-
|
|
799
|
-
unitPrice: 0.04,
|
|
800
|
-
unit: "images",
|
|
812
|
+
checkedAt: FAL_PRICING_CHECKED_JUL_2026,
|
|
801
813
|
currency: "USD",
|
|
814
|
+
endpointId: "fal-ai/recraft/v4/text-to-image",
|
|
802
815
|
estimatedCostPerImageUsd: 0.04,
|
|
803
816
|
source: "fal-pricing-api",
|
|
804
|
-
|
|
817
|
+
unit: "images",
|
|
818
|
+
unitPrice: 0.04
|
|
805
819
|
},
|
|
820
|
+
name: "Recraft V4",
|
|
821
|
+
pricePerImageUsd: 0.04,
|
|
822
|
+
pricing: "$0.04",
|
|
806
823
|
sizeMode: "image_size_enum",
|
|
807
824
|
supportsAspect: true,
|
|
808
|
-
supportsResolution: false,
|
|
809
825
|
supportsEdit: false,
|
|
810
826
|
supportsNumImages: false,
|
|
827
|
+
supportsResolution: false,
|
|
811
828
|
supportsStyle: true,
|
|
812
|
-
supportsSyncMode: true
|
|
829
|
+
supportsSyncMode: true,
|
|
830
|
+
type: "generation"
|
|
813
831
|
},
|
|
814
832
|
ideogram: {
|
|
815
|
-
name: "Ideogram V3",
|
|
816
833
|
endpoint: "fal-ai/ideogram/v3",
|
|
817
|
-
type: "generation",
|
|
818
|
-
pricing: "$0.03",
|
|
819
|
-
pricePerImageUsd: 0.03,
|
|
820
834
|
falPricing: {
|
|
821
|
-
|
|
822
|
-
unitPrice: 0.03,
|
|
823
|
-
unit: "images",
|
|
835
|
+
checkedAt: FAL_PRICING_CHECKED_AT,
|
|
824
836
|
currency: "USD",
|
|
837
|
+
endpointId: "fal-ai/ideogram/v3",
|
|
825
838
|
estimatedCostPerImageUsd: 0.03,
|
|
826
839
|
source: "fal-pricing-api",
|
|
827
|
-
|
|
840
|
+
unit: "images",
|
|
841
|
+
unitPrice: 0.03
|
|
828
842
|
},
|
|
843
|
+
name: "Ideogram V3",
|
|
844
|
+
pricePerImageUsd: 0.03,
|
|
845
|
+
pricing: "$0.03",
|
|
829
846
|
sizeMode: "image_size_enum",
|
|
830
847
|
supportsAspect: true,
|
|
831
|
-
supportsResolution: false,
|
|
832
848
|
supportsEdit: false,
|
|
833
|
-
supportsNumImages: true,
|
|
834
849
|
supportsExpandPrompt: true,
|
|
835
850
|
supportsNegativePrompt: true,
|
|
851
|
+
supportsNumImages: true,
|
|
836
852
|
supportsRenderingSpeed: true,
|
|
853
|
+
supportsResolution: false,
|
|
837
854
|
supportsSeed: true,
|
|
838
855
|
supportsStyle: true,
|
|
839
|
-
supportsSyncMode: true
|
|
856
|
+
supportsSyncMode: true,
|
|
857
|
+
type: "generation"
|
|
840
858
|
},
|
|
841
859
|
ideogram4: {
|
|
842
860
|
name: "Ideogram V4",
|
|
@@ -848,13 +866,13 @@ var MODELS = {
|
|
|
848
866
|
pricing: "$0.03",
|
|
849
867
|
pricePerImageUsd: 0.03,
|
|
850
868
|
falPricing: {
|
|
851
|
-
|
|
852
|
-
unitPrice: 0.03,
|
|
853
|
-
unit: "megapixels",
|
|
869
|
+
checkedAt: FAL_PRICING_CHECKED_JUL_2026,
|
|
854
870
|
currency: "USD",
|
|
871
|
+
endpointId: "ideogram/v4",
|
|
855
872
|
estimatedCostPerImageUsd: 0.03,
|
|
856
873
|
source: "fal-pricing-api",
|
|
857
|
-
|
|
874
|
+
unit: "megapixels",
|
|
875
|
+
unitPrice: 0.03
|
|
858
876
|
},
|
|
859
877
|
sizeMode: "image_size_enum",
|
|
860
878
|
supportsAspect: true,
|
|
@@ -869,135 +887,135 @@ var MODELS = {
|
|
|
869
887
|
supportsSyncMode: true
|
|
870
888
|
},
|
|
871
889
|
"grok-image": {
|
|
872
|
-
name: "Grok Imagine Image",
|
|
873
|
-
endpoint: "xai/grok-imagine-image",
|
|
874
|
-
editEndpoint: "xai/grok-imagine-image/edit",
|
|
875
|
-
type: "generation",
|
|
876
|
-
pricing: "$0.02",
|
|
877
|
-
pricePerImageUsd: 0.02,
|
|
878
|
-
falPricing: {
|
|
879
|
-
endpointId: "xai/grok-imagine-image",
|
|
880
|
-
unitPrice: 0.02,
|
|
881
|
-
unit: "images",
|
|
882
|
-
currency: "USD",
|
|
883
|
-
estimatedCostPerImageUsd: 0.02,
|
|
884
|
-
source: "fal-pricing-api",
|
|
885
|
-
checkedAt: FAL_PRICING_CHECKED_AT
|
|
886
|
-
},
|
|
887
890
|
benchmark: {
|
|
888
|
-
|
|
889
|
-
|
|
891
|
+
artificialAnalysis: {
|
|
892
|
+
editing: { elo: 1213, pricePer1k: 20, rank: 7, winRate: 0.6 },
|
|
893
|
+
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
894
|
+
sourceUrls: AA_IMAGE_SOURCES,
|
|
895
|
+
textToImage: { elo: 1182, pricePer1k: 20, rank: 12, winRate: 0.6 }
|
|
896
|
+
},
|
|
890
897
|
speed: {
|
|
891
898
|
medianSeconds: 5.1,
|
|
892
899
|
p95Seconds: 6.5,
|
|
893
900
|
source: "artificial-analysis-models"
|
|
894
901
|
},
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
sourceUrls: AA_IMAGE_SOURCES,
|
|
898
|
-
textToImage: { rank: 12, elo: 1182, winRate: 0.6, pricePer1k: 20 },
|
|
899
|
-
editing: { rank: 7, elo: 1213, winRate: 0.6, pricePer1k: 20 }
|
|
900
|
-
}
|
|
902
|
+
tiers: { price: "budget", quality: "best", speed: "fast" },
|
|
903
|
+
useCase: "Very fast, cheap generation and edits"
|
|
901
904
|
},
|
|
905
|
+
editEndpoint: "xai/grok-imagine-image/edit",
|
|
906
|
+
endpoint: "xai/grok-imagine-image",
|
|
907
|
+
falPricing: {
|
|
908
|
+
checkedAt: FAL_PRICING_CHECKED_AT,
|
|
909
|
+
currency: "USD",
|
|
910
|
+
endpointId: "xai/grok-imagine-image",
|
|
911
|
+
estimatedCostPerImageUsd: 0.02,
|
|
912
|
+
source: "fal-pricing-api",
|
|
913
|
+
unit: "images",
|
|
914
|
+
unitPrice: 0.02
|
|
915
|
+
},
|
|
916
|
+
maxReferenceImages: 4,
|
|
917
|
+
name: "Grok Imagine Image",
|
|
918
|
+
pricePerImageUsd: 0.02,
|
|
919
|
+
pricing: "$0.02",
|
|
902
920
|
sizeMode: "aspect_ratio",
|
|
903
921
|
supportsAspect: true,
|
|
904
|
-
supportsResolution: true,
|
|
905
922
|
supportsEdit: true,
|
|
906
923
|
supportsNumImages: true,
|
|
907
924
|
supportsOutputFormat: true,
|
|
925
|
+
supportsResolution: true,
|
|
908
926
|
supportsSyncMode: true,
|
|
909
|
-
|
|
927
|
+
type: "generation"
|
|
910
928
|
},
|
|
911
929
|
qwen: {
|
|
912
|
-
name: "Qwen Image",
|
|
913
|
-
endpoint: "fal-ai/qwen-image",
|
|
914
|
-
type: "generation",
|
|
915
|
-
pricing: "$0.02/MP",
|
|
916
|
-
pricePerImageUsd: 0.02,
|
|
917
|
-
falPricing: {
|
|
918
|
-
endpointId: "fal-ai/qwen-image",
|
|
919
|
-
unitPrice: 0.02,
|
|
920
|
-
unit: "megapixels",
|
|
921
|
-
currency: "USD",
|
|
922
|
-
estimatedCostPerImageUsd: 0.02,
|
|
923
|
-
source: "fal-pricing-api",
|
|
924
|
-
checkedAt: FAL_PRICING_CHECKED_AT
|
|
925
|
-
},
|
|
926
930
|
benchmark: {
|
|
927
|
-
|
|
928
|
-
|
|
931
|
+
artificialAnalysis: {
|
|
932
|
+
snapshotDate: AA_IMAGE_LEADERBOARD_SNAPSHOT,
|
|
933
|
+
sourceUrls: AA_IMAGE_SOURCES,
|
|
934
|
+
textToImage: { elo: 1158, pricePer1k: 20, rank: 20, winRate: 0.6 }
|
|
935
|
+
},
|
|
929
936
|
speed: {
|
|
930
937
|
medianSeconds: 23.3,
|
|
931
938
|
p95Seconds: 491,
|
|
932
939
|
source: "artificial-analysis-models"
|
|
933
940
|
},
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
941
|
+
tiers: { price: "budget", quality: "better", speed: "slow" },
|
|
942
|
+
useCase: "Low-cost open-weight text and design generation"
|
|
943
|
+
},
|
|
944
|
+
endpoint: "fal-ai/qwen-image",
|
|
945
|
+
falPricing: {
|
|
946
|
+
checkedAt: FAL_PRICING_CHECKED_AT,
|
|
947
|
+
currency: "USD",
|
|
948
|
+
endpointId: "fal-ai/qwen-image",
|
|
949
|
+
estimatedCostPerImageUsd: 0.02,
|
|
950
|
+
source: "fal-pricing-api",
|
|
951
|
+
unit: "megapixels",
|
|
952
|
+
unitPrice: 0.02
|
|
939
953
|
},
|
|
954
|
+
name: "Qwen Image",
|
|
955
|
+
pricePerImageUsd: 0.02,
|
|
956
|
+
pricing: "$0.02/MP",
|
|
940
957
|
sizeMode: "image_size_enum",
|
|
941
958
|
supportsAspect: true,
|
|
942
|
-
supportsResolution: false,
|
|
943
959
|
supportsEdit: false,
|
|
944
960
|
supportsNumImages: true,
|
|
945
961
|
supportsOutputFormat: true,
|
|
962
|
+
supportsResolution: false,
|
|
946
963
|
supportsSeed: true,
|
|
947
|
-
supportsSyncMode: true
|
|
964
|
+
supportsSyncMode: true,
|
|
965
|
+
type: "generation"
|
|
948
966
|
},
|
|
949
967
|
// ─── Video Models ─────────────────────────────────────────────
|
|
950
968
|
kling: {
|
|
951
|
-
name: "Kling v3 Pro",
|
|
952
969
|
endpoint: "fal-ai/kling-video/v3/pro/image-to-video",
|
|
953
|
-
|
|
970
|
+
name: "Kling v3 Pro",
|
|
954
971
|
pricing: "$0.11/sec",
|
|
955
972
|
sizeMode: "none",
|
|
956
973
|
supportsAspect: false,
|
|
957
|
-
supportsResolution: false,
|
|
958
974
|
supportsEdit: false,
|
|
959
|
-
supportsNumImages: false
|
|
975
|
+
supportsNumImages: false,
|
|
976
|
+
supportsResolution: false,
|
|
977
|
+
type: "video"
|
|
960
978
|
},
|
|
961
979
|
// ─── Utility Models ───────────────────────────────────────────
|
|
962
980
|
clarity: {
|
|
963
|
-
name: "Clarity Upscaler",
|
|
964
981
|
endpoint: "fal-ai/clarity-upscaler",
|
|
965
|
-
|
|
982
|
+
name: "Clarity Upscaler",
|
|
966
983
|
pricing: "$0.03/MP",
|
|
967
984
|
supportsAspect: false,
|
|
968
|
-
supportsResolution: false,
|
|
969
985
|
supportsEdit: false,
|
|
970
|
-
supportsNumImages: false
|
|
986
|
+
supportsNumImages: false,
|
|
987
|
+
supportsResolution: false,
|
|
988
|
+
type: "utility"
|
|
971
989
|
},
|
|
972
990
|
crystal: {
|
|
973
|
-
name: "Crystal Upscaler",
|
|
974
991
|
endpoint: "clarityai/crystal-upscaler",
|
|
975
|
-
|
|
992
|
+
name: "Crystal Upscaler",
|
|
976
993
|
pricing: "$0.02",
|
|
977
994
|
supportsAspect: false,
|
|
978
|
-
supportsResolution: false,
|
|
979
995
|
supportsEdit: false,
|
|
980
|
-
supportsNumImages: false
|
|
996
|
+
supportsNumImages: false,
|
|
997
|
+
supportsResolution: false,
|
|
998
|
+
type: "utility"
|
|
981
999
|
},
|
|
982
1000
|
rmbg: {
|
|
983
|
-
name: "BiRefNet (Background Removal)",
|
|
984
1001
|
endpoint: "fal-ai/birefnet",
|
|
985
|
-
|
|
1002
|
+
name: "BiRefNet (Background Removal)",
|
|
986
1003
|
pricing: "$0.02",
|
|
987
1004
|
supportsAspect: false,
|
|
988
|
-
supportsResolution: false,
|
|
989
1005
|
supportsEdit: false,
|
|
990
|
-
supportsNumImages: false
|
|
1006
|
+
supportsNumImages: false,
|
|
1007
|
+
supportsResolution: false,
|
|
1008
|
+
type: "utility"
|
|
991
1009
|
},
|
|
992
1010
|
bria: {
|
|
993
|
-
name: "Bria RMBG 2.0",
|
|
994
1011
|
endpoint: "fal-ai/bria/background/remove",
|
|
995
|
-
|
|
1012
|
+
name: "Bria RMBG 2.0",
|
|
996
1013
|
pricing: "$0.02",
|
|
997
1014
|
supportsAspect: false,
|
|
998
|
-
supportsResolution: false,
|
|
999
1015
|
supportsEdit: false,
|
|
1000
|
-
supportsNumImages: false
|
|
1016
|
+
supportsNumImages: false,
|
|
1017
|
+
supportsResolution: false,
|
|
1018
|
+
type: "utility"
|
|
1001
1019
|
}
|
|
1002
1020
|
};
|
|
1003
1021
|
var GENERATION_MODELS = [
|
|
@@ -1026,7 +1044,7 @@ var GENERATION_MODELS = [
|
|
|
1026
1044
|
"qwen"
|
|
1027
1045
|
];
|
|
1028
1046
|
var EDIT_CAPABLE_MODELS = GENERATION_MODELS.filter(
|
|
1029
|
-
(id) => MODELS[id]?.supportsEdit
|
|
1047
|
+
(id) => MODELS[id]?.supportsEdit === true
|
|
1030
1048
|
);
|
|
1031
1049
|
var UTILITY_MODELS = ["clarity", "crystal", "rmbg", "bria"];
|
|
1032
1050
|
var VIDEO_MODELS = ["kling"];
|
|
@@ -1092,30 +1110,40 @@ function estimateCost(model, resolution, numImages = 1) {
|
|
|
1092
1110
|
return configuredPrice * numImages;
|
|
1093
1111
|
}
|
|
1094
1112
|
switch (model) {
|
|
1095
|
-
case "gpt2":
|
|
1113
|
+
case "gpt2": {
|
|
1096
1114
|
return 0.211 * numImages;
|
|
1097
|
-
|
|
1115
|
+
}
|
|
1116
|
+
case "gpt": {
|
|
1098
1117
|
return 0.133 * numImages;
|
|
1118
|
+
}
|
|
1099
1119
|
case "banana":
|
|
1100
|
-
case "gemini3":
|
|
1120
|
+
case "gemini3": {
|
|
1101
1121
|
return (resolution === "4K" ? 0.3 : 0.15) * numImages;
|
|
1102
|
-
|
|
1122
|
+
}
|
|
1123
|
+
case "gemini": {
|
|
1103
1124
|
return 0.039 * numImages;
|
|
1125
|
+
}
|
|
1104
1126
|
case "flux":
|
|
1105
|
-
case "ideogram":
|
|
1127
|
+
case "ideogram": {
|
|
1106
1128
|
return 0.06 * numImages;
|
|
1107
|
-
|
|
1129
|
+
}
|
|
1130
|
+
case "recraft": {
|
|
1108
1131
|
return 0.04 * numImages;
|
|
1109
|
-
|
|
1132
|
+
}
|
|
1133
|
+
case "flux-fast": {
|
|
1110
1134
|
return 3e-3 * numImages;
|
|
1111
|
-
|
|
1135
|
+
}
|
|
1136
|
+
case "clarity": {
|
|
1112
1137
|
return 0.03 * numImages;
|
|
1138
|
+
}
|
|
1113
1139
|
case "crystal":
|
|
1114
1140
|
case "rmbg":
|
|
1115
|
-
case "bria":
|
|
1141
|
+
case "bria": {
|
|
1116
1142
|
return 0.02 * numImages;
|
|
1117
|
-
|
|
1143
|
+
}
|
|
1144
|
+
default: {
|
|
1118
1145
|
return 0.1 * numImages;
|
|
1146
|
+
}
|
|
1119
1147
|
}
|
|
1120
1148
|
}
|
|
1121
1149
|
function estimateVideoCost(durationSeconds = 5, generateAudio = true) {
|
|
@@ -1124,7 +1152,7 @@ function estimateVideoCost(durationSeconds = 5, generateAudio = true) {
|
|
|
1124
1152
|
}
|
|
1125
1153
|
|
|
1126
1154
|
// src/creative.ts
|
|
1127
|
-
var CONTROL_CHAR_REGEX = /[\
|
|
1155
|
+
var CONTROL_CHAR_REGEX = /[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F]/g;
|
|
1128
1156
|
var CreativeOptionError = class extends Error {
|
|
1129
1157
|
availableIds;
|
|
1130
1158
|
code = "INVALID_OPTION";
|
|
@@ -1151,28 +1179,20 @@ var CREATIVE_FIELDS = [
|
|
|
1151
1179
|
"motion"
|
|
1152
1180
|
];
|
|
1153
1181
|
var CREATIVE_TAXONOMY = {
|
|
1154
|
-
|
|
1155
|
-
{
|
|
1156
|
-
clause: "cinematic scene",
|
|
1157
|
-
description: "Frames the prompt as a cinematic still or scene.",
|
|
1158
|
-
id: "cinematic",
|
|
1159
|
-
label: "Cinematic"
|
|
1160
|
-
}
|
|
1161
|
-
],
|
|
1162
|
-
shot: [
|
|
1182
|
+
camera: [
|
|
1163
1183
|
{
|
|
1164
|
-
clause: "
|
|
1165
|
-
description: "
|
|
1166
|
-
id: "
|
|
1167
|
-
label: "
|
|
1184
|
+
clause: "macro product photography with crisp surface detail",
|
|
1185
|
+
description: "Product-oriented macro camera language for close detail.",
|
|
1186
|
+
id: "macro-product",
|
|
1187
|
+
label: "Macro product"
|
|
1168
1188
|
}
|
|
1169
1189
|
],
|
|
1170
|
-
|
|
1190
|
+
color: [
|
|
1171
1191
|
{
|
|
1172
|
-
clause: "
|
|
1173
|
-
description: "
|
|
1174
|
-
id: "
|
|
1175
|
-
label: "
|
|
1192
|
+
clause: "monochrome palette with tonal contrast",
|
|
1193
|
+
description: "Black-and-white or single-channel tonal treatment.",
|
|
1194
|
+
id: "monochrome",
|
|
1195
|
+
label: "Monochrome"
|
|
1176
1196
|
}
|
|
1177
1197
|
],
|
|
1178
1198
|
genre: [
|
|
@@ -1183,20 +1203,12 @@ var CREATIVE_TAXONOMY = {
|
|
|
1183
1203
|
label: "Film noir"
|
|
1184
1204
|
}
|
|
1185
1205
|
],
|
|
1186
|
-
|
|
1187
|
-
{
|
|
1188
|
-
clause: "macro product photography with crisp surface detail",
|
|
1189
|
-
description: "Product-oriented macro camera language for close detail.",
|
|
1190
|
-
id: "macro-product",
|
|
1191
|
-
label: "Macro product"
|
|
1192
|
-
}
|
|
1193
|
-
],
|
|
1194
|
-
color: [
|
|
1206
|
+
lighting: [
|
|
1195
1207
|
{
|
|
1196
|
-
clause: "
|
|
1197
|
-
description: "
|
|
1198
|
-
id: "
|
|
1199
|
-
label: "
|
|
1208
|
+
clause: "rim lighting with defined edge highlights",
|
|
1209
|
+
description: "Back or side light that separates the subject edge.",
|
|
1210
|
+
id: "rim",
|
|
1211
|
+
label: "Rim"
|
|
1200
1212
|
}
|
|
1201
1213
|
],
|
|
1202
1214
|
material: [
|
|
@@ -1214,10 +1226,26 @@ var CREATIVE_TAXONOMY = {
|
|
|
1214
1226
|
id: "still",
|
|
1215
1227
|
label: "Still"
|
|
1216
1228
|
}
|
|
1229
|
+
],
|
|
1230
|
+
recipe: [
|
|
1231
|
+
{
|
|
1232
|
+
clause: "cinematic scene",
|
|
1233
|
+
description: "Frames the prompt as a cinematic still or scene.",
|
|
1234
|
+
id: "cinematic",
|
|
1235
|
+
label: "Cinematic"
|
|
1236
|
+
}
|
|
1237
|
+
],
|
|
1238
|
+
shot: [
|
|
1239
|
+
{
|
|
1240
|
+
clause: "close-up composition with controlled depth of field",
|
|
1241
|
+
description: "Tight framing that emphasizes subject detail.",
|
|
1242
|
+
id: "close-up",
|
|
1243
|
+
label: "Close-up"
|
|
1244
|
+
}
|
|
1217
1245
|
]
|
|
1218
1246
|
};
|
|
1219
1247
|
function sanitizePrompt(prompt) {
|
|
1220
|
-
return prompt.replace(CONTROL_CHAR_REGEX, "").
|
|
1248
|
+
return prompt.replace(CONTROL_CHAR_REGEX, "").replaceAll("\r\n", "\n").trim();
|
|
1221
1249
|
}
|
|
1222
1250
|
function enrichPrompt(options) {
|
|
1223
1251
|
const basePrompt = sanitizePrompt(options.prompt);
|
|
@@ -1225,7 +1253,7 @@ function enrichPrompt(options) {
|
|
|
1225
1253
|
const selected = {};
|
|
1226
1254
|
for (const field of CREATIVE_FIELDS) {
|
|
1227
1255
|
const optionId = options.creative?.[field];
|
|
1228
|
-
if (
|
|
1256
|
+
if (optionId === void 0 || optionId === "") {
|
|
1229
1257
|
continue;
|
|
1230
1258
|
}
|
|
1231
1259
|
const option = CREATIVE_TAXONOMY[field].find(
|
|
@@ -1300,11 +1328,11 @@ function normalizeImageSize(imageSize, sizeMode) {
|
|
|
1300
1328
|
if (FAL_IMAGE_SIZE_PRESETS.includes(imageSize)) {
|
|
1301
1329
|
return imageSize;
|
|
1302
1330
|
}
|
|
1303
|
-
const match =
|
|
1331
|
+
const match = /^(\d+)x(\d+)$/.exec(imageSize);
|
|
1304
1332
|
if (match) {
|
|
1305
1333
|
const width = Number(match[1]);
|
|
1306
1334
|
const height = Number(match[2]);
|
|
1307
|
-
return {
|
|
1335
|
+
return { height, width };
|
|
1308
1336
|
}
|
|
1309
1337
|
throw new Error(
|
|
1310
1338
|
`fal image_size must be one of ${FAL_IMAGE_SIZE_PRESETS.join(", ")} or WIDTHxHEIGHT`
|
|
@@ -1314,12 +1342,12 @@ function unsupported(config, option) {
|
|
|
1314
1342
|
throw new Error(`${config.name} does not support ${option}`);
|
|
1315
1343
|
}
|
|
1316
1344
|
function validateGenerateOptions(options, config, sizeMode, hasEditImages) {
|
|
1317
|
-
if (options.editImageUrls
|
|
1345
|
+
if (options.editImageUrls !== void 0 && options.editImageUrls.length > 0 && config.maxReferenceImages !== void 0 && options.editImageUrls.length > config.maxReferenceImages) {
|
|
1318
1346
|
throw new Error(
|
|
1319
1347
|
`${config.name} supports at most ${config.maxReferenceImages} reference images`
|
|
1320
1348
|
);
|
|
1321
1349
|
}
|
|
1322
|
-
if (options.editImageUrls
|
|
1350
|
+
if (options.editImageUrls !== void 0 && options.editImageUrls.length > 0 && !config.supportsEdit) {
|
|
1323
1351
|
unsupported(config, "image editing");
|
|
1324
1352
|
}
|
|
1325
1353
|
if (options.aspect !== void 0 && sizeMode === "none") {
|
|
@@ -1331,10 +1359,10 @@ function validateGenerateOptions(options, config, sizeMode, hasEditImages) {
|
|
|
1331
1359
|
if (options.numImages !== void 0 && options.numImages !== 1 && !config.supportsNumImages) {
|
|
1332
1360
|
unsupported(config, "numImages");
|
|
1333
1361
|
}
|
|
1334
|
-
if (options.background !== void 0 &&
|
|
1362
|
+
if (options.background !== void 0 && config.supportsBackground !== true) {
|
|
1335
1363
|
unsupported(config, "background");
|
|
1336
1364
|
}
|
|
1337
|
-
if (options.transparent && !(config.supportsBackground || config.supportsOutputFormat)) {
|
|
1365
|
+
if (options.transparent === true && !(config.supportsBackground === true || config.supportsOutputFormat === true)) {
|
|
1338
1366
|
unsupported(config, "transparent output");
|
|
1339
1367
|
}
|
|
1340
1368
|
if (options.inputFidelity !== void 0) {
|
|
@@ -1348,70 +1376,70 @@ function validateGenerateOptions(options, config, sizeMode, hasEditImages) {
|
|
|
1348
1376
|
if (options.imageSize !== void 0 && sizeMode !== "gpt_size" && sizeMode !== "image_size_enum") {
|
|
1349
1377
|
unsupported(config, "imageSize");
|
|
1350
1378
|
}
|
|
1351
|
-
if (options.imagePromptStrength !== void 0 &&
|
|
1379
|
+
if (options.imagePromptStrength !== void 0 && config.supportsImagePromptStrength !== true) {
|
|
1352
1380
|
unsupported(config, "imagePromptStrength");
|
|
1353
1381
|
}
|
|
1354
1382
|
if (options.imagePromptStrength !== void 0 && !hasEditImages) {
|
|
1355
1383
|
throw new Error("imagePromptStrength requires editImageUrls");
|
|
1356
1384
|
}
|
|
1357
|
-
if (options.maskImageUrl !== void 0 &&
|
|
1385
|
+
if (options.maskImageUrl !== void 0 && config.supportsMaskImage !== true) {
|
|
1358
1386
|
unsupported(config, "maskImageUrl");
|
|
1359
1387
|
}
|
|
1360
1388
|
if (options.maskImageUrl !== void 0 && !hasEditImages) {
|
|
1361
1389
|
throw new Error("maskImageUrl requires editImageUrls");
|
|
1362
1390
|
}
|
|
1363
|
-
if (options.seed !== void 0 &&
|
|
1391
|
+
if (options.seed !== void 0 && config.supportsSeed !== true) {
|
|
1364
1392
|
unsupported(config, "seed");
|
|
1365
1393
|
}
|
|
1366
|
-
if (options.outputFormat !== void 0 &&
|
|
1394
|
+
if (options.outputFormat !== void 0 && config.supportsOutputFormat !== true) {
|
|
1367
1395
|
unsupported(config, "outputFormat");
|
|
1368
1396
|
}
|
|
1369
|
-
if (options.quality !== void 0 &&
|
|
1397
|
+
if (options.quality !== void 0 && config.supportsQuality !== true) {
|
|
1370
1398
|
unsupported(config, "quality");
|
|
1371
1399
|
}
|
|
1372
|
-
if (options.negativePrompt !== void 0 &&
|
|
1400
|
+
if (options.negativePrompt !== void 0 && config.supportsNegativePrompt !== true) {
|
|
1373
1401
|
unsupported(config, "negativePrompt");
|
|
1374
1402
|
}
|
|
1375
|
-
if (options.style !== void 0 &&
|
|
1403
|
+
if (options.style !== void 0 && config.supportsStyle !== true) {
|
|
1376
1404
|
unsupported(config, "style");
|
|
1377
1405
|
}
|
|
1378
|
-
if (options.syncMode !== void 0 &&
|
|
1406
|
+
if (options.syncMode !== void 0 && config.supportsSyncMode !== true) {
|
|
1379
1407
|
unsupported(config, "syncMode");
|
|
1380
1408
|
}
|
|
1381
|
-
if (options.renderingSpeed !== void 0 &&
|
|
1409
|
+
if (options.renderingSpeed !== void 0 && config.supportsRenderingSpeed !== true) {
|
|
1382
1410
|
unsupported(config, "renderingSpeed");
|
|
1383
1411
|
}
|
|
1384
|
-
if (options.guidanceScale !== void 0 &&
|
|
1412
|
+
if (options.guidanceScale !== void 0 && config.supportsGuidanceScale !== true) {
|
|
1385
1413
|
unsupported(config, "guidanceScale");
|
|
1386
1414
|
}
|
|
1387
|
-
if (options.numInferenceSteps !== void 0 &&
|
|
1415
|
+
if (options.numInferenceSteps !== void 0 && config.supportsInferenceSteps !== true) {
|
|
1388
1416
|
unsupported(config, "numInferenceSteps");
|
|
1389
1417
|
}
|
|
1390
|
-
if (options.raw !== void 0 &&
|
|
1418
|
+
if (options.raw !== void 0 && config.supportsRaw !== true) {
|
|
1391
1419
|
unsupported(config, "raw");
|
|
1392
1420
|
}
|
|
1393
|
-
if (options.enhancePrompt !== void 0 &&
|
|
1421
|
+
if (options.enhancePrompt !== void 0 && config.supportsEnhancePrompt !== true) {
|
|
1394
1422
|
unsupported(config, "enhancePrompt");
|
|
1395
1423
|
}
|
|
1396
|
-
if (options.safetyTolerance !== void 0 &&
|
|
1424
|
+
if (options.safetyTolerance !== void 0 && config.supportsSafetyTolerance !== true) {
|
|
1397
1425
|
unsupported(config, "safetyTolerance");
|
|
1398
1426
|
}
|
|
1399
|
-
if (options.enableWebSearch !== void 0 &&
|
|
1427
|
+
if (options.enableWebSearch !== void 0 && config.supportsWebSearch !== true) {
|
|
1400
1428
|
unsupported(config, "enableWebSearch");
|
|
1401
1429
|
}
|
|
1402
|
-
if (options.enableGoogleSearch !== void 0 &&
|
|
1430
|
+
if (options.enableGoogleSearch !== void 0 && config.supportsGoogleSearch !== true) {
|
|
1403
1431
|
unsupported(config, "enableGoogleSearch");
|
|
1404
1432
|
}
|
|
1405
|
-
if (options.enableSafetyChecker !== void 0 &&
|
|
1433
|
+
if (options.enableSafetyChecker !== void 0 && config.supportsSafetyChecker !== true) {
|
|
1406
1434
|
unsupported(config, "enableSafetyChecker");
|
|
1407
1435
|
}
|
|
1408
|
-
if (options.limitGenerations !== void 0 &&
|
|
1436
|
+
if (options.limitGenerations !== void 0 && config.supportsLimitGenerations !== true) {
|
|
1409
1437
|
unsupported(config, "limitGenerations");
|
|
1410
1438
|
}
|
|
1411
|
-
if (options.thinkingLevel !== void 0 &&
|
|
1439
|
+
if (options.thinkingLevel !== void 0 && config.supportsThinkingLevel !== true) {
|
|
1412
1440
|
unsupported(config, "thinkingLevel");
|
|
1413
1441
|
}
|
|
1414
|
-
if (options.expandPrompt !== void 0 &&
|
|
1442
|
+
if (options.expandPrompt !== void 0 && config.supportsExpandPrompt !== true) {
|
|
1415
1443
|
unsupported(config, "expandPrompt");
|
|
1416
1444
|
}
|
|
1417
1445
|
}
|
|
@@ -1453,8 +1481,8 @@ function buildGenerateBody(options) {
|
|
|
1453
1481
|
if (!config) {
|
|
1454
1482
|
throw new Error(`Unknown model: ${model}`);
|
|
1455
1483
|
}
|
|
1456
|
-
let endpoint = config
|
|
1457
|
-
const enrichedPrompt = creative ? enrichPrompt({
|
|
1484
|
+
let { endpoint } = config;
|
|
1485
|
+
const enrichedPrompt = creative ? enrichPrompt({ creative, prompt }).prompt : prompt;
|
|
1458
1486
|
const body = { prompt: enrichedPrompt };
|
|
1459
1487
|
const hasEditImages = Boolean(editImageUrls?.length);
|
|
1460
1488
|
const editImages = editImageUrls ?? [];
|
|
@@ -1463,13 +1491,15 @@ function buildGenerateBody(options) {
|
|
|
1463
1491
|
validateGenerateOptions(options, config, sizeMode, hasEditImages);
|
|
1464
1492
|
const normalizedImageSize = normalizeImageSize(imageSize, sizeMode);
|
|
1465
1493
|
switch (sizeMode) {
|
|
1466
|
-
case "gpt_size":
|
|
1494
|
+
case "gpt_size": {
|
|
1467
1495
|
body.image_size = normalizedImageSize ?? (hasEditImages && !explicitAspect ? "auto" : aspectToGptSize(aspect));
|
|
1468
1496
|
break;
|
|
1469
|
-
|
|
1497
|
+
}
|
|
1498
|
+
case "image_size_enum": {
|
|
1470
1499
|
body.image_size = normalizedImageSize ?? aspectToFalImageSize(aspect);
|
|
1471
1500
|
break;
|
|
1472
|
-
|
|
1501
|
+
}
|
|
1502
|
+
case "aspect_ratio": {
|
|
1473
1503
|
if (config.supportsAspect) {
|
|
1474
1504
|
body.aspect_ratio = aspect;
|
|
1475
1505
|
}
|
|
@@ -1477,26 +1507,30 @@ function buildGenerateBody(options) {
|
|
|
1477
1507
|
body.resolution = model === "grok-image" ? resolution.toLowerCase() : resolution;
|
|
1478
1508
|
}
|
|
1479
1509
|
break;
|
|
1510
|
+
}
|
|
1511
|
+
case "none": {
|
|
1512
|
+
break;
|
|
1513
|
+
}
|
|
1480
1514
|
}
|
|
1481
|
-
if (config.supportsQuality) {
|
|
1515
|
+
if (config.supportsQuality === true) {
|
|
1482
1516
|
body.quality = quality ?? "high";
|
|
1483
1517
|
}
|
|
1484
|
-
if (config.supportsBackground && background) {
|
|
1518
|
+
if (config.supportsBackground === true && background) {
|
|
1485
1519
|
body.background = background;
|
|
1486
1520
|
}
|
|
1487
|
-
if (config.supportsBackground && transparent) {
|
|
1521
|
+
if (config.supportsBackground === true && transparent === true) {
|
|
1488
1522
|
body.background = "transparent";
|
|
1489
1523
|
}
|
|
1490
|
-
if (transparent && config.supportsOutputFormat) {
|
|
1524
|
+
if (transparent === true && config.supportsOutputFormat === true) {
|
|
1491
1525
|
body.output_format = "png";
|
|
1492
1526
|
}
|
|
1493
|
-
if (syncMode !== void 0 && config.supportsSyncMode) {
|
|
1527
|
+
if (syncMode !== void 0 && config.supportsSyncMode === true) {
|
|
1494
1528
|
body.sync_mode = syncMode;
|
|
1495
1529
|
}
|
|
1496
|
-
if (seed !== void 0 && config.supportsSeed) {
|
|
1530
|
+
if (seed !== void 0 && config.supportsSeed === true) {
|
|
1497
1531
|
body.seed = seed;
|
|
1498
1532
|
}
|
|
1499
|
-
if (outputFormat && config.supportsOutputFormat &&
|
|
1533
|
+
if (outputFormat && config.supportsOutputFormat === true && transparent !== true) {
|
|
1500
1534
|
if (config.supportedOutputFormats && !config.supportedOutputFormats.includes(outputFormat)) {
|
|
1501
1535
|
throw new Error(
|
|
1502
1536
|
`${config.name} supports output formats: ${config.supportedOutputFormats.join(", ")}`
|
|
@@ -1504,62 +1538,78 @@ function buildGenerateBody(options) {
|
|
|
1504
1538
|
}
|
|
1505
1539
|
body.output_format = outputFormat;
|
|
1506
1540
|
}
|
|
1507
|
-
if (config.supportsRaw && raw !== void 0) {
|
|
1541
|
+
if (config.supportsRaw === true && raw !== void 0) {
|
|
1508
1542
|
body.raw = raw;
|
|
1509
1543
|
}
|
|
1510
|
-
if (config.supportsEnhancePrompt && enhancePrompt !== void 0) {
|
|
1544
|
+
if (config.supportsEnhancePrompt === true && enhancePrompt !== void 0) {
|
|
1511
1545
|
body.enhance_prompt = enhancePrompt;
|
|
1512
1546
|
}
|
|
1513
|
-
if (config.supportsImagePromptStrength && imagePromptStrength !== void 0) {
|
|
1547
|
+
if (config.supportsImagePromptStrength === true && imagePromptStrength !== void 0) {
|
|
1514
1548
|
body.image_prompt_strength = imagePromptStrength;
|
|
1515
1549
|
}
|
|
1516
1550
|
if (model === "flux") {
|
|
1517
|
-
if (safetyTolerance
|
|
1551
|
+
if (safetyTolerance !== void 0 && safetyTolerance !== "") {
|
|
1552
|
+
body.safety_tolerance = safetyTolerance;
|
|
1553
|
+
}
|
|
1518
1554
|
}
|
|
1519
|
-
if (config.supportsGuidanceScale && guidanceScale !== void 0) {
|
|
1555
|
+
if (config.supportsGuidanceScale === true && guidanceScale !== void 0) {
|
|
1520
1556
|
body.guidance_scale = guidanceScale;
|
|
1521
1557
|
}
|
|
1522
|
-
if (config.supportsInferenceSteps && numInferenceSteps !== void 0) {
|
|
1558
|
+
if (config.supportsInferenceSteps === true && numInferenceSteps !== void 0) {
|
|
1523
1559
|
body.num_inference_steps = numInferenceSteps;
|
|
1524
1560
|
}
|
|
1525
|
-
if (config.supportsSafetyTolerance) {
|
|
1526
|
-
if (safetyTolerance
|
|
1561
|
+
if (config.supportsSafetyTolerance === true) {
|
|
1562
|
+
if (safetyTolerance !== void 0 && safetyTolerance !== "") {
|
|
1563
|
+
body.safety_tolerance = safetyTolerance;
|
|
1564
|
+
}
|
|
1527
1565
|
}
|
|
1528
|
-
if (config.supportsWebSearch) {
|
|
1529
|
-
if (enableWebSearch !== void 0)
|
|
1566
|
+
if (config.supportsWebSearch === true) {
|
|
1567
|
+
if (enableWebSearch !== void 0) {
|
|
1568
|
+
body.enable_web_search = enableWebSearch;
|
|
1569
|
+
}
|
|
1530
1570
|
}
|
|
1531
|
-
if (config.supportsGoogleSearch) {
|
|
1571
|
+
if (config.supportsGoogleSearch === true) {
|
|
1532
1572
|
if (enableGoogleSearch !== void 0) {
|
|
1533
1573
|
body.enable_google_search = enableGoogleSearch;
|
|
1534
1574
|
}
|
|
1535
1575
|
}
|
|
1536
|
-
if (config.supportsSafetyChecker) {
|
|
1576
|
+
if (config.supportsSafetyChecker === true) {
|
|
1537
1577
|
if (enableSafetyChecker !== void 0) {
|
|
1538
1578
|
body.enable_safety_checker = enableSafetyChecker;
|
|
1539
1579
|
}
|
|
1540
1580
|
}
|
|
1541
|
-
if (config.supportsLimitGenerations) {
|
|
1581
|
+
if (config.supportsLimitGenerations === true) {
|
|
1542
1582
|
if (limitGenerations !== void 0) {
|
|
1543
1583
|
body.limit_generations = limitGenerations;
|
|
1544
1584
|
}
|
|
1545
1585
|
}
|
|
1546
|
-
if (config.supportsThinkingLevel) {
|
|
1547
|
-
if (thinkingLevel)
|
|
1586
|
+
if (config.supportsThinkingLevel === true) {
|
|
1587
|
+
if (thinkingLevel) {
|
|
1588
|
+
body.thinking_level = thinkingLevel;
|
|
1589
|
+
}
|
|
1548
1590
|
}
|
|
1549
|
-
if (config.supportsStyle && style) {
|
|
1591
|
+
if (config.supportsStyle === true && style !== void 0 && style !== "") {
|
|
1550
1592
|
body.style = style;
|
|
1551
1593
|
}
|
|
1552
|
-
if (config.supportsNegativePrompt) {
|
|
1553
|
-
if (negativePrompt
|
|
1594
|
+
if (config.supportsNegativePrompt === true) {
|
|
1595
|
+
if (negativePrompt !== void 0 && negativePrompt !== "") {
|
|
1596
|
+
body.negative_prompt = negativePrompt;
|
|
1597
|
+
}
|
|
1554
1598
|
}
|
|
1555
1599
|
if (model === "ideogram") {
|
|
1556
|
-
if (style
|
|
1600
|
+
if (style !== void 0 && style !== "") {
|
|
1601
|
+
body.style = style;
|
|
1602
|
+
}
|
|
1557
1603
|
}
|
|
1558
|
-
if (config.supportsRenderingSpeed) {
|
|
1559
|
-
if (renderingSpeed)
|
|
1604
|
+
if (config.supportsRenderingSpeed === true) {
|
|
1605
|
+
if (renderingSpeed) {
|
|
1606
|
+
body.rendering_speed = renderingSpeed;
|
|
1607
|
+
}
|
|
1560
1608
|
}
|
|
1561
|
-
if (config.supportsExpandPrompt) {
|
|
1562
|
-
if (expandPrompt !== void 0)
|
|
1609
|
+
if (config.supportsExpandPrompt === true) {
|
|
1610
|
+
if (expandPrompt !== void 0) {
|
|
1611
|
+
body.expand_prompt = expandPrompt;
|
|
1612
|
+
}
|
|
1563
1613
|
}
|
|
1564
1614
|
if (model === "flux" && hasEditImages) {
|
|
1565
1615
|
body.image_url = editImages[0];
|
|
@@ -1586,959 +1636,1057 @@ function buildGenerateBody(options) {
|
|
|
1586
1636
|
body.input_fidelity = inputFidelity;
|
|
1587
1637
|
}
|
|
1588
1638
|
}
|
|
1589
|
-
if (maskImageUrl && config.supportsMaskImage) {
|
|
1639
|
+
if (maskImageUrl !== void 0 && maskImageUrl !== "" && config.supportsMaskImage === true) {
|
|
1590
1640
|
body.mask_image_url = maskImageUrl;
|
|
1591
1641
|
}
|
|
1592
|
-
return {
|
|
1642
|
+
return { body, endpoint };
|
|
1593
1643
|
}
|
|
1594
1644
|
|
|
1595
1645
|
// src/leaderboards.ts
|
|
1596
1646
|
var IMAGE_TEXT_TO_IMAGE_TOP_20 = {
|
|
1597
1647
|
capturedAt: "2026-05-12",
|
|
1598
|
-
source: "https://artificialanalysis.ai/image/leaderboard/text-to-image",
|
|
1599
1648
|
entries: [
|
|
1600
1649
|
{
|
|
1601
|
-
|
|
1650
|
+
apiPricing: "$211/1k images",
|
|
1602
1651
|
creator: "OpenAI",
|
|
1603
|
-
model: "GPT Image 2 (high)",
|
|
1604
1652
|
elo: 1337,
|
|
1605
|
-
apiPricing: "$211/1k images",
|
|
1606
1653
|
isCurrent: true,
|
|
1654
|
+
model: "GPT Image 2 (high)",
|
|
1655
|
+
rank: 1,
|
|
1607
1656
|
routableModelId: "gpt2"
|
|
1608
1657
|
},
|
|
1609
1658
|
{
|
|
1610
|
-
|
|
1659
|
+
apiPricing: "$133/1k images",
|
|
1611
1660
|
creator: "OpenAI",
|
|
1612
|
-
model: "GPT Image 1.5 (high)",
|
|
1613
1661
|
elo: 1268,
|
|
1614
|
-
apiPricing: "$133/1k images",
|
|
1615
1662
|
isCurrent: true,
|
|
1663
|
+
model: "GPT Image 1.5 (high)",
|
|
1664
|
+
rank: 2,
|
|
1616
1665
|
routableModelId: "gpt"
|
|
1617
1666
|
},
|
|
1618
1667
|
{
|
|
1619
|
-
|
|
1668
|
+
apiPricing: "$67/1k images",
|
|
1620
1669
|
creator: "Google",
|
|
1621
|
-
model: "Nano Banana 2 (Gemini 3.1 Flash Image Preview)",
|
|
1622
1670
|
elo: 1263,
|
|
1623
|
-
apiPricing: "$67/1k images",
|
|
1624
1671
|
isCurrent: true,
|
|
1672
|
+
model: "Nano Banana 2 (Gemini 3.1 Flash Image Preview)",
|
|
1673
|
+
rank: 3,
|
|
1625
1674
|
routableModelId: "banana2"
|
|
1626
1675
|
},
|
|
1627
1676
|
{
|
|
1628
|
-
|
|
1677
|
+
apiPricing: "$150/1k images",
|
|
1629
1678
|
creator: "Sourceful",
|
|
1630
|
-
model: "Riverflow 2.0",
|
|
1631
1679
|
elo: 1256,
|
|
1632
|
-
|
|
1633
|
-
|
|
1680
|
+
isCurrent: true,
|
|
1681
|
+
model: "Riverflow 2.0",
|
|
1682
|
+
rank: 4
|
|
1634
1683
|
},
|
|
1635
1684
|
{
|
|
1636
|
-
|
|
1685
|
+
apiPricing: "$134/1k images",
|
|
1637
1686
|
creator: "Google",
|
|
1638
|
-
model: "Nano Banana Pro (Gemini 3 Pro Image)",
|
|
1639
1687
|
elo: 1220,
|
|
1640
|
-
apiPricing: "$134/1k images",
|
|
1641
1688
|
isCurrent: true,
|
|
1689
|
+
model: "Nano Banana Pro (Gemini 3 Pro Image)",
|
|
1690
|
+
rank: 5,
|
|
1642
1691
|
routableModelId: "banana"
|
|
1643
1692
|
},
|
|
1644
1693
|
{
|
|
1645
|
-
|
|
1694
|
+
apiPricing: "$30/1k images",
|
|
1646
1695
|
creator: "ByteDance Seed",
|
|
1647
|
-
model: "Seedream 4.0",
|
|
1648
1696
|
elo: 1198,
|
|
1649
|
-
apiPricing: "$30/1k images",
|
|
1650
1697
|
isCurrent: true,
|
|
1698
|
+
model: "Seedream 4.0",
|
|
1699
|
+
rank: 6,
|
|
1651
1700
|
routableModelId: "seedream4"
|
|
1652
1701
|
},
|
|
1653
1702
|
{
|
|
1654
|
-
|
|
1703
|
+
apiPricing: "$50/1k images",
|
|
1655
1704
|
creator: "Microsoft",
|
|
1656
|
-
model: "MAI-Image-2",
|
|
1657
1705
|
elo: 1198,
|
|
1658
|
-
|
|
1659
|
-
|
|
1706
|
+
isCurrent: true,
|
|
1707
|
+
model: "MAI-Image-2",
|
|
1708
|
+
rank: 7
|
|
1660
1709
|
},
|
|
1661
1710
|
{
|
|
1662
|
-
|
|
1711
|
+
apiPricing: "$70/1k images",
|
|
1663
1712
|
creator: "Black Forest Labs",
|
|
1664
|
-
model: "FLUX.2 [max]",
|
|
1665
1713
|
elo: 1197,
|
|
1666
|
-
apiPricing: "$70/1k images",
|
|
1667
1714
|
isCurrent: true,
|
|
1715
|
+
model: "FLUX.2 [max]",
|
|
1716
|
+
rank: 8,
|
|
1668
1717
|
routableModelId: "flux2-max"
|
|
1669
1718
|
},
|
|
1670
1719
|
{
|
|
1671
|
-
|
|
1720
|
+
apiPricing: "Unavailable",
|
|
1672
1721
|
creator: "Peanut",
|
|
1673
|
-
model: "Peanut (Open Weights Coming Soon)",
|
|
1674
1722
|
elo: 1187,
|
|
1675
|
-
|
|
1676
|
-
|
|
1723
|
+
isCurrent: true,
|
|
1724
|
+
model: "Peanut (Open Weights Coming Soon)",
|
|
1725
|
+
rank: 9
|
|
1677
1726
|
},
|
|
1678
1727
|
{
|
|
1679
|
-
|
|
1728
|
+
apiPricing: "$30/1k images",
|
|
1680
1729
|
creator: "Black Forest Labs",
|
|
1681
|
-
model: "FLUX.2 [pro]",
|
|
1682
1730
|
elo: 1186,
|
|
1683
|
-
apiPricing: "$30/1k images",
|
|
1684
1731
|
isCurrent: true,
|
|
1732
|
+
model: "FLUX.2 [pro]",
|
|
1733
|
+
rank: 10,
|
|
1685
1734
|
routableModelId: "flux2-pro"
|
|
1686
1735
|
},
|
|
1687
1736
|
{
|
|
1688
|
-
|
|
1737
|
+
apiPricing: "$60/1k images",
|
|
1689
1738
|
creator: "Google",
|
|
1690
|
-
model: "Imagen 4 Ultra Preview 0606",
|
|
1691
1739
|
elo: 1184,
|
|
1692
|
-
|
|
1693
|
-
|
|
1740
|
+
isCurrent: false,
|
|
1741
|
+
model: "Imagen 4 Ultra Preview 0606",
|
|
1742
|
+
rank: 11
|
|
1694
1743
|
},
|
|
1695
1744
|
{
|
|
1696
|
-
|
|
1745
|
+
apiPricing: "$20/1k images",
|
|
1697
1746
|
creator: "xAI",
|
|
1698
|
-
model: "grok-imagine-image",
|
|
1699
1747
|
elo: 1182,
|
|
1700
|
-
apiPricing: "$20/1k images",
|
|
1701
1748
|
isCurrent: true,
|
|
1749
|
+
model: "grok-imagine-image",
|
|
1750
|
+
rank: 12,
|
|
1702
1751
|
routableModelId: "grok-image"
|
|
1703
1752
|
},
|
|
1704
1753
|
{
|
|
1705
|
-
|
|
1754
|
+
apiPricing: "$60/1k images",
|
|
1706
1755
|
creator: "Black Forest Labs",
|
|
1707
|
-
model: "FLUX.2 [flex]",
|
|
1708
1756
|
elo: 1182,
|
|
1709
|
-
apiPricing: "$60/1k images",
|
|
1710
1757
|
isCurrent: true,
|
|
1758
|
+
model: "FLUX.2 [flex]",
|
|
1759
|
+
rank: 13,
|
|
1711
1760
|
routableModelId: "flux2-flex"
|
|
1712
1761
|
},
|
|
1713
1762
|
{
|
|
1714
|
-
|
|
1763
|
+
apiPricing: "$30/1k images",
|
|
1715
1764
|
creator: "ImagineArt",
|
|
1716
|
-
model: "ImagineArt 2.0",
|
|
1717
1765
|
elo: 1181,
|
|
1718
|
-
|
|
1719
|
-
|
|
1766
|
+
isCurrent: true,
|
|
1767
|
+
model: "ImagineArt 2.0",
|
|
1768
|
+
rank: 14
|
|
1720
1769
|
},
|
|
1721
1770
|
{
|
|
1722
|
-
|
|
1771
|
+
apiPricing: "$60/1k images",
|
|
1723
1772
|
creator: "Google",
|
|
1724
|
-
model: "Imagen 4 Ultra",
|
|
1725
1773
|
elo: 1171,
|
|
1726
|
-
|
|
1727
|
-
|
|
1774
|
+
isCurrent: true,
|
|
1775
|
+
model: "Imagen 4 Ultra",
|
|
1776
|
+
rank: 15
|
|
1728
1777
|
},
|
|
1729
1778
|
{
|
|
1730
|
-
|
|
1779
|
+
apiPricing: "$40/1k images",
|
|
1731
1780
|
creator: "Google",
|
|
1732
|
-
model: "Imagen 4 Preview 0606",
|
|
1733
1781
|
elo: 1169,
|
|
1734
|
-
|
|
1735
|
-
|
|
1782
|
+
isCurrent: false,
|
|
1783
|
+
model: "Imagen 4 Preview 0606",
|
|
1784
|
+
rank: 16
|
|
1736
1785
|
},
|
|
1737
1786
|
{
|
|
1738
|
-
|
|
1787
|
+
apiPricing: "$40/1k images",
|
|
1739
1788
|
creator: "ByteDance Seed",
|
|
1740
|
-
model: "Seedream 4.5",
|
|
1741
1789
|
elo: 1167,
|
|
1742
|
-
apiPricing: "$40/1k images",
|
|
1743
1790
|
isCurrent: true,
|
|
1791
|
+
model: "Seedream 4.5",
|
|
1792
|
+
rank: 17,
|
|
1744
1793
|
routableModelId: "seedream45"
|
|
1745
1794
|
},
|
|
1746
1795
|
{
|
|
1747
|
-
|
|
1796
|
+
apiPricing: "$8/1k images",
|
|
1748
1797
|
creator: "Fal",
|
|
1749
|
-
model: "FLUX.2 [dev] Turbo",
|
|
1750
1798
|
elo: 1161,
|
|
1751
|
-
|
|
1752
|
-
|
|
1799
|
+
isCurrent: true,
|
|
1800
|
+
model: "FLUX.2 [dev] Turbo",
|
|
1801
|
+
rank: 18
|
|
1753
1802
|
},
|
|
1754
1803
|
{
|
|
1755
|
-
|
|
1804
|
+
apiPricing: "$12/1k images",
|
|
1756
1805
|
creator: "Black Forest Labs",
|
|
1757
|
-
model: "FLUX.2 [dev]",
|
|
1758
1806
|
elo: 1160,
|
|
1759
|
-
apiPricing: "$12/1k images",
|
|
1760
1807
|
isCurrent: true,
|
|
1808
|
+
model: "FLUX.2 [dev]",
|
|
1809
|
+
rank: 19,
|
|
1761
1810
|
routableModelId: "flux2-dev"
|
|
1762
1811
|
},
|
|
1763
1812
|
{
|
|
1764
|
-
|
|
1813
|
+
apiPricing: "$20/1k images",
|
|
1765
1814
|
creator: "Alibaba",
|
|
1766
|
-
model: "Qwen Image Max 2512",
|
|
1767
1815
|
elo: 1158,
|
|
1768
|
-
apiPricing: "$20/1k images",
|
|
1769
1816
|
isCurrent: true,
|
|
1817
|
+
model: "Qwen Image Max 2512",
|
|
1818
|
+
rank: 20,
|
|
1770
1819
|
routableModelId: "qwen"
|
|
1771
1820
|
}
|
|
1772
|
-
]
|
|
1821
|
+
],
|
|
1822
|
+
source: "https://artificialanalysis.ai/image/leaderboard/text-to-image"
|
|
1773
1823
|
};
|
|
1774
1824
|
var IMAGE_EDITING_TOP_20 = {
|
|
1775
1825
|
capturedAt: "2026-05-12",
|
|
1776
|
-
source: "https://artificialanalysis.ai/image/leaderboard/editing",
|
|
1777
1826
|
entries: [
|
|
1778
1827
|
{
|
|
1779
|
-
|
|
1828
|
+
apiPricing: "$150/1k images",
|
|
1780
1829
|
creator: "Sourceful",
|
|
1781
|
-
model: "Riverflow 2.0",
|
|
1782
1830
|
elo: 1286,
|
|
1783
|
-
|
|
1784
|
-
|
|
1831
|
+
isCurrent: true,
|
|
1832
|
+
model: "Riverflow 2.0",
|
|
1833
|
+
rank: 1
|
|
1785
1834
|
},
|
|
1786
1835
|
{
|
|
1787
|
-
|
|
1836
|
+
apiPricing: "$133/1k images",
|
|
1788
1837
|
creator: "OpenAI",
|
|
1789
|
-
model: "GPT Image 1.5 (high)",
|
|
1790
1838
|
elo: 1262,
|
|
1791
|
-
apiPricing: "$133/1k images",
|
|
1792
1839
|
isCurrent: true,
|
|
1840
|
+
model: "GPT Image 1.5 (high)",
|
|
1841
|
+
rank: 2,
|
|
1793
1842
|
routableModelId: "gpt"
|
|
1794
1843
|
},
|
|
1795
1844
|
{
|
|
1796
|
-
|
|
1845
|
+
apiPricing: "$211/1k images",
|
|
1797
1846
|
creator: "OpenAI",
|
|
1798
|
-
model: "GPT Image 2 (high)",
|
|
1799
1847
|
elo: 1249,
|
|
1800
|
-
apiPricing: "$211/1k images",
|
|
1801
1848
|
isCurrent: true,
|
|
1849
|
+
model: "GPT Image 2 (high)",
|
|
1850
|
+
rank: 3,
|
|
1802
1851
|
routableModelId: "gpt2"
|
|
1803
1852
|
},
|
|
1804
1853
|
{
|
|
1805
|
-
|
|
1854
|
+
apiPricing: "$134/1k images",
|
|
1806
1855
|
creator: "Google",
|
|
1807
|
-
model: "Nano Banana Pro (Gemini 3 Pro Image)",
|
|
1808
1856
|
elo: 1241,
|
|
1809
|
-
apiPricing: "$134/1k images",
|
|
1810
1857
|
isCurrent: true,
|
|
1858
|
+
model: "Nano Banana Pro (Gemini 3 Pro Image)",
|
|
1859
|
+
rank: 4,
|
|
1811
1860
|
routableModelId: "banana"
|
|
1812
1861
|
},
|
|
1813
1862
|
{
|
|
1814
|
-
|
|
1863
|
+
apiPricing: "$67/1k images",
|
|
1815
1864
|
creator: "Google",
|
|
1816
|
-
model: "Nano Banana 2 (Gemini 3.1 Flash Image Preview)",
|
|
1817
1865
|
elo: 1231,
|
|
1818
|
-
apiPricing: "$67/1k images",
|
|
1819
1866
|
isCurrent: true,
|
|
1867
|
+
model: "Nano Banana 2 (Gemini 3.1 Flash Image Preview)",
|
|
1868
|
+
rank: 5,
|
|
1820
1869
|
routableModelId: "banana2"
|
|
1821
1870
|
},
|
|
1822
1871
|
{
|
|
1823
|
-
|
|
1872
|
+
apiPricing: "$90/1k images",
|
|
1824
1873
|
creator: "Tencent",
|
|
1825
|
-
model: "HunyuanImage 3.0 Instruct (Fal)",
|
|
1826
1874
|
elo: 1222,
|
|
1827
|
-
|
|
1828
|
-
|
|
1875
|
+
isCurrent: true,
|
|
1876
|
+
model: "HunyuanImage 3.0 Instruct (Fal)",
|
|
1877
|
+
rank: 6
|
|
1829
1878
|
},
|
|
1830
1879
|
{
|
|
1831
|
-
|
|
1880
|
+
apiPricing: "$20/1k images",
|
|
1832
1881
|
creator: "xAI",
|
|
1833
|
-
model: "grok-imagine-image",
|
|
1834
1882
|
elo: 1213,
|
|
1835
|
-
apiPricing: "$20/1k images",
|
|
1836
1883
|
isCurrent: true,
|
|
1884
|
+
model: "grok-imagine-image",
|
|
1885
|
+
rank: 7,
|
|
1837
1886
|
routableModelId: "grok-image"
|
|
1838
1887
|
},
|
|
1839
1888
|
{
|
|
1840
|
-
|
|
1889
|
+
apiPricing: "$70/1k images",
|
|
1841
1890
|
creator: "xAI",
|
|
1842
|
-
model: "grok-imagine-image-pro",
|
|
1843
1891
|
elo: 1212,
|
|
1844
|
-
|
|
1845
|
-
|
|
1892
|
+
isCurrent: true,
|
|
1893
|
+
model: "grok-imagine-image-pro",
|
|
1894
|
+
rank: 8
|
|
1846
1895
|
},
|
|
1847
1896
|
{
|
|
1848
|
-
|
|
1897
|
+
apiPricing: "Unavailable",
|
|
1849
1898
|
creator: "KlingAI",
|
|
1850
|
-
model: "Kling Image 3.0 Omni",
|
|
1851
1899
|
elo: 1207,
|
|
1852
|
-
|
|
1853
|
-
|
|
1900
|
+
isCurrent: true,
|
|
1901
|
+
model: "Kling Image 3.0 Omni",
|
|
1902
|
+
rank: 9
|
|
1854
1903
|
},
|
|
1855
1904
|
{
|
|
1856
|
-
|
|
1905
|
+
apiPricing: "$140/1k images",
|
|
1857
1906
|
creator: "Black Forest Labs",
|
|
1858
|
-
model: "FLUX.2 [max]",
|
|
1859
1907
|
elo: 1206,
|
|
1860
|
-
apiPricing: "$140/1k images",
|
|
1861
1908
|
isCurrent: true,
|
|
1909
|
+
model: "FLUX.2 [max]",
|
|
1910
|
+
rank: 10,
|
|
1862
1911
|
routableModelId: "flux2-max"
|
|
1863
1912
|
},
|
|
1864
1913
|
{
|
|
1865
|
-
|
|
1914
|
+
apiPricing: "Unavailable",
|
|
1866
1915
|
creator: "Alibaba",
|
|
1867
|
-
model: "Wan 2.7 Pro",
|
|
1868
1916
|
elo: 1200,
|
|
1869
|
-
|
|
1870
|
-
|
|
1917
|
+
isCurrent: true,
|
|
1918
|
+
model: "Wan 2.7 Pro",
|
|
1919
|
+
rank: 11
|
|
1871
1920
|
},
|
|
1872
1921
|
{
|
|
1873
|
-
|
|
1922
|
+
apiPricing: "$28/1k images",
|
|
1874
1923
|
creator: "KlingAI",
|
|
1875
|
-
model: "Kling Image 3.0",
|
|
1876
1924
|
elo: 1196,
|
|
1877
|
-
|
|
1878
|
-
|
|
1925
|
+
isCurrent: true,
|
|
1926
|
+
model: "Kling Image 3.0",
|
|
1927
|
+
rank: 12
|
|
1879
1928
|
},
|
|
1880
1929
|
{
|
|
1881
|
-
|
|
1930
|
+
apiPricing: "$28/1k images",
|
|
1882
1931
|
creator: "KlingAI",
|
|
1883
|
-
model: "Kling Image O1",
|
|
1884
1932
|
elo: 1193,
|
|
1885
|
-
|
|
1886
|
-
|
|
1933
|
+
isCurrent: true,
|
|
1934
|
+
model: "Kling Image O1",
|
|
1935
|
+
rank: 13
|
|
1887
1936
|
},
|
|
1888
1937
|
{
|
|
1889
|
-
|
|
1938
|
+
apiPricing: "$30/1k images",
|
|
1890
1939
|
creator: "Alibaba",
|
|
1891
|
-
model: "Wan 2.6 Image",
|
|
1892
1940
|
elo: 1188,
|
|
1893
|
-
|
|
1894
|
-
|
|
1941
|
+
isCurrent: true,
|
|
1942
|
+
model: "Wan 2.6 Image",
|
|
1943
|
+
rank: 14
|
|
1895
1944
|
},
|
|
1896
1945
|
{
|
|
1897
|
-
|
|
1946
|
+
apiPricing: "$66/1k images",
|
|
1898
1947
|
creator: "Sourceful",
|
|
1899
|
-
model: "Riverflow 1",
|
|
1900
1948
|
elo: 1184,
|
|
1901
|
-
|
|
1902
|
-
|
|
1949
|
+
isCurrent: true,
|
|
1950
|
+
model: "Riverflow 1",
|
|
1951
|
+
rank: 15
|
|
1903
1952
|
},
|
|
1904
1953
|
{
|
|
1905
|
-
|
|
1954
|
+
apiPricing: "$30/1k images",
|
|
1906
1955
|
creator: "ByteDance Seed",
|
|
1907
|
-
model: "Seedream 4.0",
|
|
1908
1956
|
elo: 1184,
|
|
1909
|
-
apiPricing: "$30/1k images",
|
|
1910
1957
|
isCurrent: true,
|
|
1958
|
+
model: "Seedream 4.0",
|
|
1959
|
+
rank: 16,
|
|
1911
1960
|
routableModelId: "seedream4"
|
|
1912
1961
|
},
|
|
1913
1962
|
{
|
|
1914
|
-
|
|
1963
|
+
apiPricing: "$40/1k images",
|
|
1915
1964
|
creator: "ByteDance Seed",
|
|
1916
|
-
model: "Seedream 4.5",
|
|
1917
1965
|
elo: 1184,
|
|
1918
|
-
apiPricing: "$40/1k images",
|
|
1919
1966
|
isCurrent: true,
|
|
1967
|
+
model: "Seedream 4.5",
|
|
1968
|
+
rank: 17,
|
|
1920
1969
|
routableModelId: "seedream45"
|
|
1921
1970
|
},
|
|
1922
1971
|
{
|
|
1923
|
-
|
|
1972
|
+
apiPricing: "$26/1k images",
|
|
1924
1973
|
creator: "Alibaba",
|
|
1925
|
-
model: "Wan 2.7",
|
|
1926
1974
|
elo: 1181,
|
|
1927
|
-
|
|
1928
|
-
|
|
1975
|
+
isCurrent: true,
|
|
1976
|
+
model: "Wan 2.7",
|
|
1977
|
+
rank: 18
|
|
1929
1978
|
},
|
|
1930
1979
|
{
|
|
1931
|
-
|
|
1980
|
+
apiPricing: "$39/1k images",
|
|
1932
1981
|
creator: "Google",
|
|
1933
|
-
model: "Nano Banana (Gemini 2.5 Flash Image)",
|
|
1934
1982
|
elo: 1173,
|
|
1935
|
-
apiPricing: "$39/1k images",
|
|
1936
1983
|
isCurrent: true,
|
|
1984
|
+
model: "Nano Banana (Gemini 2.5 Flash Image)",
|
|
1985
|
+
rank: 19,
|
|
1937
1986
|
routableModelId: "gemini"
|
|
1938
1987
|
},
|
|
1939
1988
|
{
|
|
1940
|
-
|
|
1989
|
+
apiPricing: "$40/1k images",
|
|
1941
1990
|
creator: "Reve",
|
|
1942
|
-
model: "Reve V1 (December)",
|
|
1943
1991
|
elo: 1172,
|
|
1944
|
-
|
|
1945
|
-
|
|
1992
|
+
isCurrent: true,
|
|
1993
|
+
model: "Reve V1 (December)",
|
|
1994
|
+
rank: 20
|
|
1946
1995
|
}
|
|
1947
|
-
]
|
|
1996
|
+
],
|
|
1997
|
+
source: "https://artificialanalysis.ai/image/leaderboard/editing"
|
|
1948
1998
|
};
|
|
1949
1999
|
var VIDEO_TEXT_TO_VIDEO_TOP_15 = {
|
|
1950
2000
|
capturedAt: "2026-05-12",
|
|
1951
|
-
source: "https://artificialanalysis.ai/video/leaderboard/text-to-video",
|
|
1952
2001
|
entries: [
|
|
1953
2002
|
{
|
|
1954
|
-
|
|
2003
|
+
apiPricing: "$14.40/min",
|
|
1955
2004
|
creator: "Alibaba-ATH",
|
|
1956
|
-
model: "HappyHorse-1.0",
|
|
1957
2005
|
elo: 1354,
|
|
1958
|
-
|
|
2006
|
+
model: "HappyHorse-1.0",
|
|
2007
|
+
rank: 1
|
|
1959
2008
|
},
|
|
1960
2009
|
{
|
|
1961
|
-
|
|
2010
|
+
apiPricing: "No API available",
|
|
1962
2011
|
creator: "ByteDance Seed",
|
|
1963
|
-
model: "Dreamina Seedance 2.0 720p",
|
|
1964
2012
|
elo: 1273,
|
|
1965
|
-
|
|
2013
|
+
model: "Dreamina Seedance 2.0 720p",
|
|
2014
|
+
rank: 2
|
|
1966
2015
|
},
|
|
1967
2016
|
{
|
|
1968
|
-
|
|
2017
|
+
apiPricing: "$13.44/min",
|
|
1969
2018
|
creator: "KlingAI",
|
|
1970
|
-
model: "Kling 3.0 1080p (Pro)",
|
|
1971
2019
|
elo: 1249,
|
|
1972
|
-
|
|
2020
|
+
model: "Kling 3.0 1080p (Pro)",
|
|
2021
|
+
rank: 3
|
|
1973
2022
|
},
|
|
1974
2023
|
{
|
|
1975
|
-
|
|
2024
|
+
apiPricing: "$13.44/min",
|
|
1976
2025
|
creator: "KlingAI",
|
|
1977
|
-
model: "Kling 3.0 Omni 1080p (Pro)",
|
|
1978
2026
|
elo: 1233,
|
|
1979
|
-
|
|
2027
|
+
model: "Kling 3.0 Omni 1080p (Pro)",
|
|
2028
|
+
rank: 4
|
|
1980
2029
|
},
|
|
1981
2030
|
{
|
|
1982
|
-
|
|
2031
|
+
apiPricing: "$4.20/min",
|
|
1983
2032
|
creator: "xAI",
|
|
1984
|
-
model: "grok-imagine-video",
|
|
1985
2033
|
elo: 1233,
|
|
1986
|
-
|
|
2034
|
+
model: "grok-imagine-video",
|
|
2035
|
+
rank: 5
|
|
1987
2036
|
},
|
|
1988
2037
|
{
|
|
1989
|
-
|
|
2038
|
+
apiPricing: "$9.60/min",
|
|
1990
2039
|
creator: "Vidu",
|
|
1991
|
-
model: "Vidu Q3 Pro",
|
|
1992
2040
|
elo: 1225,
|
|
1993
|
-
|
|
2041
|
+
model: "Vidu Q3 Pro",
|
|
2042
|
+
rank: 6
|
|
1994
2043
|
},
|
|
1995
2044
|
{
|
|
1996
|
-
|
|
2045
|
+
apiPricing: "$3.00/min",
|
|
1997
2046
|
creator: "Video Rebirth",
|
|
1998
|
-
model: "Bach-1.0 Preview",
|
|
1999
2047
|
elo: 1224,
|
|
2000
|
-
|
|
2048
|
+
model: "Bach-1.0 Preview",
|
|
2049
|
+
rank: 7
|
|
2001
2050
|
},
|
|
2002
2051
|
{
|
|
2003
|
-
|
|
2052
|
+
apiPricing: "$10.08/min",
|
|
2004
2053
|
creator: "KlingAI",
|
|
2005
|
-
model: "Kling 3.0 Omni 720p (Standard)",
|
|
2006
2054
|
elo: 1224,
|
|
2007
|
-
|
|
2055
|
+
model: "Kling 3.0 Omni 720p (Standard)",
|
|
2056
|
+
rank: 8
|
|
2008
2057
|
},
|
|
2009
2058
|
{
|
|
2010
|
-
|
|
2059
|
+
apiPricing: "$5.40/min",
|
|
2011
2060
|
creator: "PixVerse",
|
|
2012
|
-
model: "PixVerse V6",
|
|
2013
2061
|
elo: 1222,
|
|
2014
|
-
|
|
2062
|
+
model: "PixVerse V6",
|
|
2063
|
+
rank: 9
|
|
2015
2064
|
},
|
|
2016
2065
|
{
|
|
2017
|
-
|
|
2066
|
+
apiPricing: "$9.00/min",
|
|
2018
2067
|
creator: "PixVerse",
|
|
2019
|
-
model: "PixVerse V5.6",
|
|
2020
2068
|
elo: 1221,
|
|
2021
|
-
|
|
2069
|
+
model: "PixVerse V5.6",
|
|
2070
|
+
rank: 10
|
|
2022
2071
|
},
|
|
2023
2072
|
{
|
|
2024
|
-
|
|
2073
|
+
apiPricing: "No API available",
|
|
2025
2074
|
creator: "Runway",
|
|
2026
|
-
model: "Runway Gen-4.5",
|
|
2027
2075
|
elo: 1220,
|
|
2028
|
-
|
|
2076
|
+
model: "Runway Gen-4.5",
|
|
2077
|
+
rank: 11
|
|
2029
2078
|
},
|
|
2030
2079
|
{
|
|
2031
|
-
|
|
2080
|
+
apiPricing: "$12.00/min",
|
|
2032
2081
|
creator: "Google",
|
|
2033
|
-
model: "Veo 3",
|
|
2034
2082
|
elo: 1218,
|
|
2035
|
-
|
|
2083
|
+
model: "Veo 3",
|
|
2084
|
+
rank: 12
|
|
2036
2085
|
},
|
|
2037
2086
|
{
|
|
2038
|
-
|
|
2087
|
+
apiPricing: "$10.08/min",
|
|
2039
2088
|
creator: "KlingAI",
|
|
2040
|
-
model: "Kling 3.0 720p (Standard)",
|
|
2041
2089
|
elo: 1215,
|
|
2042
|
-
|
|
2090
|
+
model: "Kling 3.0 720p (Standard)",
|
|
2091
|
+
rank: 13
|
|
2043
2092
|
},
|
|
2044
2093
|
{
|
|
2045
|
-
|
|
2094
|
+
apiPricing: "$3.00/min",
|
|
2046
2095
|
creator: "Google",
|
|
2047
|
-
model: "Veo 3.1 Lite",
|
|
2048
2096
|
elo: 1214,
|
|
2049
|
-
|
|
2097
|
+
model: "Veo 3.1 Lite",
|
|
2098
|
+
rank: 14
|
|
2050
2099
|
},
|
|
2051
2100
|
{
|
|
2052
|
-
|
|
2101
|
+
apiPricing: "$10.08/min",
|
|
2053
2102
|
creator: "KlingAI",
|
|
2054
|
-
model: "Kling O1 Pro (January)",
|
|
2055
2103
|
elo: 1209,
|
|
2056
|
-
|
|
2104
|
+
model: "Kling O1 Pro (January)",
|
|
2105
|
+
rank: 15
|
|
2057
2106
|
}
|
|
2058
|
-
]
|
|
2107
|
+
],
|
|
2108
|
+
source: "https://artificialanalysis.ai/video/leaderboard/text-to-video"
|
|
2059
2109
|
};
|
|
2060
2110
|
var VIDEO_IMAGE_TO_VIDEO_TOP_15 = {
|
|
2061
2111
|
capturedAt: "2026-05-12",
|
|
2062
|
-
source: "https://artificialanalysis.ai/video/leaderboard/image-to-video",
|
|
2063
2112
|
entries: [
|
|
2064
2113
|
{
|
|
2065
|
-
|
|
2114
|
+
apiPricing: "Coming soon",
|
|
2066
2115
|
creator: "Alibaba-ATH",
|
|
2067
|
-
model: "HappyHorse-1.0",
|
|
2068
2116
|
elo: 1395,
|
|
2069
|
-
|
|
2117
|
+
model: "HappyHorse-1.0",
|
|
2118
|
+
rank: 1
|
|
2070
2119
|
},
|
|
2071
2120
|
{
|
|
2072
|
-
|
|
2121
|
+
apiPricing: "No API available",
|
|
2073
2122
|
creator: "ByteDance Seed",
|
|
2074
|
-
model: "Dreamina Seedance 2.0 720p",
|
|
2075
2123
|
elo: 1348,
|
|
2076
|
-
|
|
2124
|
+
model: "Dreamina Seedance 2.0 720p",
|
|
2125
|
+
rank: 2
|
|
2077
2126
|
},
|
|
2078
2127
|
{
|
|
2079
|
-
|
|
2128
|
+
apiPricing: "$4.20/min",
|
|
2080
2129
|
creator: "xAI",
|
|
2081
|
-
model: "grok-imagine-video",
|
|
2082
2130
|
elo: 1326,
|
|
2083
|
-
|
|
2131
|
+
model: "grok-imagine-video",
|
|
2132
|
+
rank: 3
|
|
2084
2133
|
},
|
|
2085
2134
|
{
|
|
2086
|
-
|
|
2135
|
+
apiPricing: "$5.40/min",
|
|
2087
2136
|
creator: "PixVerse",
|
|
2088
|
-
model: "PixVerse V6",
|
|
2089
2137
|
elo: 1322,
|
|
2090
|
-
|
|
2138
|
+
model: "PixVerse V6",
|
|
2139
|
+
rank: 4
|
|
2091
2140
|
},
|
|
2092
2141
|
{
|
|
2093
|
-
|
|
2142
|
+
apiPricing: "$9.60/min",
|
|
2094
2143
|
creator: "Vidu",
|
|
2095
|
-
model: "Vidu Q3 Pro",
|
|
2096
2144
|
elo: 1287,
|
|
2097
|
-
|
|
2145
|
+
model: "Vidu Q3 Pro",
|
|
2146
|
+
rank: 5
|
|
2098
2147
|
},
|
|
2099
2148
|
{
|
|
2100
|
-
|
|
2149
|
+
apiPricing: "$4.20/min",
|
|
2101
2150
|
creator: "KlingAI",
|
|
2102
|
-
model: "Kling 2.5 Turbo 1080p",
|
|
2103
2151
|
elo: 1283,
|
|
2104
|
-
|
|
2152
|
+
model: "Kling 2.5 Turbo 1080p",
|
|
2153
|
+
rank: 6
|
|
2105
2154
|
},
|
|
2106
2155
|
{
|
|
2107
|
-
|
|
2156
|
+
apiPricing: "$13.44/min",
|
|
2108
2157
|
creator: "KlingAI",
|
|
2109
|
-
model: "Kling 3.0 1080p (Pro)",
|
|
2110
2158
|
elo: 1280,
|
|
2111
|
-
|
|
2159
|
+
model: "Kling 3.0 1080p (Pro)",
|
|
2160
|
+
rank: 7
|
|
2112
2161
|
},
|
|
2113
2162
|
{
|
|
2114
|
-
|
|
2163
|
+
apiPricing: "$9.00/min",
|
|
2115
2164
|
creator: "PixVerse",
|
|
2116
|
-
model: "PixVerse V5.6",
|
|
2117
2165
|
elo: 1279,
|
|
2118
|
-
|
|
2166
|
+
model: "PixVerse V5.6",
|
|
2167
|
+
rank: 8
|
|
2119
2168
|
},
|
|
2120
2169
|
{
|
|
2121
|
-
|
|
2170
|
+
apiPricing: "$13.44/min",
|
|
2122
2171
|
creator: "KlingAI",
|
|
2123
|
-
model: "Kling 3.0 Omni 1080p (Pro)",
|
|
2124
2172
|
elo: 1277,
|
|
2125
|
-
|
|
2173
|
+
model: "Kling 3.0 Omni 1080p (Pro)",
|
|
2174
|
+
rank: 9
|
|
2126
2175
|
},
|
|
2127
2176
|
{
|
|
2128
|
-
|
|
2177
|
+
apiPricing: "Coming soon",
|
|
2129
2178
|
creator: "KlingAI",
|
|
2130
|
-
model: "Kling 2.6 Standard (January)",
|
|
2131
2179
|
elo: 1271,
|
|
2132
|
-
|
|
2180
|
+
model: "Kling 2.6 Standard (January)",
|
|
2181
|
+
rank: 10
|
|
2133
2182
|
},
|
|
2134
2183
|
{
|
|
2135
|
-
|
|
2184
|
+
apiPricing: "$6.40/min",
|
|
2136
2185
|
creator: "PixVerse",
|
|
2137
|
-
model: "PixVerse V5.5",
|
|
2138
2186
|
elo: 1271,
|
|
2139
|
-
|
|
2187
|
+
model: "PixVerse V5.5",
|
|
2188
|
+
rank: 11
|
|
2140
2189
|
},
|
|
2141
2190
|
{
|
|
2142
|
-
|
|
2191
|
+
apiPricing: "$6.00/min",
|
|
2143
2192
|
creator: "Google",
|
|
2144
|
-
model: "Veo 3.1 Fast",
|
|
2145
2193
|
elo: 1268,
|
|
2146
|
-
|
|
2194
|
+
model: "Veo 3.1 Fast",
|
|
2195
|
+
rank: 12
|
|
2147
2196
|
},
|
|
2148
2197
|
{
|
|
2149
|
-
|
|
2198
|
+
apiPricing: "No API available",
|
|
2150
2199
|
creator: "Runway",
|
|
2151
|
-
model: "Runway Gen-4.5",
|
|
2152
2200
|
elo: 1263,
|
|
2153
|
-
|
|
2201
|
+
model: "Runway Gen-4.5",
|
|
2202
|
+
rank: 13
|
|
2154
2203
|
},
|
|
2155
2204
|
{
|
|
2156
|
-
|
|
2205
|
+
apiPricing: "$10.08/min",
|
|
2157
2206
|
creator: "KlingAI",
|
|
2158
|
-
model: "Kling 3.0 Omni 720p (Standard)",
|
|
2159
2207
|
elo: 1263,
|
|
2160
|
-
|
|
2208
|
+
model: "Kling 3.0 Omni 720p (Standard)",
|
|
2209
|
+
rank: 14
|
|
2161
2210
|
},
|
|
2162
2211
|
{
|
|
2163
|
-
|
|
2212
|
+
apiPricing: "$10.08/min",
|
|
2164
2213
|
creator: "KlingAI",
|
|
2165
|
-
model: "Kling 3.0 720p (Standard)",
|
|
2166
2214
|
elo: 1263,
|
|
2167
|
-
|
|
2215
|
+
model: "Kling 3.0 720p (Standard)",
|
|
2216
|
+
rank: 15
|
|
2168
2217
|
}
|
|
2169
|
-
]
|
|
2218
|
+
],
|
|
2219
|
+
source: "https://artificialanalysis.ai/video/leaderboard/image-to-video"
|
|
2170
2220
|
};
|
|
2171
2221
|
|
|
2172
2222
|
// src/server.ts
|
|
2173
2223
|
var import_neverthrow = require("neverthrow");
|
|
2174
2224
|
|
|
2225
|
+
// src/fal-parse.ts
|
|
2226
|
+
function isRecord(value) {
|
|
2227
|
+
return typeof value === "object" && value !== null;
|
|
2228
|
+
}
|
|
2229
|
+
function asString(value) {
|
|
2230
|
+
return typeof value === "string" ? value : void 0;
|
|
2231
|
+
}
|
|
2232
|
+
function asNumber(value) {
|
|
2233
|
+
return typeof value === "number" ? value : void 0;
|
|
2234
|
+
}
|
|
2235
|
+
function toMotifImage(value) {
|
|
2236
|
+
if (isRecord(value)) {
|
|
2237
|
+
return {
|
|
2238
|
+
content_type: asString(value.content_type),
|
|
2239
|
+
height: asNumber(value.height),
|
|
2240
|
+
url: asString(value.url) ?? "",
|
|
2241
|
+
width: asNumber(value.width)
|
|
2242
|
+
};
|
|
2243
|
+
}
|
|
2244
|
+
return { url: "" };
|
|
2245
|
+
}
|
|
2246
|
+
function parseImages(value) {
|
|
2247
|
+
if (!Array.isArray(value)) {
|
|
2248
|
+
return [];
|
|
2249
|
+
}
|
|
2250
|
+
return value.map((entry) => toMotifImage(entry));
|
|
2251
|
+
}
|
|
2252
|
+
function parseLogs(value) {
|
|
2253
|
+
if (!Array.isArray(value)) {
|
|
2254
|
+
return void 0;
|
|
2255
|
+
}
|
|
2256
|
+
const entries = [];
|
|
2257
|
+
for (const entry of value) {
|
|
2258
|
+
if (isRecord(entry)) {
|
|
2259
|
+
entries.push({
|
|
2260
|
+
message: asString(entry.message) ?? "",
|
|
2261
|
+
timestamp: asString(entry.timestamp) ?? ""
|
|
2262
|
+
});
|
|
2263
|
+
}
|
|
2264
|
+
}
|
|
2265
|
+
return entries;
|
|
2266
|
+
}
|
|
2267
|
+
function endpointFromQueueUrl(url, fallback) {
|
|
2268
|
+
if (url === void 0 || url === "") {
|
|
2269
|
+
return fallback;
|
|
2270
|
+
}
|
|
2271
|
+
try {
|
|
2272
|
+
const parsed = new URL(url);
|
|
2273
|
+
const match = /^\/(.+)\/requests\//.exec(parsed.pathname);
|
|
2274
|
+
return match?.[1] ?? fallback;
|
|
2275
|
+
} catch {
|
|
2276
|
+
return fallback;
|
|
2277
|
+
}
|
|
2278
|
+
}
|
|
2279
|
+
function parseQueueSubmission(data) {
|
|
2280
|
+
if (!isRecord(data)) {
|
|
2281
|
+
return { requestId: "" };
|
|
2282
|
+
}
|
|
2283
|
+
return {
|
|
2284
|
+
requestId: asString(data.request_id) ?? "",
|
|
2285
|
+
responseUrl: asString(data.response_url)
|
|
2286
|
+
};
|
|
2287
|
+
}
|
|
2288
|
+
function toHeaderRecord(headers) {
|
|
2289
|
+
if (headers === void 0) {
|
|
2290
|
+
return {};
|
|
2291
|
+
}
|
|
2292
|
+
if (headers instanceof Headers) {
|
|
2293
|
+
const record = {};
|
|
2294
|
+
for (const [key, value] of headers.entries()) {
|
|
2295
|
+
record[key] = value;
|
|
2296
|
+
}
|
|
2297
|
+
return record;
|
|
2298
|
+
}
|
|
2299
|
+
if (Array.isArray(headers)) {
|
|
2300
|
+
const record = {};
|
|
2301
|
+
for (const [key, value] of headers) {
|
|
2302
|
+
record[key] = value;
|
|
2303
|
+
}
|
|
2304
|
+
return record;
|
|
2305
|
+
}
|
|
2306
|
+
return headers;
|
|
2307
|
+
}
|
|
2308
|
+
function requestIdFromBody(text) {
|
|
2309
|
+
let parsed;
|
|
2310
|
+
try {
|
|
2311
|
+
parsed = JSON.parse(text);
|
|
2312
|
+
} catch {
|
|
2313
|
+
return void 0;
|
|
2314
|
+
}
|
|
2315
|
+
if (!isRecord(parsed)) {
|
|
2316
|
+
return void 0;
|
|
2317
|
+
}
|
|
2318
|
+
return asString(parsed.request_id) ?? asString(parsed.requestId) ?? asString(parsed.trace_id);
|
|
2319
|
+
}
|
|
2320
|
+
|
|
2175
2321
|
// src/tools.ts
|
|
2176
2322
|
var FAL_EXPLORE_CHECKED_AT = "2026-05-12";
|
|
2177
2323
|
var FAL_TOOLS = {
|
|
2178
|
-
nsfw: {
|
|
2179
|
-
name: "NSFW Checker",
|
|
2180
|
-
endpoint: "fal-ai/x-ailab/nsfw",
|
|
2181
|
-
task: "vision moderation",
|
|
2182
|
-
category: "moderation",
|
|
2183
|
-
description: "Predict whether one or more images contain NSFW concepts.",
|
|
2184
|
-
inputKind: "images",
|
|
2185
|
-
inputField: "image_urls",
|
|
2186
|
-
outputKeys: ["has_nsfw_concepts"],
|
|
2187
|
-
pricing: "$0.001/image",
|
|
2188
|
-
sourceUrl: "https://fal.ai/models/fal-ai/x-ailab/nsfw"
|
|
2189
|
-
},
|
|
2190
|
-
"topaz-image": {
|
|
2191
|
-
name: "Topaz Image Upscale",
|
|
2192
|
-
endpoint: "fal-ai/topaz/upscale/image",
|
|
2193
|
-
task: "image enhancement",
|
|
2194
|
-
category: "upscale",
|
|
2195
|
-
description: "Professional Topaz image enhancement and upscaling.",
|
|
2196
|
-
inputKind: "image",
|
|
2197
|
-
inputField: "image_url",
|
|
2198
|
-
outputKeys: ["image"],
|
|
2199
|
-
pricing: "$0.08+ by output megapixels",
|
|
2200
|
-
sourceUrl: "https://fal.ai/models/fal-ai/topaz/upscale/image",
|
|
2201
|
-
defaultOptions: {
|
|
2202
|
-
model: "Standard V2",
|
|
2203
|
-
output_format: "jpeg",
|
|
2204
|
-
upscale_factor: 2
|
|
2205
|
-
}
|
|
2206
|
-
},
|
|
2207
|
-
"topaz-video": {
|
|
2208
|
-
name: "Topaz Video Upscale",
|
|
2209
|
-
endpoint: "fal-ai/topaz/upscale/video",
|
|
2210
|
-
task: "video enhancement",
|
|
2211
|
-
category: "upscale",
|
|
2212
|
-
description: "Professional Topaz video enhancement and upscaling.",
|
|
2213
|
-
inputKind: "video",
|
|
2214
|
-
inputField: "video_url",
|
|
2215
|
-
outputKeys: ["video"],
|
|
2216
|
-
pricing: "$0.01-$0.08/sec by output resolution",
|
|
2217
|
-
sourceUrl: "https://fal.ai/models/fal-ai/topaz/upscale/video",
|
|
2218
|
-
defaultOptions: {
|
|
2219
|
-
model: "Proteus",
|
|
2220
|
-
upscale_factor: 2
|
|
2221
|
-
}
|
|
2222
|
-
},
|
|
2223
|
-
"bria-rmbg": {
|
|
2224
|
-
name: "Bria RMBG 2.0",
|
|
2225
|
-
endpoint: "fal-ai/bria/background/remove",
|
|
2226
|
-
task: "image background removal",
|
|
2227
|
-
category: "background",
|
|
2228
|
-
description: "Commercial-safe background removal for images.",
|
|
2229
|
-
inputKind: "image",
|
|
2230
|
-
inputField: "image_url",
|
|
2231
|
-
outputKeys: ["image"],
|
|
2232
|
-
pricing: "$0.02/image",
|
|
2233
|
-
sourceUrl: "https://fal.ai/models/fal-ai/bria/background/remove"
|
|
2234
|
-
},
|
|
2235
2324
|
birefnet: {
|
|
2236
|
-
name: "BirefNet Background Removal",
|
|
2237
|
-
endpoint: "fal-ai/birefnet/v2",
|
|
2238
|
-
task: "image background removal",
|
|
2239
2325
|
category: "background",
|
|
2240
|
-
description: "High-resolution dichotomous image segmentation and background removal.",
|
|
2241
|
-
inputKind: "image",
|
|
2242
|
-
inputField: "image_url",
|
|
2243
|
-
outputKeys: ["image", "mask_image"],
|
|
2244
|
-
pricing: "$0/compute-second listed by fal",
|
|
2245
|
-
sourceUrl: "https://fal.ai/models/fal-ai/birefnet/v2",
|
|
2246
2326
|
defaultOptions: {
|
|
2247
2327
|
model: "General Use (Light)",
|
|
2248
2328
|
operating_resolution: "1024x1024",
|
|
2249
2329
|
output_format: "png",
|
|
2250
2330
|
refine_foreground: true
|
|
2251
|
-
}
|
|
2331
|
+
},
|
|
2332
|
+
description: "High-resolution dichotomous image segmentation and background removal.",
|
|
2333
|
+
endpoint: "fal-ai/birefnet/v2",
|
|
2334
|
+
inputField: "image_url",
|
|
2335
|
+
inputKind: "image",
|
|
2336
|
+
name: "BirefNet Background Removal",
|
|
2337
|
+
outputKeys: ["image", "mask_image"],
|
|
2338
|
+
pricing: "$0/compute-second listed by fal",
|
|
2339
|
+
sourceUrl: "https://fal.ai/models/fal-ai/birefnet/v2",
|
|
2340
|
+
task: "image background removal"
|
|
2252
2341
|
},
|
|
2253
|
-
|
|
2254
|
-
name: "Remove Background",
|
|
2255
|
-
endpoint: "fal-ai/imageutils/rembg",
|
|
2256
|
-
task: "image background removal",
|
|
2342
|
+
"bria-rmbg": {
|
|
2257
2343
|
category: "background",
|
|
2258
|
-
description: "
|
|
2259
|
-
|
|
2344
|
+
description: "Commercial-safe background removal for images.",
|
|
2345
|
+
endpoint: "fal-ai/bria/background/remove",
|
|
2260
2346
|
inputField: "image_url",
|
|
2347
|
+
inputKind: "image",
|
|
2348
|
+
name: "Bria RMBG 2.0",
|
|
2261
2349
|
outputKeys: ["image"],
|
|
2262
|
-
pricing: "$0/
|
|
2263
|
-
sourceUrl: "https://fal.ai/models/fal-ai/
|
|
2264
|
-
|
|
2265
|
-
crop_to_bbox: false
|
|
2266
|
-
}
|
|
2350
|
+
pricing: "$0.02/image",
|
|
2351
|
+
sourceUrl: "https://fal.ai/models/fal-ai/bria/background/remove",
|
|
2352
|
+
task: "image background removal"
|
|
2267
2353
|
},
|
|
2268
2354
|
"bria-video-rmbg": {
|
|
2269
|
-
name: "Bria Video Background Removal",
|
|
2270
|
-
endpoint: "bria/video/background-removal",
|
|
2271
|
-
task: "video background removal",
|
|
2272
2355
|
category: "background",
|
|
2356
|
+
defaultOptions: {
|
|
2357
|
+
background_color: "Black",
|
|
2358
|
+
output_container_and_codec: "webm_vp9",
|
|
2359
|
+
preserve_audio: true
|
|
2360
|
+
},
|
|
2273
2361
|
description: "Remove video backgrounds with configurable output container.",
|
|
2274
|
-
|
|
2362
|
+
endpoint: "bria/video/background-removal",
|
|
2275
2363
|
inputField: "video_url",
|
|
2364
|
+
inputKind: "video",
|
|
2365
|
+
name: "Bria Video Background Removal",
|
|
2276
2366
|
outputKeys: ["video"],
|
|
2277
2367
|
pricing: "$0.14/sec",
|
|
2278
2368
|
sourceUrl: "https://fal.ai/models/bria/video/background-removal",
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2369
|
+
task: "video background removal"
|
|
2370
|
+
},
|
|
2371
|
+
"depth-anything": {
|
|
2372
|
+
category: "preprocess",
|
|
2373
|
+
description: "Generate Depth Anything v2 depth maps from input images.",
|
|
2374
|
+
endpoint: "fal-ai/image-preprocessors/depth-anything/v2",
|
|
2375
|
+
inputField: "image_url",
|
|
2376
|
+
inputKind: "image",
|
|
2377
|
+
name: "Depth Anything v2 Preprocessor",
|
|
2378
|
+
outputKeys: ["image"],
|
|
2379
|
+
pricing: "$0/compute-second listed by fal",
|
|
2380
|
+
sourceUrl: "https://fal.ai/models/fal-ai/image-preprocessors/depth-anything/v2",
|
|
2381
|
+
task: "depth preprocessing"
|
|
2284
2382
|
},
|
|
2285
2383
|
lineart: {
|
|
2286
|
-
name: "Line Art Preprocessor",
|
|
2287
|
-
endpoint: "fal-ai/image-preprocessors/lineart",
|
|
2288
|
-
task: "image preprocessing",
|
|
2289
2384
|
category: "preprocess",
|
|
2385
|
+
defaultOptions: {
|
|
2386
|
+
coarse: false
|
|
2387
|
+
},
|
|
2290
2388
|
description: "Generate line art/control-style edges from an input image.",
|
|
2291
|
-
|
|
2389
|
+
endpoint: "fal-ai/image-preprocessors/lineart",
|
|
2292
2390
|
inputField: "image_url",
|
|
2391
|
+
inputKind: "image",
|
|
2392
|
+
name: "Line Art Preprocessor",
|
|
2293
2393
|
outputKeys: ["image"],
|
|
2294
2394
|
pricing: "$0/compute-second listed by fal",
|
|
2295
2395
|
sourceUrl: "https://fal.ai/models/fal-ai/image-preprocessors/lineart",
|
|
2296
|
-
|
|
2297
|
-
coarse: false
|
|
2298
|
-
}
|
|
2396
|
+
task: "image preprocessing"
|
|
2299
2397
|
},
|
|
2300
|
-
"
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2398
|
+
"marigold-depth": {
|
|
2399
|
+
category: "depth",
|
|
2400
|
+
defaultOptions: {
|
|
2401
|
+
ensemble_size: 10,
|
|
2402
|
+
num_inference_steps: 10
|
|
2403
|
+
},
|
|
2404
|
+
description: "Create depth maps using Marigold depth estimation.",
|
|
2405
|
+
endpoint: "fal-ai/imageutils/marigold-depth",
|
|
2307
2406
|
inputField: "image_url",
|
|
2407
|
+
inputKind: "image",
|
|
2408
|
+
name: "Marigold Depth Estimation",
|
|
2308
2409
|
outputKeys: ["image"],
|
|
2309
2410
|
pricing: "$0/compute-second listed by fal",
|
|
2310
|
-
sourceUrl: "https://fal.ai/models/fal-ai/
|
|
2411
|
+
sourceUrl: "https://fal.ai/models/fal-ai/imageutils/marigold-depth",
|
|
2412
|
+
task: "depth map"
|
|
2311
2413
|
},
|
|
2312
2414
|
"midas-depth": {
|
|
2313
|
-
name: "MiDaS Depth Estimation",
|
|
2314
|
-
endpoint: "fal-ai/imageutils/depth",
|
|
2315
|
-
task: "depth map",
|
|
2316
2415
|
category: "depth",
|
|
2416
|
+
defaultOptions: {
|
|
2417
|
+
a: Math.PI * 2,
|
|
2418
|
+
bg_th: 0.1
|
|
2419
|
+
},
|
|
2317
2420
|
description: "Create MiDaS depth maps from input images.",
|
|
2318
|
-
|
|
2421
|
+
endpoint: "fal-ai/imageutils/depth",
|
|
2319
2422
|
inputField: "image_url",
|
|
2423
|
+
inputKind: "image",
|
|
2424
|
+
name: "MiDaS Depth Estimation",
|
|
2320
2425
|
outputKeys: ["image"],
|
|
2321
2426
|
pricing: "$0/compute-second listed by fal",
|
|
2322
2427
|
sourceUrl: "https://fal.ai/models/fal-ai/imageutils/depth",
|
|
2323
|
-
|
|
2324
|
-
a: Math.PI * 2,
|
|
2325
|
-
bg_th: 0.1
|
|
2326
|
-
}
|
|
2428
|
+
task: "depth map"
|
|
2327
2429
|
},
|
|
2328
2430
|
"midas-preprocessor": {
|
|
2329
|
-
name: "MiDaS Preprocessor",
|
|
2330
|
-
endpoint: "fal-ai/image-preprocessors/midas",
|
|
2331
|
-
task: "depth and normal preprocessing",
|
|
2332
2431
|
category: "preprocess",
|
|
2333
2432
|
description: "Generate MiDaS depth and normal maps for image workflows.",
|
|
2334
|
-
|
|
2433
|
+
endpoint: "fal-ai/image-preprocessors/midas",
|
|
2335
2434
|
inputField: "image_url",
|
|
2435
|
+
inputKind: "image",
|
|
2436
|
+
name: "MiDaS Preprocessor",
|
|
2336
2437
|
outputKeys: ["depth_map", "normal_map"],
|
|
2337
2438
|
pricing: "$0/compute-second listed by fal",
|
|
2338
|
-
sourceUrl: "https://fal.ai/models/fal-ai/image-preprocessors/midas"
|
|
2439
|
+
sourceUrl: "https://fal.ai/models/fal-ai/image-preprocessors/midas",
|
|
2440
|
+
task: "depth and normal preprocessing"
|
|
2339
2441
|
},
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2442
|
+
nsfw: {
|
|
2443
|
+
category: "moderation",
|
|
2444
|
+
description: "Predict whether one or more images contain NSFW concepts.",
|
|
2445
|
+
endpoint: "fal-ai/x-ailab/nsfw",
|
|
2446
|
+
inputField: "image_urls",
|
|
2447
|
+
inputKind: "images",
|
|
2448
|
+
name: "NSFW Checker",
|
|
2449
|
+
outputKeys: ["has_nsfw_concepts"],
|
|
2450
|
+
pricing: "$0.001/image",
|
|
2451
|
+
sourceUrl: "https://fal.ai/models/fal-ai/x-ailab/nsfw",
|
|
2452
|
+
task: "vision moderation"
|
|
2453
|
+
},
|
|
2454
|
+
rembg: {
|
|
2455
|
+
category: "background",
|
|
2456
|
+
defaultOptions: {
|
|
2457
|
+
crop_to_bbox: false
|
|
2458
|
+
},
|
|
2459
|
+
description: "Generic image background removal utility.",
|
|
2460
|
+
endpoint: "fal-ai/imageutils/rembg",
|
|
2347
2461
|
inputField: "image_url",
|
|
2462
|
+
inputKind: "image",
|
|
2463
|
+
name: "Remove Background",
|
|
2348
2464
|
outputKeys: ["image"],
|
|
2349
2465
|
pricing: "$0/compute-second listed by fal",
|
|
2350
|
-
sourceUrl: "https://fal.ai/models/fal-ai/imageutils/
|
|
2351
|
-
|
|
2352
|
-
ensemble_size: 10,
|
|
2353
|
-
num_inference_steps: 10
|
|
2354
|
-
}
|
|
2466
|
+
sourceUrl: "https://fal.ai/models/fal-ai/imageutils/rembg",
|
|
2467
|
+
task: "image background removal"
|
|
2355
2468
|
},
|
|
2356
|
-
"
|
|
2357
|
-
name: "Depth Anything v2 Preprocessor",
|
|
2358
|
-
endpoint: "fal-ai/image-preprocessors/depth-anything/v2",
|
|
2359
|
-
task: "depth preprocessing",
|
|
2469
|
+
"sam-preprocessor": {
|
|
2360
2470
|
category: "preprocess",
|
|
2361
|
-
description: "Generate
|
|
2362
|
-
|
|
2471
|
+
description: "Generate a SAM segmentation map for ControlNet-style workflows.",
|
|
2472
|
+
endpoint: "fal-ai/image-preprocessors/sam",
|
|
2363
2473
|
inputField: "image_url",
|
|
2474
|
+
inputKind: "image",
|
|
2475
|
+
name: "SAM Preprocessor",
|
|
2364
2476
|
outputKeys: ["image"],
|
|
2365
2477
|
pricing: "$0/compute-second listed by fal",
|
|
2366
|
-
sourceUrl: "https://fal.ai/models/fal-ai/image-preprocessors/
|
|
2478
|
+
sourceUrl: "https://fal.ai/models/fal-ai/image-preprocessors/sam",
|
|
2479
|
+
task: "segmentation preprocessing"
|
|
2480
|
+
},
|
|
2481
|
+
"sam2-auto": {
|
|
2482
|
+
category: "segmentation",
|
|
2483
|
+
defaultOptions: {
|
|
2484
|
+
min_mask_region_area: 100,
|
|
2485
|
+
output_format: "png",
|
|
2486
|
+
points_per_side: 32,
|
|
2487
|
+
pred_iou_thresh: 0.88,
|
|
2488
|
+
stability_score_thresh: 0.95
|
|
2489
|
+
},
|
|
2490
|
+
description: "Automatically segment an image into combined and individual masks.",
|
|
2491
|
+
endpoint: "fal-ai/sam2/auto-segment",
|
|
2492
|
+
inputField: "image_url",
|
|
2493
|
+
inputKind: "image",
|
|
2494
|
+
name: "SAM 2 Auto Segment",
|
|
2495
|
+
outputKeys: ["combined_mask", "individual_masks"],
|
|
2496
|
+
pricing: "$0/compute-second listed by fal",
|
|
2497
|
+
sourceUrl: "https://fal.ai/models/fal-ai/sam2/auto-segment",
|
|
2498
|
+
task: "automatic image segmentation"
|
|
2499
|
+
},
|
|
2500
|
+
"sam3-1-image": {
|
|
2501
|
+
category: "segmentation",
|
|
2502
|
+
defaultOptions: {
|
|
2503
|
+
apply_mask: true,
|
|
2504
|
+
max_masks: 3,
|
|
2505
|
+
output_format: "png"
|
|
2506
|
+
},
|
|
2507
|
+
description: "Segment image objects with text, point, or box prompts. SAM 3.1 adds Object Multiplex for faster multi-object tracking.",
|
|
2508
|
+
endpoint: "fal-ai/sam-3-1/image",
|
|
2509
|
+
inputField: "image_url",
|
|
2510
|
+
inputKind: "image",
|
|
2511
|
+
name: "SAM 3.1 Image",
|
|
2512
|
+
outputKeys: ["image", "masks", "metadata", "scores", "boxes"],
|
|
2513
|
+
pricing: "$0.005/request",
|
|
2514
|
+
sourceUrl: "https://fal.ai/models/fal-ai/sam-3-1/image",
|
|
2515
|
+
task: "promptable image segmentation"
|
|
2516
|
+
},
|
|
2517
|
+
"sam3-1-video": {
|
|
2518
|
+
category: "segmentation",
|
|
2519
|
+
defaultOptions: {
|
|
2520
|
+
apply_mask: true,
|
|
2521
|
+
prompt: "person"
|
|
2522
|
+
},
|
|
2523
|
+
description: "SAM 3.1 video segmentation with Object Multiplex tracking for multiple objects.",
|
|
2524
|
+
endpoint: "fal-ai/sam-3-1/video",
|
|
2525
|
+
inputField: "video_url",
|
|
2526
|
+
inputKind: "video",
|
|
2527
|
+
name: "SAM 3.1 Video",
|
|
2528
|
+
outputKeys: ["video", "boundingbox_frames_zip"],
|
|
2529
|
+
pricing: "fal pricing varies by frame count",
|
|
2530
|
+
sourceUrl: "https://fal.ai/models/fal-ai/sam-3-1/video",
|
|
2531
|
+
task: "multi-object video segmentation"
|
|
2367
2532
|
},
|
|
2368
|
-
"
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
description: "Automatically segment an image into combined and individual masks.",
|
|
2533
|
+
"sam3-3d-align": {
|
|
2534
|
+
category: "3d",
|
|
2535
|
+
description: "Align SAM 3D objects and bodies into a shared scene.",
|
|
2536
|
+
endpoint: "fal-ai/sam-3/3d-align",
|
|
2537
|
+
inputField: "image_url",
|
|
2374
2538
|
inputKind: "image",
|
|
2539
|
+
name: "SAM 3D Align",
|
|
2540
|
+
outputKeys: ["scene_glb", "metadata", "artifacts_zip"],
|
|
2541
|
+
pricing: "fal pricing varies by scene",
|
|
2542
|
+
sourceUrl: "https://fal.ai/models/fal-ai/sam-3/3d-align",
|
|
2543
|
+
task: "3D scene alignment"
|
|
2544
|
+
},
|
|
2545
|
+
"sam3-3d-body": {
|
|
2546
|
+
category: "3d",
|
|
2547
|
+
defaultOptions: {
|
|
2548
|
+
export_meshes: true,
|
|
2549
|
+
include_3d_keypoints: true,
|
|
2550
|
+
include_mhr_params: true
|
|
2551
|
+
},
|
|
2552
|
+
description: "Reconstruct human body meshes and keypoints from a single image.",
|
|
2553
|
+
endpoint: "fal-ai/sam-3/3d-body",
|
|
2375
2554
|
inputField: "image_url",
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2555
|
+
inputKind: "image",
|
|
2556
|
+
name: "SAM 3D Body",
|
|
2557
|
+
outputKeys: ["model_glb", "visualization", "meshes", "metadata"],
|
|
2558
|
+
pricing: "$0.015/inference",
|
|
2559
|
+
sourceUrl: "https://fal.ai/models/fal-ai/sam-3/3d-body",
|
|
2560
|
+
task: "single-image 3D body reconstruction"
|
|
2561
|
+
},
|
|
2562
|
+
"sam3-3d-objects": {
|
|
2563
|
+
category: "3d",
|
|
2379
2564
|
defaultOptions: {
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2565
|
+
prompt: "car"
|
|
2566
|
+
},
|
|
2567
|
+
description: "Reconstruct one or more 3D objects from an image and prompts.",
|
|
2568
|
+
endpoint: "fal-ai/sam-3/3d-objects",
|
|
2569
|
+
inputField: "image_url",
|
|
2570
|
+
inputKind: "image",
|
|
2571
|
+
name: "SAM 3D Objects",
|
|
2572
|
+
outputKeys: [
|
|
2573
|
+
"gaussian_splat",
|
|
2574
|
+
"model_glb",
|
|
2575
|
+
"metadata",
|
|
2576
|
+
"individual_splats",
|
|
2577
|
+
"individual_glbs",
|
|
2578
|
+
"artifacts_zip"
|
|
2579
|
+
],
|
|
2580
|
+
pricing: "$0.02/generation",
|
|
2581
|
+
sourceUrl: "https://fal.ai/models/fal-ai/sam-3/3d-objects",
|
|
2582
|
+
task: "single-image 3D object reconstruction"
|
|
2386
2583
|
},
|
|
2387
2584
|
"sam3-image": {
|
|
2388
|
-
name: "SAM 3 Image",
|
|
2389
|
-
endpoint: "fal-ai/sam-3/image",
|
|
2390
|
-
task: "promptable image segmentation",
|
|
2391
2585
|
category: "segmentation",
|
|
2392
|
-
description: "Segment image objects with text, point, or box prompts.",
|
|
2393
|
-
inputKind: "image",
|
|
2394
|
-
inputField: "image_url",
|
|
2395
|
-
outputKeys: ["image", "masks", "metadata", "scores", "boxes"],
|
|
2396
|
-
pricing: "$0.005/request",
|
|
2397
|
-
sourceUrl: "https://fal.ai/models/fal-ai/sam-3/image",
|
|
2398
2586
|
defaultOptions: {
|
|
2399
2587
|
apply_mask: true,
|
|
2400
2588
|
max_masks: 3,
|
|
2401
2589
|
output_format: "png"
|
|
2402
|
-
}
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
name: "SAM 3.1 Image",
|
|
2406
|
-
endpoint: "fal-ai/sam-3-1/image",
|
|
2407
|
-
task: "promptable image segmentation",
|
|
2408
|
-
category: "segmentation",
|
|
2409
|
-
description: "Segment image objects with text, point, or box prompts. SAM 3.1 adds Object Multiplex for faster multi-object tracking.",
|
|
2410
|
-
inputKind: "image",
|
|
2590
|
+
},
|
|
2591
|
+
description: "Segment image objects with text, point, or box prompts.",
|
|
2592
|
+
endpoint: "fal-ai/sam-3/image",
|
|
2411
2593
|
inputField: "image_url",
|
|
2594
|
+
inputKind: "image",
|
|
2595
|
+
name: "SAM 3 Image",
|
|
2412
2596
|
outputKeys: ["image", "masks", "metadata", "scores", "boxes"],
|
|
2413
2597
|
pricing: "$0.005/request",
|
|
2414
|
-
sourceUrl: "https://fal.ai/models/fal-ai/sam-3
|
|
2415
|
-
|
|
2416
|
-
apply_mask: true,
|
|
2417
|
-
max_masks: 3,
|
|
2418
|
-
output_format: "png"
|
|
2419
|
-
}
|
|
2598
|
+
sourceUrl: "https://fal.ai/models/fal-ai/sam-3/image",
|
|
2599
|
+
task: "promptable image segmentation"
|
|
2420
2600
|
},
|
|
2421
2601
|
"sam3-image-rle": {
|
|
2422
|
-
name: "SAM 3 Image RLE",
|
|
2423
|
-
endpoint: "fal-ai/sam-3/image-rle",
|
|
2424
|
-
task: "promptable image segmentation to RLE",
|
|
2425
2602
|
category: "segmentation",
|
|
2603
|
+
defaultOptions: {
|
|
2604
|
+
apply_mask: true,
|
|
2605
|
+
max_masks: 3
|
|
2606
|
+
},
|
|
2426
2607
|
description: "Segment image objects and return run-length encoded masks.",
|
|
2427
|
-
|
|
2608
|
+
endpoint: "fal-ai/sam-3/image-rle",
|
|
2428
2609
|
inputField: "image_url",
|
|
2610
|
+
inputKind: "image",
|
|
2611
|
+
name: "SAM 3 Image RLE",
|
|
2429
2612
|
outputKeys: ["rle_masks", "metadata", "scores", "boxes"],
|
|
2430
2613
|
pricing: "$0.005/request",
|
|
2431
2614
|
sourceUrl: "https://fal.ai/models/fal-ai/sam-3/image-rle",
|
|
2432
|
-
|
|
2433
|
-
apply_mask: true,
|
|
2434
|
-
max_masks: 3
|
|
2435
|
-
}
|
|
2615
|
+
task: "promptable image segmentation to RLE"
|
|
2436
2616
|
},
|
|
2437
2617
|
"sam3-video": {
|
|
2438
|
-
name: "SAM 3 Video",
|
|
2439
|
-
endpoint: "fal-ai/sam-3/video",
|
|
2440
|
-
task: "promptable video segmentation",
|
|
2441
2618
|
category: "segmentation",
|
|
2442
|
-
description: "Segment and track prompted objects across video frames.",
|
|
2443
|
-
inputKind: "video",
|
|
2444
|
-
inputField: "video_url",
|
|
2445
|
-
outputKeys: ["video", "boundingbox_frames_zip"],
|
|
2446
|
-
pricing: "$0.005/16 frames",
|
|
2447
|
-
sourceUrl: "https://fal.ai/models/fal-ai/sam-3/video",
|
|
2448
2619
|
defaultOptions: {
|
|
2449
2620
|
apply_mask: true,
|
|
2450
2621
|
detection_threshold: 0.5,
|
|
2451
2622
|
prompt: "person",
|
|
2452
2623
|
video_output_type: "X264 (.mp4)"
|
|
2453
|
-
}
|
|
2624
|
+
},
|
|
2625
|
+
description: "Segment and track prompted objects across video frames.",
|
|
2626
|
+
endpoint: "fal-ai/sam-3/video",
|
|
2627
|
+
inputField: "video_url",
|
|
2628
|
+
inputKind: "video",
|
|
2629
|
+
name: "SAM 3 Video",
|
|
2630
|
+
outputKeys: ["video", "boundingbox_frames_zip"],
|
|
2631
|
+
pricing: "$0.005/16 frames",
|
|
2632
|
+
sourceUrl: "https://fal.ai/models/fal-ai/sam-3/video",
|
|
2633
|
+
task: "promptable video segmentation"
|
|
2454
2634
|
},
|
|
2455
2635
|
"sam3-video-rle": {
|
|
2456
|
-
name: "SAM 3 Video RLE",
|
|
2457
|
-
endpoint: "fal-ai/sam-3/video-rle",
|
|
2458
|
-
task: "promptable video segmentation to RLE",
|
|
2459
2636
|
category: "segmentation",
|
|
2637
|
+
defaultOptions: {
|
|
2638
|
+
apply_mask: true,
|
|
2639
|
+
detection_threshold: 0.5,
|
|
2640
|
+
prompt: "person"
|
|
2641
|
+
},
|
|
2460
2642
|
description: "Track prompted video objects and return RLE mask data.",
|
|
2461
|
-
|
|
2643
|
+
endpoint: "fal-ai/sam-3/video-rle",
|
|
2462
2644
|
inputField: "video_url",
|
|
2645
|
+
inputKind: "video",
|
|
2646
|
+
name: "SAM 3 Video RLE",
|
|
2463
2647
|
outputKeys: ["rle_masks", "metadata"],
|
|
2464
2648
|
pricing: "$0.005/16 frames",
|
|
2465
2649
|
sourceUrl: "https://fal.ai/models/fal-ai/sam-3/video-rle",
|
|
2466
|
-
|
|
2467
|
-
apply_mask: true,
|
|
2468
|
-
detection_threshold: 0.5,
|
|
2469
|
-
prompt: "person"
|
|
2470
|
-
}
|
|
2650
|
+
task: "promptable video segmentation to RLE"
|
|
2471
2651
|
},
|
|
2472
|
-
"
|
|
2473
|
-
|
|
2474
|
-
endpoint: "fal-ai/sam-3-1/video",
|
|
2475
|
-
task: "multi-object video segmentation",
|
|
2476
|
-
category: "segmentation",
|
|
2477
|
-
description: "SAM 3.1 video segmentation with Object Multiplex tracking for multiple objects.",
|
|
2478
|
-
inputKind: "video",
|
|
2479
|
-
inputField: "video_url",
|
|
2480
|
-
outputKeys: ["video", "boundingbox_frames_zip"],
|
|
2481
|
-
pricing: "fal pricing varies by frame count",
|
|
2482
|
-
sourceUrl: "https://fal.ai/models/fal-ai/sam-3-1/video",
|
|
2652
|
+
"topaz-image": {
|
|
2653
|
+
category: "upscale",
|
|
2483
2654
|
defaultOptions: {
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
endpoint: "fal-ai/sam-3/3d-objects",
|
|
2491
|
-
task: "single-image 3D object reconstruction",
|
|
2492
|
-
category: "3d",
|
|
2493
|
-
description: "Reconstruct one or more 3D objects from an image and prompts.",
|
|
2494
|
-
inputKind: "image",
|
|
2655
|
+
model: "Standard V2",
|
|
2656
|
+
output_format: "jpeg",
|
|
2657
|
+
upscale_factor: 2
|
|
2658
|
+
},
|
|
2659
|
+
description: "Professional Topaz image enhancement and upscaling.",
|
|
2660
|
+
endpoint: "fal-ai/topaz/upscale/image",
|
|
2495
2661
|
inputField: "image_url",
|
|
2496
|
-
outputKeys: [
|
|
2497
|
-
"gaussian_splat",
|
|
2498
|
-
"model_glb",
|
|
2499
|
-
"metadata",
|
|
2500
|
-
"individual_splats",
|
|
2501
|
-
"individual_glbs",
|
|
2502
|
-
"artifacts_zip"
|
|
2503
|
-
],
|
|
2504
|
-
pricing: "$0.02/generation",
|
|
2505
|
-
sourceUrl: "https://fal.ai/models/fal-ai/sam-3/3d-objects",
|
|
2506
|
-
defaultOptions: {
|
|
2507
|
-
prompt: "car"
|
|
2508
|
-
}
|
|
2509
|
-
},
|
|
2510
|
-
"sam3-3d-body": {
|
|
2511
|
-
name: "SAM 3D Body",
|
|
2512
|
-
endpoint: "fal-ai/sam-3/3d-body",
|
|
2513
|
-
task: "single-image 3D body reconstruction",
|
|
2514
|
-
category: "3d",
|
|
2515
|
-
description: "Reconstruct human body meshes and keypoints from a single image.",
|
|
2516
2662
|
inputKind: "image",
|
|
2517
|
-
|
|
2518
|
-
outputKeys: ["
|
|
2519
|
-
pricing: "$0.
|
|
2520
|
-
sourceUrl: "https://fal.ai/models/fal-ai/
|
|
2521
|
-
|
|
2522
|
-
export_meshes: true,
|
|
2523
|
-
include_3d_keypoints: true,
|
|
2524
|
-
include_mhr_params: true
|
|
2525
|
-
}
|
|
2663
|
+
name: "Topaz Image Upscale",
|
|
2664
|
+
outputKeys: ["image"],
|
|
2665
|
+
pricing: "$0.08+ by output megapixels",
|
|
2666
|
+
sourceUrl: "https://fal.ai/models/fal-ai/topaz/upscale/image",
|
|
2667
|
+
task: "image enhancement"
|
|
2526
2668
|
},
|
|
2527
|
-
"
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2669
|
+
"topaz-video": {
|
|
2670
|
+
category: "upscale",
|
|
2671
|
+
defaultOptions: {
|
|
2672
|
+
model: "Proteus",
|
|
2673
|
+
upscale_factor: 2
|
|
2674
|
+
},
|
|
2675
|
+
description: "Professional Topaz video enhancement and upscaling.",
|
|
2676
|
+
endpoint: "fal-ai/topaz/upscale/video",
|
|
2677
|
+
inputField: "video_url",
|
|
2678
|
+
inputKind: "video",
|
|
2679
|
+
name: "Topaz Video Upscale",
|
|
2680
|
+
outputKeys: ["video"],
|
|
2681
|
+
pricing: "$0.01-$0.08/sec by output resolution",
|
|
2682
|
+
sourceUrl: "https://fal.ai/models/fal-ai/topaz/upscale/video",
|
|
2683
|
+
task: "video enhancement"
|
|
2538
2684
|
}
|
|
2539
2685
|
};
|
|
2540
2686
|
var FAL_TOOLS_CHECKED_AT = FAL_EXPLORE_CHECKED_AT;
|
|
2541
|
-
var FAL_TOOL_IDS = Object.keys(
|
|
2687
|
+
var FAL_TOOL_IDS = Object.keys(
|
|
2688
|
+
FAL_TOOLS
|
|
2689
|
+
);
|
|
2542
2690
|
function isFalToolId(tool) {
|
|
2543
2691
|
return Object.hasOwn(FAL_TOOLS, tool);
|
|
2544
2692
|
}
|
|
@@ -2547,7 +2695,7 @@ function buildFalToolRequest(options) {
|
|
|
2547
2695
|
throw new Error(`Unknown fal tool: ${options.tool}`);
|
|
2548
2696
|
}
|
|
2549
2697
|
const tool = FAL_TOOLS[options.tool];
|
|
2550
|
-
const values = options.inputs ?? (options.input ? [options.input] : []);
|
|
2698
|
+
const values = options.inputs ?? (options.input !== void 0 && options.input !== "" ? [options.input] : []);
|
|
2551
2699
|
if (values.length === 0) {
|
|
2552
2700
|
throw new Error(`${options.tool} requires input media`);
|
|
2553
2701
|
}
|
|
@@ -2558,7 +2706,7 @@ function buildFalToolRequest(options) {
|
|
|
2558
2706
|
...options.options,
|
|
2559
2707
|
[tool.inputField]: mediaValue
|
|
2560
2708
|
};
|
|
2561
|
-
return { endpoint: tool.endpoint,
|
|
2709
|
+
return { body, endpoint: tool.endpoint, tool };
|
|
2562
2710
|
}
|
|
2563
2711
|
|
|
2564
2712
|
// src/server.ts
|
|
@@ -2566,16 +2714,6 @@ var FAL_BASE_URL = "https://fal.run";
|
|
|
2566
2714
|
var FAL_QUEUE_URL = "https://queue.fal.run";
|
|
2567
2715
|
var FAL_API_URL = "https://api.fal.ai";
|
|
2568
2716
|
var FAL_REST_URL = "https://rest.alpha.fal.ai";
|
|
2569
|
-
function endpointFromQueueUrl(url, fallback) {
|
|
2570
|
-
if (!url) return fallback;
|
|
2571
|
-
try {
|
|
2572
|
-
const parsed = new URL(url);
|
|
2573
|
-
const match = parsed.pathname.match(/^\/(.+)\/requests\//);
|
|
2574
|
-
return match?.[1] ?? fallback;
|
|
2575
|
-
} catch {
|
|
2576
|
-
return fallback;
|
|
2577
|
-
}
|
|
2578
|
-
}
|
|
2579
2717
|
var MotifServer = class {
|
|
2580
2718
|
apiKey;
|
|
2581
2719
|
timeout;
|
|
@@ -2598,8 +2736,8 @@ var MotifServer = class {
|
|
|
2598
2736
|
/** Generate images synchronously (blocks until fal.ai returns). */
|
|
2599
2737
|
async generate(options) {
|
|
2600
2738
|
const config = MODELS[options.model];
|
|
2601
|
-
if (config?.useQueue) {
|
|
2602
|
-
return this.generateQueued(options);
|
|
2739
|
+
if (config?.useQueue === true) {
|
|
2740
|
+
return await this.generateQueued(options);
|
|
2603
2741
|
}
|
|
2604
2742
|
let built;
|
|
2605
2743
|
try {
|
|
@@ -2609,9 +2747,9 @@ var MotifServer = class {
|
|
|
2609
2747
|
}
|
|
2610
2748
|
const { endpoint, body } = built;
|
|
2611
2749
|
const response = await this.request(`${FAL_BASE_URL}/${endpoint}`, {
|
|
2612
|
-
method: "POST",
|
|
2613
2750
|
body: JSON.stringify(body),
|
|
2614
|
-
headers: this.ephemeralHeaders(options)
|
|
2751
|
+
headers: this.ephemeralHeaders(options),
|
|
2752
|
+
method: "POST"
|
|
2615
2753
|
});
|
|
2616
2754
|
if (response.isErr()) {
|
|
2617
2755
|
return (0, import_neverthrow.err)(response.error);
|
|
@@ -2635,14 +2773,15 @@ var MotifServer = class {
|
|
|
2635
2773
|
return (0, import_neverthrow.err)(status.error);
|
|
2636
2774
|
}
|
|
2637
2775
|
if (status.value.status === "completed") {
|
|
2638
|
-
return this.getJobResult(job.value.endpoint, job.value.requestId);
|
|
2776
|
+
return await this.getJobResult(job.value.endpoint, job.value.requestId);
|
|
2639
2777
|
}
|
|
2640
2778
|
if (status.value.status === "failed") {
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
);
|
|
2779
|
+
const message = status.value.error ?? "Queued generation failed";
|
|
2780
|
+
return (0, import_neverthrow.err)(new MotifError(message, 0, void 0, job.value.requestId));
|
|
2644
2781
|
}
|
|
2645
|
-
await new Promise((resolve) =>
|
|
2782
|
+
await new Promise((resolve) => {
|
|
2783
|
+
setTimeout(resolve, pollIntervalMs);
|
|
2784
|
+
});
|
|
2646
2785
|
}
|
|
2647
2786
|
return (0, import_neverthrow.err)(new MotifError("Queued generation timed out", 0));
|
|
2648
2787
|
}
|
|
@@ -2657,22 +2796,23 @@ var MotifServer = class {
|
|
|
2657
2796
|
}
|
|
2658
2797
|
const { endpoint, body } = built;
|
|
2659
2798
|
const response = await this.request(`${FAL_QUEUE_URL}/${endpoint}`, {
|
|
2660
|
-
method: "POST",
|
|
2661
2799
|
body: JSON.stringify(body),
|
|
2662
|
-
headers: this.ephemeralHeaders(options)
|
|
2800
|
+
headers: this.ephemeralHeaders(options),
|
|
2801
|
+
method: "POST"
|
|
2663
2802
|
});
|
|
2664
2803
|
if (response.isErr()) {
|
|
2665
2804
|
return (0, import_neverthrow.err)(response.error);
|
|
2666
2805
|
}
|
|
2667
2806
|
const data = await response.value.json();
|
|
2807
|
+
const submission = parseQueueSubmission(data);
|
|
2668
2808
|
return (0, import_neverthrow.ok)({
|
|
2669
|
-
|
|
2670
|
-
endpoint: endpointFromQueueUrl(data.response_url, endpoint),
|
|
2809
|
+
endpoint: endpointFromQueueUrl(submission.responseUrl, endpoint),
|
|
2671
2810
|
estimatedCost: estimateCost(
|
|
2672
2811
|
options.model,
|
|
2673
2812
|
options.resolution,
|
|
2674
2813
|
options.numImages
|
|
2675
|
-
)
|
|
2814
|
+
),
|
|
2815
|
+
requestId: submission.requestId
|
|
2676
2816
|
});
|
|
2677
2817
|
}
|
|
2678
2818
|
/** Check the status of a queued generation. */
|
|
@@ -2683,23 +2823,25 @@ var MotifServer = class {
|
|
|
2683
2823
|
return (0, import_neverthrow.err)(response.error);
|
|
2684
2824
|
}
|
|
2685
2825
|
const data = await response.value.json();
|
|
2826
|
+
const record = isRecord(data) ? data : {};
|
|
2827
|
+
const rawStatus = asString(record.status);
|
|
2686
2828
|
let status;
|
|
2687
|
-
if (
|
|
2829
|
+
if (rawStatus === "IN_QUEUE") {
|
|
2688
2830
|
status = "queued";
|
|
2689
|
-
} else if (
|
|
2831
|
+
} else if (rawStatus === "IN_PROGRESS") {
|
|
2690
2832
|
status = "processing";
|
|
2691
|
-
} else if (
|
|
2833
|
+
} else if (rawStatus === "COMPLETED") {
|
|
2692
2834
|
status = "completed";
|
|
2693
|
-
} else if (
|
|
2835
|
+
} else if (rawStatus === "FAILED" || rawStatus === "ERROR" || rawStatus === "CANCELED") {
|
|
2694
2836
|
status = "failed";
|
|
2695
2837
|
} else {
|
|
2696
|
-
return (0, import_neverthrow.err)(new MotifError(`Unknown job status: ${
|
|
2838
|
+
return (0, import_neverthrow.err)(new MotifError(`Unknown job status: ${rawStatus}`, 0));
|
|
2697
2839
|
}
|
|
2698
2840
|
return (0, import_neverthrow.ok)({
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
queuePosition:
|
|
2702
|
-
|
|
2841
|
+
error: asString(record.error) ?? asString(record.detail),
|
|
2842
|
+
logs: parseLogs(record.logs),
|
|
2843
|
+
queuePosition: asNumber(record.queue_position),
|
|
2844
|
+
status
|
|
2703
2845
|
});
|
|
2704
2846
|
}
|
|
2705
2847
|
/** Fetch the completed result from the queue. */
|
|
@@ -2732,21 +2874,38 @@ var MotifServer = class {
|
|
|
2732
2874
|
}
|
|
2733
2875
|
const body = { image_url: imageUrl };
|
|
2734
2876
|
if (model === "crystal") {
|
|
2735
|
-
if (scaleFactor !== void 0)
|
|
2736
|
-
|
|
2877
|
+
if (scaleFactor !== void 0) {
|
|
2878
|
+
body.scale_factor = scaleFactor;
|
|
2879
|
+
}
|
|
2880
|
+
if (creativity !== void 0) {
|
|
2881
|
+
body.creativity = creativity;
|
|
2882
|
+
}
|
|
2737
2883
|
} else {
|
|
2738
|
-
if (scaleFactor !== void 0)
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
if (
|
|
2742
|
-
|
|
2743
|
-
|
|
2884
|
+
if (scaleFactor !== void 0) {
|
|
2885
|
+
body.upscale_factor = scaleFactor;
|
|
2886
|
+
}
|
|
2887
|
+
if (creativity !== void 0) {
|
|
2888
|
+
body.creativity = creativity;
|
|
2889
|
+
}
|
|
2890
|
+
if (resemblance !== void 0) {
|
|
2891
|
+
body.resemblance = resemblance;
|
|
2892
|
+
}
|
|
2893
|
+
if (upscalePrompt !== void 0 && upscalePrompt !== "") {
|
|
2894
|
+
body.prompt = upscalePrompt;
|
|
2895
|
+
}
|
|
2896
|
+
if (negativePrompt !== void 0 && negativePrompt !== "") {
|
|
2897
|
+
body.negative_prompt = negativePrompt;
|
|
2898
|
+
}
|
|
2899
|
+
if (numInferenceSteps !== void 0) {
|
|
2744
2900
|
body.num_inference_steps = numInferenceSteps;
|
|
2745
|
-
|
|
2901
|
+
}
|
|
2902
|
+
if (guidanceScale !== void 0) {
|
|
2903
|
+
body.guidance_scale = guidanceScale;
|
|
2904
|
+
}
|
|
2746
2905
|
}
|
|
2747
2906
|
const response = await this.request(`${FAL_BASE_URL}/${config.endpoint}`, {
|
|
2748
|
-
|
|
2749
|
-
|
|
2907
|
+
body: JSON.stringify(body),
|
|
2908
|
+
method: "POST"
|
|
2750
2909
|
});
|
|
2751
2910
|
if (response.isErr()) {
|
|
2752
2911
|
return (0, import_neverthrow.err)(response.error);
|
|
@@ -2773,17 +2932,25 @@ var MotifServer = class {
|
|
|
2773
2932
|
}
|
|
2774
2933
|
const rbBody = { image_url: imageUrl };
|
|
2775
2934
|
if (model === "rmbg") {
|
|
2776
|
-
if (variant)
|
|
2777
|
-
|
|
2935
|
+
if (variant) {
|
|
2936
|
+
rbBody.model = variant;
|
|
2937
|
+
}
|
|
2938
|
+
if (operatingResolution) {
|
|
2778
2939
|
rbBody.operating_resolution = operatingResolution;
|
|
2779
|
-
|
|
2780
|
-
if (
|
|
2940
|
+
}
|
|
2941
|
+
if (outputFormat) {
|
|
2942
|
+
rbBody.output_format = outputFormat;
|
|
2943
|
+
}
|
|
2944
|
+
if (refineForeground !== void 0) {
|
|
2781
2945
|
rbBody.refine_foreground = refineForeground;
|
|
2782
|
-
|
|
2946
|
+
}
|
|
2947
|
+
if (outputMask !== void 0) {
|
|
2948
|
+
rbBody.output_mask = outputMask;
|
|
2949
|
+
}
|
|
2783
2950
|
}
|
|
2784
2951
|
const response = await this.request(`${FAL_BASE_URL}/${config.endpoint}`, {
|
|
2785
|
-
|
|
2786
|
-
|
|
2952
|
+
body: JSON.stringify(rbBody),
|
|
2953
|
+
method: "POST"
|
|
2787
2954
|
});
|
|
2788
2955
|
if (response.isErr()) {
|
|
2789
2956
|
return (0, import_neverthrow.err)(response.error);
|
|
@@ -2812,28 +2979,33 @@ var MotifServer = class {
|
|
|
2812
2979
|
return (0, import_neverthrow.err)(new MotifError("Kling video model not found", 0));
|
|
2813
2980
|
}
|
|
2814
2981
|
const body = {
|
|
2815
|
-
start_image_url: imageUrl,
|
|
2816
|
-
prompt,
|
|
2817
2982
|
duration: String(duration),
|
|
2818
|
-
generate_audio: generateAudio
|
|
2983
|
+
generate_audio: generateAudio,
|
|
2984
|
+
prompt,
|
|
2985
|
+
start_image_url: imageUrl
|
|
2819
2986
|
};
|
|
2820
|
-
if (endImageUrl) {
|
|
2987
|
+
if (endImageUrl !== void 0 && endImageUrl !== "") {
|
|
2821
2988
|
body.end_image_url = endImageUrl;
|
|
2822
2989
|
}
|
|
2823
|
-
if (negativePrompt
|
|
2824
|
-
|
|
2990
|
+
if (negativePrompt !== void 0 && negativePrompt !== "") {
|
|
2991
|
+
body.negative_prompt = negativePrompt;
|
|
2992
|
+
}
|
|
2993
|
+
if (cfgScale !== void 0) {
|
|
2994
|
+
body.cfg_scale = cfgScale;
|
|
2995
|
+
}
|
|
2825
2996
|
const response = await this.request(`${FAL_QUEUE_URL}/${config.endpoint}`, {
|
|
2826
|
-
|
|
2827
|
-
|
|
2997
|
+
body: JSON.stringify(body),
|
|
2998
|
+
method: "POST"
|
|
2828
2999
|
});
|
|
2829
3000
|
if (response.isErr()) {
|
|
2830
3001
|
return (0, import_neverthrow.err)(response.error);
|
|
2831
3002
|
}
|
|
2832
3003
|
const data = await response.value.json();
|
|
3004
|
+
const submission = parseQueueSubmission(data);
|
|
2833
3005
|
return (0, import_neverthrow.ok)({
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
3006
|
+
endpoint: endpointFromQueueUrl(submission.responseUrl, config.endpoint),
|
|
3007
|
+
estimatedCost: estimateVideoCost(duration, generateAudio),
|
|
3008
|
+
requestId: submission.requestId
|
|
2837
3009
|
});
|
|
2838
3010
|
}
|
|
2839
3011
|
/** Fetch the completed video result from the queue. */
|
|
@@ -2844,14 +3016,15 @@ var MotifServer = class {
|
|
|
2844
3016
|
return (0, import_neverthrow.err)(response.error);
|
|
2845
3017
|
}
|
|
2846
3018
|
const data = await response.value.json();
|
|
2847
|
-
|
|
3019
|
+
const video = isRecord(data) && isRecord(data.video) ? data.video : void 0;
|
|
3020
|
+
if (video === void 0) {
|
|
2848
3021
|
return (0, import_neverthrow.err)(new MotifError("No video in response", 0));
|
|
2849
3022
|
}
|
|
2850
3023
|
return (0, import_neverthrow.ok)({
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
3024
|
+
contentType: asString(video.content_type) ?? "",
|
|
3025
|
+
fileName: asString(video.file_name) ?? "",
|
|
3026
|
+
fileSize: asNumber(video.file_size) ?? 0,
|
|
3027
|
+
url: asString(video.url) ?? ""
|
|
2855
3028
|
});
|
|
2856
3029
|
}
|
|
2857
3030
|
/** ─── File Upload ─────────────────────────────────────────── */
|
|
@@ -2863,26 +3036,33 @@ var MotifServer = class {
|
|
|
2863
3036
|
const initiateResponse = await this.request(
|
|
2864
3037
|
`${FAL_REST_URL}/storage/upload/initiate?storage_type=fal-cdn-v3`,
|
|
2865
3038
|
{
|
|
2866
|
-
method: "POST",
|
|
2867
3039
|
body: JSON.stringify({
|
|
2868
3040
|
content_type: options.contentType,
|
|
2869
3041
|
file_name: options.fileName
|
|
2870
|
-
})
|
|
3042
|
+
}),
|
|
3043
|
+
method: "POST"
|
|
2871
3044
|
}
|
|
2872
3045
|
);
|
|
2873
3046
|
if (initiateResponse.isErr()) {
|
|
2874
3047
|
return (0, import_neverthrow.err)(initiateResponse.error);
|
|
2875
3048
|
}
|
|
2876
|
-
const
|
|
3049
|
+
const initiateData = await initiateResponse.value.json();
|
|
3050
|
+
const fileUrl = isRecord(initiateData) ? asString(initiateData.file_url) ?? "" : "";
|
|
3051
|
+
const uploadUrl = isRecord(initiateData) ? asString(initiateData.upload_url) : void 0;
|
|
3052
|
+
if (uploadUrl === void 0 || uploadUrl === "") {
|
|
3053
|
+
return (0, import_neverthrow.err)(
|
|
3054
|
+
new MotifError("Upload initiate response missing upload_url", 0)
|
|
3055
|
+
);
|
|
3056
|
+
}
|
|
2877
3057
|
let putResponse;
|
|
2878
3058
|
try {
|
|
2879
3059
|
const body = Buffer.from(
|
|
2880
3060
|
file instanceof Uint8Array ? file : new Uint8Array(file)
|
|
2881
3061
|
);
|
|
2882
|
-
putResponse = await fetch(
|
|
2883
|
-
|
|
3062
|
+
putResponse = await fetch(uploadUrl, {
|
|
3063
|
+
body,
|
|
2884
3064
|
headers: { "Content-Type": options.contentType },
|
|
2885
|
-
|
|
3065
|
+
method: "PUT"
|
|
2886
3066
|
});
|
|
2887
3067
|
} catch (error) {
|
|
2888
3068
|
return (0, import_neverthrow.err)(
|
|
@@ -2900,7 +3080,7 @@ var MotifServer = class {
|
|
|
2900
3080
|
)
|
|
2901
3081
|
);
|
|
2902
3082
|
}
|
|
2903
|
-
return (0, import_neverthrow.ok)(
|
|
3083
|
+
return (0, import_neverthrow.ok)(fileUrl);
|
|
2904
3084
|
}
|
|
2905
3085
|
/** ─── Utilities ───────────────────────────────────────────── */
|
|
2906
3086
|
/** Run a registered fal utility/tool endpoint. */
|
|
@@ -2917,13 +3097,14 @@ var MotifServer = class {
|
|
|
2917
3097
|
);
|
|
2918
3098
|
}
|
|
2919
3099
|
const response = await this.request(`${FAL_BASE_URL}/${request.endpoint}`, {
|
|
2920
|
-
|
|
2921
|
-
|
|
3100
|
+
body: JSON.stringify(request.body),
|
|
3101
|
+
method: "POST"
|
|
2922
3102
|
});
|
|
2923
3103
|
if (response.isErr()) {
|
|
2924
3104
|
return (0, import_neverthrow.err)(response.error);
|
|
2925
3105
|
}
|
|
2926
|
-
|
|
3106
|
+
const data = await response.value.json();
|
|
3107
|
+
return (0, import_neverthrow.ok)(isRecord(data) ? data : {});
|
|
2927
3108
|
}
|
|
2928
3109
|
/**
|
|
2929
3110
|
* Delete fal's stored IO payloads for a completed request.
|
|
@@ -2940,7 +3121,7 @@ var MotifServer = class {
|
|
|
2940
3121
|
if (response.isErr()) {
|
|
2941
3122
|
return (0, import_neverthrow.err)(response.error);
|
|
2942
3123
|
}
|
|
2943
|
-
return (0, import_neverthrow.ok)(
|
|
3124
|
+
return (0, import_neverthrow.ok)();
|
|
2944
3125
|
}
|
|
2945
3126
|
/** Estimate cost for a generation (no API call). */
|
|
2946
3127
|
estimateCost(model, resolution, numImages) {
|
|
@@ -2972,30 +3153,33 @@ var MotifServer = class {
|
|
|
2972
3153
|
let lastError = null;
|
|
2973
3154
|
for (let attempt = 0; attempt <= this.retries; attempt++) {
|
|
2974
3155
|
const controller = new AbortController();
|
|
2975
|
-
const timeoutId = setTimeout(() =>
|
|
3156
|
+
const timeoutId = setTimeout(() => {
|
|
3157
|
+
controller.abort();
|
|
3158
|
+
}, this.timeout);
|
|
2976
3159
|
try {
|
|
2977
3160
|
const response = await fetch(url, {
|
|
2978
3161
|
...options,
|
|
2979
|
-
signal: controller.signal,
|
|
2980
3162
|
headers: {
|
|
2981
3163
|
Authorization: `Key ${this.apiKey}`,
|
|
2982
3164
|
"Content-Type": "application/json",
|
|
2983
|
-
...options.headers
|
|
2984
|
-
}
|
|
3165
|
+
...toHeaderRecord(options.headers)
|
|
3166
|
+
},
|
|
3167
|
+
signal: controller.signal
|
|
2985
3168
|
});
|
|
2986
3169
|
clearTimeout(timeoutId);
|
|
2987
3170
|
if ((response.status === 429 || response.status >= 500) && attempt < this.retries) {
|
|
2988
3171
|
const delay = 1e3 * 2 ** attempt;
|
|
2989
|
-
await new Promise((r) =>
|
|
3172
|
+
await new Promise((r) => {
|
|
3173
|
+
setTimeout(r, delay);
|
|
3174
|
+
});
|
|
2990
3175
|
continue;
|
|
2991
3176
|
}
|
|
2992
3177
|
if (!response.ok) {
|
|
2993
3178
|
const text = await response.text();
|
|
3179
|
+
const message = `Request failed: ${response.status} ${text}`;
|
|
3180
|
+
const requestId = response.headers.get("x-fal-request-id") ?? requestIdFromBody(text);
|
|
2994
3181
|
return (0, import_neverthrow.err)(
|
|
2995
|
-
new MotifError(
|
|
2996
|
-
`Request failed: ${response.status} ${text}`,
|
|
2997
|
-
response.status
|
|
2998
|
-
)
|
|
3182
|
+
new MotifError(message, response.status, void 0, requestId)
|
|
2999
3183
|
);
|
|
3000
3184
|
}
|
|
3001
3185
|
return (0, import_neverthrow.ok)(response);
|
|
@@ -3010,49 +3194,60 @@ var MotifServer = class {
|
|
|
3010
3194
|
);
|
|
3011
3195
|
if (attempt < this.retries) {
|
|
3012
3196
|
const delay = 1e3 * 2 ** attempt;
|
|
3013
|
-
await new Promise((r) =>
|
|
3197
|
+
await new Promise((r) => {
|
|
3198
|
+
setTimeout(r, delay);
|
|
3199
|
+
});
|
|
3014
3200
|
}
|
|
3015
3201
|
}
|
|
3016
3202
|
}
|
|
3017
3203
|
return (0, import_neverthrow.err)(lastError ?? new MotifError("Request failed after retries", 0));
|
|
3018
3204
|
}
|
|
3019
3205
|
ephemeralHeaders(options) {
|
|
3020
|
-
return options.ephemeral ? { "X-Fal-Store-IO": "0" } : {};
|
|
3206
|
+
return options.ephemeral === true ? { "X-Fal-Store-IO": "0" } : {};
|
|
3021
3207
|
}
|
|
3022
3208
|
/**
|
|
3023
3209
|
* Normalize fal.ai responses.
|
|
3024
3210
|
* Some APIs return `{ image: {...} }` instead of `{ images: [...] }`.
|
|
3025
3211
|
*/
|
|
3026
3212
|
normalizeResponse(data, fallbackRequestId) {
|
|
3027
|
-
|
|
3028
|
-
const requestId = obj.request_id ?? obj.requestId ?? fallbackRequestId;
|
|
3029
|
-
if ("detail" in obj) {
|
|
3213
|
+
if (!isRecord(data)) {
|
|
3030
3214
|
return (0, import_neverthrow.err)(
|
|
3031
|
-
new MotifError(
|
|
3215
|
+
new MotifError("Unexpected fal response shape", 0, "FAL_ERROR")
|
|
3032
3216
|
);
|
|
3033
3217
|
}
|
|
3218
|
+
const obj = data;
|
|
3219
|
+
const requestId = asString(obj.request_id) ?? asString(obj.requestId) ?? fallbackRequestId;
|
|
3220
|
+
if ("detail" in obj) {
|
|
3221
|
+
return (0, import_neverthrow.err)(new MotifError(asString(obj.detail) ?? "", 0, "FAL_ERROR"));
|
|
3222
|
+
}
|
|
3034
3223
|
if ("image" in obj && !("images" in obj)) {
|
|
3035
3224
|
return (0, import_neverthrow.ok)({
|
|
3036
|
-
images: [obj.image],
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3225
|
+
images: [toMotifImage(obj.image)],
|
|
3226
|
+
prompt: asString(obj.prompt),
|
|
3227
|
+
requestId,
|
|
3228
|
+
seed: asNumber(obj.seed)
|
|
3040
3229
|
});
|
|
3041
3230
|
}
|
|
3042
3231
|
return (0, import_neverthrow.ok)({
|
|
3043
|
-
|
|
3044
|
-
|
|
3232
|
+
images: parseImages(obj.images),
|
|
3233
|
+
prompt: asString(obj.prompt),
|
|
3234
|
+
requestId,
|
|
3235
|
+
seed: asNumber(obj.seed)
|
|
3045
3236
|
});
|
|
3046
3237
|
}
|
|
3047
3238
|
};
|
|
3048
3239
|
var MotifError = class extends Error {
|
|
3049
3240
|
status;
|
|
3050
3241
|
code;
|
|
3051
|
-
|
|
3242
|
+
/** fal's request-correlation id (from the `x-fal-request-id` header or the
|
|
3243
|
+
* error body). Ties a failure back to fal's dashboard/support. */
|
|
3244
|
+
requestId;
|
|
3245
|
+
constructor(message, status, code, requestId) {
|
|
3052
3246
|
super(message);
|
|
3053
3247
|
this.name = "MotifError";
|
|
3054
3248
|
this.status = status;
|
|
3055
3249
|
this.code = code;
|
|
3250
|
+
this.requestId = requestId;
|
|
3056
3251
|
}
|
|
3057
3252
|
};
|
|
3058
3253
|
function toMotifError(error) {
|