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