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