@shop-os/modelkit 0.7.8 → 0.7.11
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/CHANGELOG.md +22 -0
- package/dist/catalog.cjs +130 -17
- package/dist/catalog.cjs.map +1 -1
- package/dist/catalog.js +130 -17
- package/dist/catalog.js.map +1 -1
- package/dist/index.cjs +260 -49
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +260 -49
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -4844,6 +4844,8 @@ function range(min, max) {
|
|
|
4844
4844
|
}
|
|
4845
4845
|
var KLING_PROMPT = { referenceSyntax: "numbered", maxChars: 2500 };
|
|
4846
4846
|
var H3_PROMPT = { referenceSyntax: "numbered", maxChars: 5e4 };
|
|
4847
|
+
var KLING_V4_PROMPT = { referenceSyntax: "numbered", maxChars: 2500 };
|
|
4848
|
+
var KLING_V4_AUDIO = "always";
|
|
4847
4849
|
var NO_REFERENCES = { images: 0, videos: 0, audios: 0 };
|
|
4848
4850
|
function klingMotionControl(tier) {
|
|
4849
4851
|
const label = tier === "pro" ? "Pro" : "Standard";
|
|
@@ -4944,6 +4946,79 @@ var VIDEO_FAMILY_MODELS = [
|
|
|
4944
4946
|
},
|
|
4945
4947
|
capabilities: { acceptsSourceVideo: true, videoEdit: true }
|
|
4946
4948
|
},
|
|
4949
|
+
{
|
|
4950
|
+
// https://fal.ai/models/kling/v4/reference-to-video/api (+ /text-to-video,
|
|
4951
|
+
// /image-to-video): one row; references (images or videos) go to reference-to-video,
|
|
4952
|
+
// else a start frame to image-to-video, else text-to-video. Reference images: 10, the
|
|
4953
|
+
// start frame included (fal: "counts toward the image reference limit"), 300 px min.
|
|
4954
|
+
// Reference videos: 5, 3-30.05 s each and 30 s combined, 700 px min, 23.9-60.05 fps.
|
|
4955
|
+
// The prompt names references as @Image1, @Video1 (no space; @Element1 for elements,
|
|
4956
|
+
// which the kit does not send). No sound switch on any endpoint.
|
|
4957
|
+
id: "kling-4.0",
|
|
4958
|
+
aliases: ["kling-4", "kling-v4"],
|
|
4959
|
+
label: "Kling 4.0",
|
|
4960
|
+
type: "video",
|
|
4961
|
+
adapter: "fal",
|
|
4962
|
+
providerModelId: "kling/v4",
|
|
4963
|
+
lifecycle: "active",
|
|
4964
|
+
exposure: ["cowork", "space_builder"],
|
|
4965
|
+
constraints: {
|
|
4966
|
+
aspectRatios: ["adaptive", "16:9", "9:16", "1:1", "21:9"],
|
|
4967
|
+
resolutions: ["720p", "1080p"],
|
|
4968
|
+
durations: { min: 3, max: 30 },
|
|
4969
|
+
durationPresets: [5, 10, 15, 30],
|
|
4970
|
+
references: {
|
|
4971
|
+
...NO_REFERENCES,
|
|
4972
|
+
images: 10,
|
|
4973
|
+
videos: 5,
|
|
4974
|
+
videoSeconds: { min: 3, max: 30.05, total: 30 }
|
|
4975
|
+
},
|
|
4976
|
+
supports: ["lastFrame"],
|
|
4977
|
+
prompt: KLING_V4_PROMPT,
|
|
4978
|
+
audio: KLING_V4_AUDIO
|
|
4979
|
+
},
|
|
4980
|
+
defaults: { durationSeconds: 5, resolution: "1080p", aspectRatio: "16:9" },
|
|
4981
|
+
usage: { ...VIDEO_USAGE },
|
|
4982
|
+
pricingKind: "video_per_second",
|
|
4983
|
+
display: {
|
|
4984
|
+
provider: "kuaishou",
|
|
4985
|
+
logo: KLING_LOGO,
|
|
4986
|
+
description: "Kuaishou Kling 4.0: text-to-video, start/end frames, or reference-to-video from up to 10 images and 5 videos (30 seconds combined), 3-30 seconds at 720p or 1080p. Prompts name references @Image1, @Video1."
|
|
4987
|
+
},
|
|
4988
|
+
capabilities: { lastFrameRequiresFirstFrame: true }
|
|
4989
|
+
},
|
|
4990
|
+
{
|
|
4991
|
+
// https://fal.ai/models/kling/v4/video-to-video/edit/api: source 3-30.05 s (700 px
|
|
4992
|
+
// min, 23.9-60.05 fps), up to 10 reference images. duration 3-30, or left out for the
|
|
4993
|
+
// source's length. The prompt names the source @Video1 and images @Image1, @Image2.
|
|
4994
|
+
id: "kling-4.0-edit",
|
|
4995
|
+
aliases: ["kling-4-edit", "kling-v4-edit"],
|
|
4996
|
+
label: "Kling 4.0 Edit",
|
|
4997
|
+
type: "video",
|
|
4998
|
+
adapter: "fal",
|
|
4999
|
+
providerModelId: "kling/v4/video-to-video/edit",
|
|
5000
|
+
lifecycle: "active",
|
|
5001
|
+
exposure: ["cowork", "space_builder"],
|
|
5002
|
+
constraints: {
|
|
5003
|
+
resolutions: ["720p", "1080p"],
|
|
5004
|
+
durations: { min: 3, max: 30 },
|
|
5005
|
+
references: { ...NO_REFERENCES, images: 10 },
|
|
5006
|
+
requires: ["sourceVideo"],
|
|
5007
|
+
sourceVideoSeconds: { min: 3, max: 30.05 },
|
|
5008
|
+
supports: [],
|
|
5009
|
+
prompt: KLING_V4_PROMPT,
|
|
5010
|
+
audio: KLING_V4_AUDIO
|
|
5011
|
+
},
|
|
5012
|
+
defaults: { resolution: "1080p" },
|
|
5013
|
+
usage: { ...VIDEO_USAGE },
|
|
5014
|
+
pricingKind: "video_per_second",
|
|
5015
|
+
display: {
|
|
5016
|
+
provider: "kuaishou",
|
|
5017
|
+
logo: KLING_LOGO,
|
|
5018
|
+
description: "Kuaishou Kling 4.0 video edit: change a 3-30 second clip with a prompt and up to 10 reference images, at 720p or 1080p, as long as the source or a set 3-30 seconds. Prompts name the source @Video1 and images @Image1."
|
|
5019
|
+
},
|
|
5020
|
+
capabilities: { acceptsSourceVideo: true, videoEdit: true }
|
|
5021
|
+
},
|
|
4947
5022
|
{
|
|
4948
5023
|
// https://fal.ai/models/minimax/h3-max-turbo/text-to-video/api (+ /image-to-video).
|
|
4949
5024
|
// image-to-video takes a start frame, an end frame, or both, and no aspect_ratio.
|
|
@@ -5802,38 +5877,38 @@ var VIDEO_MODELS = [
|
|
|
5802
5877
|
capabilities: { ...FRAMES_EXCLUDE_REFERENCES }
|
|
5803
5878
|
},
|
|
5804
5879
|
{
|
|
5805
|
-
// mode standard/pro/4k selects 720p/1080p/4K
|
|
5806
|
-
//
|
|
5807
|
-
//
|
|
5808
|
-
//
|
|
5880
|
+
// fal Kling O3 (adapters/fal-kling-omni.ts): mode standard/pro/4k selects 720p/1080p/4K
|
|
5881
|
+
// in the endpoint path. Moved off Replicate kwaivgi/kling-v3-omni-video, which fal sells
|
|
5882
|
+
// at half the price; the id and inputs stay. The Replicate mapper stays for deployed
|
|
5883
|
+
// model_catalog rows not yet switched. Frames and reference images share fal's cap of 7.
|
|
5884
|
+
// Reference video, multi-shot and keep-sound were never wired, so stay off.
|
|
5809
5885
|
id: "kling-v3-omni-video",
|
|
5810
5886
|
aliases: ["kwaivgi/kling-v3-omni-video", "kling-v3-omni"],
|
|
5811
5887
|
label: "Kling V3 Omni",
|
|
5812
5888
|
type: "video",
|
|
5813
|
-
adapter: "
|
|
5814
|
-
providerModelId: "
|
|
5889
|
+
adapter: "fal",
|
|
5890
|
+
providerModelId: "fal-ai/kling-video/o3",
|
|
5815
5891
|
lifecycle: "active",
|
|
5816
5892
|
exposure: ["cowork", "space_builder"],
|
|
5817
5893
|
constraints: {
|
|
5818
5894
|
aspectRatios: [...KLING_OMNI_RATIOS],
|
|
5819
5895
|
resolutions: ["720p", "1080p", "4k"],
|
|
5820
5896
|
durations: { min: 3, max: 15 },
|
|
5821
|
-
references: { images: 7,
|
|
5897
|
+
references: { images: 7, videos: 0, audios: 0 },
|
|
5822
5898
|
supports: ["generateAudio", "lastFrame"],
|
|
5823
5899
|
prompt: KLING_PROMPT2,
|
|
5824
5900
|
audio: "optional"
|
|
5825
5901
|
},
|
|
5826
5902
|
defaults: { durationSeconds: 5, aspectRatio: "16:9", generateAudio: true, mode: "pro" },
|
|
5827
|
-
usage: {
|
|
5903
|
+
usage: { ...VIDEO_USAGE3 },
|
|
5828
5904
|
pricingKind: "video_per_second",
|
|
5829
5905
|
display: {
|
|
5830
5906
|
provider: "kuaishou",
|
|
5831
5907
|
logo: "https://cdn.jsdelivr.net/npm/@lobehub/icons-static-png@1.97.0/light/kling-color.png",
|
|
5832
|
-
description: "Kuaishou Kling Video 3.0 Omni
|
|
5908
|
+
description: "Kuaishou Kling Video 3.0 Omni generation from text, start/end images and up to 7 reference images, with optional native audio; up to 15 seconds at up to 4K."
|
|
5833
5909
|
}
|
|
5834
|
-
//
|
|
5835
|
-
//
|
|
5836
|
-
// the adapter sends as start_image.
|
|
5910
|
+
// No lastFrameRequiresFirstFrame: fal image-to-video needs a start frame, so the adapter
|
|
5911
|
+
// sends a lone end frame as the start frame, as the Replicate model took it.
|
|
5837
5912
|
},
|
|
5838
5913
|
{
|
|
5839
5914
|
id: "minimax-h3",
|
|
@@ -9448,11 +9523,11 @@ function toolInput(ctx, req, output) {
|
|
|
9448
9523
|
}
|
|
9449
9524
|
var EXR_DEFAULT_PROMPT = "The same video in high dynamic range, with unchanged content, motion, framing and timing.";
|
|
9450
9525
|
async function submitFalVideoTool(req, ctx, opts) {
|
|
9451
|
-
const
|
|
9452
|
-
if (!
|
|
9526
|
+
const plan4 = planVideoTool(ctx.model, req);
|
|
9527
|
+
if (!plan4.ok) {
|
|
9453
9528
|
throw new ModelKitError({
|
|
9454
9529
|
code: "unsupported_option",
|
|
9455
|
-
message:
|
|
9530
|
+
message: plan4.error,
|
|
9456
9531
|
provider: "fal",
|
|
9457
9532
|
model: ctx.model.id,
|
|
9458
9533
|
retryable: false
|
|
@@ -9460,7 +9535,7 @@ async function submitFalVideoTool(req, ctx, opts) {
|
|
|
9460
9535
|
}
|
|
9461
9536
|
const target = new URL(`${FAL_QUEUE_ORIGIN}/${ctx.model.providerModelId}`);
|
|
9462
9537
|
if (opts.webhookUrl !== void 0) target.searchParams.set("fal_webhook", opts.webhookUrl);
|
|
9463
|
-
const res = await queueFetch(ctx, target.toString(), "POST", toolInput(ctx, req,
|
|
9538
|
+
const res = await queueFetch(ctx, target.toString(), "POST", toolInput(ctx, req, plan4.output));
|
|
9464
9539
|
const parsed = submitResponseSchema.safeParse(await readJson(ctx, res));
|
|
9465
9540
|
if (!parsed.success) {
|
|
9466
9541
|
throw new ModelKitError({
|
|
@@ -9478,7 +9553,7 @@ async function submitFalVideoTool(req, ctx, opts) {
|
|
|
9478
9553
|
statusUrl: parsed.data.status_url,
|
|
9479
9554
|
responseUrl: parsed.data.response_url,
|
|
9480
9555
|
cancelUrl: parsed.data.cancel_url,
|
|
9481
|
-
output:
|
|
9556
|
+
output: plan4.output
|
|
9482
9557
|
};
|
|
9483
9558
|
}
|
|
9484
9559
|
async function falVideoToolStatus(sub, ctx) {
|
|
@@ -10167,14 +10242,14 @@ function planFalImage(req, providerModelId, model) {
|
|
|
10167
10242
|
const exact = falExactSize(spec, req);
|
|
10168
10243
|
const call = { label: spec.label, req, refs, edit: edit2, ...exact !== void 0 && { exact } };
|
|
10169
10244
|
const built = family.build(call, model);
|
|
10170
|
-
const
|
|
10245
|
+
const plan4 = {
|
|
10171
10246
|
endpoint: edit2 && family.editEndpoint !== void 0 ? family.editEndpoint : id,
|
|
10172
10247
|
input: built.input,
|
|
10173
10248
|
output: family.output ?? "images"
|
|
10174
10249
|
};
|
|
10175
|
-
if (built.imageQuality !== void 0)
|
|
10176
|
-
if (built.imageSize !== void 0)
|
|
10177
|
-
return
|
|
10250
|
+
if (built.imageQuality !== void 0) plan4.imageQuality = built.imageQuality;
|
|
10251
|
+
if (built.imageSize !== void 0) plan4.imageSize = built.imageSize;
|
|
10252
|
+
return plan4;
|
|
10178
10253
|
}
|
|
10179
10254
|
var FalFileSchema = import_zod14.z.object({ url: import_zod14.z.string(), content_type: import_zod14.z.string().nullish() });
|
|
10180
10255
|
var ImagesPayloadSchema = import_zod14.z.object({ images: import_zod14.z.array(FalFileSchema) });
|
|
@@ -10196,18 +10271,18 @@ async function downloadFalFile(ctx, file) {
|
|
|
10196
10271
|
const mime = res.headers.get("content-type") ?? file.content_type ?? "";
|
|
10197
10272
|
return { bytes: new Uint8Array(await res.arrayBuffer()), mime };
|
|
10198
10273
|
}
|
|
10199
|
-
function filesOf(payload,
|
|
10200
|
-
if (
|
|
10274
|
+
function filesOf(payload, plan4) {
|
|
10275
|
+
if (plan4.output === "image") {
|
|
10201
10276
|
const parsed2 = ImagePayloadSchema.safeParse(payload);
|
|
10202
10277
|
return parsed2.success ? [parsed2.data.image] : [];
|
|
10203
10278
|
}
|
|
10204
10279
|
const parsed = ImagesPayloadSchema.safeParse(payload);
|
|
10205
10280
|
return parsed.success ? parsed.data.images : [];
|
|
10206
10281
|
}
|
|
10207
|
-
async function collectFalPlanImages(payload,
|
|
10208
|
-
const files = filesOf(payload,
|
|
10282
|
+
async function collectFalPlanImages(payload, plan4, ctx, req) {
|
|
10283
|
+
const files = filesOf(payload, plan4);
|
|
10209
10284
|
if (files.length === 0) {
|
|
10210
|
-
throw fail2(ctx.model.id, `fal ${
|
|
10285
|
+
throw fail2(ctx.model.id, `fal ${plan4.endpoint} returned no image`, "provider_rejected");
|
|
10211
10286
|
}
|
|
10212
10287
|
const images = await Promise.all(
|
|
10213
10288
|
files.map(async (file) => {
|
|
@@ -10222,18 +10297,18 @@ async function collectFalPlanImages(payload, plan3, ctx, req) {
|
|
|
10222
10297
|
unit: "images",
|
|
10223
10298
|
quantity: images.length
|
|
10224
10299
|
};
|
|
10225
|
-
const billedSize =
|
|
10300
|
+
const billedSize = plan4.imageSize ?? req.size;
|
|
10226
10301
|
if (billedSize !== void 0 && ctx.model.type === "image") usage3.imageSize = billedSize;
|
|
10227
|
-
if (
|
|
10302
|
+
if (plan4.imageQuality !== void 0) usage3.imageQuality = plan4.imageQuality;
|
|
10228
10303
|
const result = { images, usage: usage3, raw: payload };
|
|
10229
10304
|
const remote = files.find((f) => !f.url.startsWith("data:"));
|
|
10230
10305
|
if (remote !== void 0) result.outputUrl = remote.url;
|
|
10231
10306
|
return result;
|
|
10232
10307
|
}
|
|
10233
10308
|
async function generateFalFamilyImage(req, ctx, run) {
|
|
10234
|
-
const
|
|
10235
|
-
const payload = await run(
|
|
10236
|
-
return collectFalPlanImages(payload,
|
|
10309
|
+
const plan4 = planFalImage(req, ctx.model.providerModelId, ctx.model.id);
|
|
10310
|
+
const payload = await run(plan4.endpoint, plan4.input);
|
|
10311
|
+
return collectFalPlanImages(payload, plan4, ctx, req);
|
|
10237
10312
|
}
|
|
10238
10313
|
|
|
10239
10314
|
// src/adapters/fal-mask.ts
|
|
@@ -11251,6 +11326,8 @@ var MOTION_PRO = "fal-ai/kling-video/v3/pro/motion-control";
|
|
|
11251
11326
|
var MOTION_STANDARD = "fal-ai/kling-video/v3/standard/motion-control";
|
|
11252
11327
|
var O3_REFERENCE = "fal-ai/kling-video/o3/pro/reference-to-video";
|
|
11253
11328
|
var O3_EDIT = "fal-ai/kling-video/o3/pro/video-to-video/edit";
|
|
11329
|
+
var V4_FAMILY = "kling/v4";
|
|
11330
|
+
var V4_EDIT = "kling/v4/video-to-video/edit";
|
|
11254
11331
|
function motionControl(endpoint, req, ctx) {
|
|
11255
11332
|
const [character] = req.referenceImages ?? [];
|
|
11256
11333
|
const [motion] = req.referenceVideos ?? [];
|
|
@@ -11310,6 +11387,61 @@ var klingV3Family = {
|
|
|
11310
11387
|
return motionControl(id, req, ctx);
|
|
11311
11388
|
}
|
|
11312
11389
|
};
|
|
11390
|
+
function v4Generate(req, ctx) {
|
|
11391
|
+
const images = urls(req.referenceImages);
|
|
11392
|
+
const videos = urls(req.referenceVideos);
|
|
11393
|
+
const duration = wholeSeconds(req, ctx);
|
|
11394
|
+
const resolution = resolutionOf(req, ctx);
|
|
11395
|
+
const input = { prompt: req.prompt.trim(), duration, resolution };
|
|
11396
|
+
let endpoint;
|
|
11397
|
+
if (images.length + videos.length > 0) {
|
|
11398
|
+
endpoint = `${V4_FAMILY}/reference-to-video`;
|
|
11399
|
+
if (images.length > 0) input["image_urls"] = images;
|
|
11400
|
+
if (videos.length > 0) input["video_urls"] = videos;
|
|
11401
|
+
if (req.firstFrame) input["start_image_url"] = refToUrl(req.firstFrame);
|
|
11402
|
+
if (req.aspectRatio !== void 0) {
|
|
11403
|
+
input["aspect_ratio"] = req.aspectRatio === "adaptive" ? "auto" : req.aspectRatio;
|
|
11404
|
+
}
|
|
11405
|
+
} else if (req.firstFrame) {
|
|
11406
|
+
endpoint = `${V4_FAMILY}/image-to-video`;
|
|
11407
|
+
input["start_image_url"] = refToUrl(req.firstFrame);
|
|
11408
|
+
if (req.lastFrame) input["end_image_url"] = refToUrl(req.lastFrame);
|
|
11409
|
+
} else {
|
|
11410
|
+
endpoint = `${V4_FAMILY}/text-to-video`;
|
|
11411
|
+
const ratio = concreteRatio(req);
|
|
11412
|
+
if (ratio !== void 0) input["aspect_ratio"] = ratio;
|
|
11413
|
+
}
|
|
11414
|
+
return { endpoint, input, resolution, seconds: requestedSeconds(duration) };
|
|
11415
|
+
}
|
|
11416
|
+
function v4Edit(req, ctx) {
|
|
11417
|
+
if (req.sourceVideo === void 0) throw refusal(ctx, "needs a source video", "missing_input");
|
|
11418
|
+
const resolution = resolutionOf(req, ctx);
|
|
11419
|
+
const input = {
|
|
11420
|
+
prompt: req.prompt.trim(),
|
|
11421
|
+
video_url: refToUrl(req.sourceVideo),
|
|
11422
|
+
resolution
|
|
11423
|
+
};
|
|
11424
|
+
const images = urls(req.referenceImages);
|
|
11425
|
+
if (images.length > 0) input["image_urls"] = images;
|
|
11426
|
+
if (req.durationSeconds === void 0) {
|
|
11427
|
+
return {
|
|
11428
|
+
endpoint: V4_EDIT,
|
|
11429
|
+
input,
|
|
11430
|
+
resolution,
|
|
11431
|
+
seconds: inputLengthSeconds(req, req.sourceVideo)
|
|
11432
|
+
};
|
|
11433
|
+
}
|
|
11434
|
+
const duration = wholeSeconds(req, ctx);
|
|
11435
|
+
input["duration"] = duration;
|
|
11436
|
+
return { endpoint: V4_EDIT, input, resolution, seconds: requestedSeconds(duration) };
|
|
11437
|
+
}
|
|
11438
|
+
var KLING_V4_VIDEO_IDS = /* @__PURE__ */ new Set([V4_FAMILY, V4_EDIT]);
|
|
11439
|
+
var klingV4Family = {
|
|
11440
|
+
ids: KLING_V4_VIDEO_IDS,
|
|
11441
|
+
plan(req, ctx) {
|
|
11442
|
+
return ctx.model.providerModelId.toLowerCase() === V4_EDIT ? v4Edit(req, ctx) : v4Generate(req, ctx);
|
|
11443
|
+
}
|
|
11444
|
+
};
|
|
11313
11445
|
|
|
11314
11446
|
// src/replicate-video-kinds.ts
|
|
11315
11447
|
function replicateBaseModelId(providerModelId) {
|
|
@@ -11331,15 +11463,57 @@ var KLING_TIERS = [
|
|
|
11331
11463
|
{ mode: "pro", resolution: "1080p" },
|
|
11332
11464
|
{ mode: "4k", resolution: "4k" }
|
|
11333
11465
|
];
|
|
11466
|
+
var KLING_O3_OMNI = "fal-ai/kling-video/o3";
|
|
11334
11467
|
function klingTier(req) {
|
|
11335
11468
|
return KLING_TIERS.find((tier) => tier.resolution === req.resolution) ?? KLING_TIERS.find((tier) => tier.mode === req.mode) ?? KLING_TIERS[0];
|
|
11336
11469
|
}
|
|
11337
11470
|
|
|
11471
|
+
// src/adapters/fal-kling-omni.ts
|
|
11472
|
+
function plan(req, ctx) {
|
|
11473
|
+
const tier = klingTier(req);
|
|
11474
|
+
const duration = wholeSeconds(req, ctx);
|
|
11475
|
+
const input = {
|
|
11476
|
+
prompt: req.prompt.trim(),
|
|
11477
|
+
duration: String(duration),
|
|
11478
|
+
generate_audio: req.generateAudio ?? true
|
|
11479
|
+
};
|
|
11480
|
+
const start = req.firstFrame ?? req.lastFrame;
|
|
11481
|
+
const end = req.firstFrame ? req.lastFrame : void 0;
|
|
11482
|
+
const images = urls(req.referenceImages);
|
|
11483
|
+
let task;
|
|
11484
|
+
if (images.length > 0) {
|
|
11485
|
+
task = "reference-to-video";
|
|
11486
|
+
input["image_urls"] = images;
|
|
11487
|
+
if (start) input["start_image_url"] = refToUrl(start);
|
|
11488
|
+
if (end) input["end_image_url"] = refToUrl(end);
|
|
11489
|
+
} else if (start) {
|
|
11490
|
+
task = "image-to-video";
|
|
11491
|
+
input["image_url"] = refToUrl(start);
|
|
11492
|
+
if (end) input["end_image_url"] = refToUrl(end);
|
|
11493
|
+
} else {
|
|
11494
|
+
task = "text-to-video";
|
|
11495
|
+
}
|
|
11496
|
+
const ratio = concreteRatio(req);
|
|
11497
|
+
if (ratio !== void 0 && start === void 0) input["aspect_ratio"] = ratio;
|
|
11498
|
+
return {
|
|
11499
|
+
endpoint: `${KLING_O3_OMNI}/${tier.mode}/${task}`,
|
|
11500
|
+
input,
|
|
11501
|
+
resolution: tier.resolution,
|
|
11502
|
+
seconds: requestedSeconds(duration)
|
|
11503
|
+
};
|
|
11504
|
+
}
|
|
11505
|
+
var klingOmniFamily = {
|
|
11506
|
+
ids: /* @__PURE__ */ new Set([KLING_O3_OMNI]),
|
|
11507
|
+
plan
|
|
11508
|
+
};
|
|
11509
|
+
|
|
11338
11510
|
// src/resolve-video-rules.ts
|
|
11339
11511
|
var MOTION_PRO2 = "fal-ai/kling-video/v3/pro/motion-control";
|
|
11340
11512
|
var MOTION_STANDARD2 = "fal-ai/kling-video/v3/standard/motion-control";
|
|
11341
11513
|
var O3_REFERENCE2 = "fal-ai/kling-video/o3/pro/reference-to-video";
|
|
11342
11514
|
var O3_EDIT2 = "fal-ai/kling-video/o3/pro/video-to-video/edit";
|
|
11515
|
+
var KLING_V4 = "kling/v4";
|
|
11516
|
+
var KLING_V4_EDIT = "kling/v4/video-to-video/edit";
|
|
11343
11517
|
var H3_TURBO = "minimax/h3-max-turbo";
|
|
11344
11518
|
var H3_RECAST = "minimax/h3-max/recast";
|
|
11345
11519
|
var H3_RELIGHT = "minimax/h3-max/relight";
|
|
@@ -11348,6 +11522,7 @@ var HAPPY_HORSE_EDIT = "alibaba/happy-horse/video-edit";
|
|
|
11348
11522
|
var VIDU_Q4 = "fal-ai/vidu/q4";
|
|
11349
11523
|
var OMNIHUMAN_V2 = "bytedance/omnihuman/v2";
|
|
11350
11524
|
var KLING_O3_IMAGE_CAP = 7;
|
|
11525
|
+
var KLING_V4_IMAGE_CAP = 10;
|
|
11351
11526
|
var TURBO_AUDIO_MIN_SECONDS = 2;
|
|
11352
11527
|
var OMNIHUMAN_AUDIO_SECONDS = { min: 4, max: 300 };
|
|
11353
11528
|
function missing(message) {
|
|
@@ -11403,6 +11578,23 @@ function o3Reference2(req) {
|
|
|
11403
11578
|
}
|
|
11404
11579
|
return needsPrompt(req);
|
|
11405
11580
|
}
|
|
11581
|
+
function hasReferences(req) {
|
|
11582
|
+
return count(req.referenceImages) + count(req.referenceVideos) > 0;
|
|
11583
|
+
}
|
|
11584
|
+
function klingV4(req) {
|
|
11585
|
+
if (hasReferences(req)) {
|
|
11586
|
+
if (req.lastFrame !== void 0) {
|
|
11587
|
+
return unsupported2("takes an end frame only without reference images or videos");
|
|
11588
|
+
}
|
|
11589
|
+
const images = count(req.referenceImages) + (req.firstFrame === void 0 ? 0 : 1);
|
|
11590
|
+
if (images > KLING_V4_IMAGE_CAP) {
|
|
11591
|
+
return unsupported2(
|
|
11592
|
+
`takes up to ${KLING_V4_IMAGE_CAP} images in all, the start frame included; this request has ${images}`
|
|
11593
|
+
);
|
|
11594
|
+
}
|
|
11595
|
+
}
|
|
11596
|
+
return needsPrompt(req);
|
|
11597
|
+
}
|
|
11406
11598
|
function h3Turbo(req) {
|
|
11407
11599
|
if (count(req.referenceImages) + count(req.referenceVideos) > 0) {
|
|
11408
11600
|
return unsupported2("takes no reference images or videos");
|
|
@@ -11479,7 +11671,10 @@ var RULES = /* @__PURE__ */ new Map([
|
|
|
11479
11671
|
[MOTION_PRO2, motionControl2],
|
|
11480
11672
|
[MOTION_STANDARD2, motionControl2],
|
|
11481
11673
|
[O3_REFERENCE2, o3Reference2],
|
|
11674
|
+
[KLING_O3_OMNI, o3Reference2],
|
|
11482
11675
|
[O3_EDIT2, (req) => needsSource(req) ?? needsPrompt(req)],
|
|
11676
|
+
[KLING_V4, klingV4],
|
|
11677
|
+
[KLING_V4_EDIT, (req) => needsSource(req) ?? needsPrompt(req)],
|
|
11483
11678
|
[H3_TURBO, h3Turbo],
|
|
11484
11679
|
[MINIMAX_H3_INSERT, h3Insert],
|
|
11485
11680
|
[H3_RECAST, h3Recast],
|
|
@@ -11508,13 +11703,14 @@ function h3EndFrameRatioWarning(model, ratio) {
|
|
|
11508
11703
|
message: `${model.id} follows the end frame's aspect ratio`
|
|
11509
11704
|
};
|
|
11510
11705
|
}
|
|
11511
|
-
function
|
|
11706
|
+
function takesKlingMode(model) {
|
|
11707
|
+
if (model.adapter === "fal") return model.providerModelId.toLowerCase() === KLING_O3_OMNI;
|
|
11512
11708
|
if (model.adapter !== "replicate") return false;
|
|
11513
11709
|
const kind = videoKind(model.providerModelId);
|
|
11514
11710
|
return kind === "kling" || kind === "kling-omni";
|
|
11515
11711
|
}
|
|
11516
|
-
function
|
|
11517
|
-
if (
|
|
11712
|
+
function fillKlingModeResolution(model, req) {
|
|
11713
|
+
if (takesKlingMode(model) && req.resolution === void 0) {
|
|
11518
11714
|
req.resolution = klingTier(req).resolution;
|
|
11519
11715
|
}
|
|
11520
11716
|
}
|
|
@@ -11528,6 +11724,19 @@ function applyFalVideoRules(model, req, callerRatio, warnings) {
|
|
|
11528
11724
|
warnings.push(viduSilentWarning(model));
|
|
11529
11725
|
req.generateAudio = false;
|
|
11530
11726
|
}
|
|
11727
|
+
if (id === KLING_V4 && req.firstFrame !== void 0 && !hasReferences(req)) {
|
|
11728
|
+
if (req.aspectRatio !== void 0) {
|
|
11729
|
+
if (callerRatio !== void 0) {
|
|
11730
|
+
warnings.push({
|
|
11731
|
+
code: "ratio_dropped",
|
|
11732
|
+
field: "aspectRatio",
|
|
11733
|
+
from: req.aspectRatio,
|
|
11734
|
+
message: `${model.id} follows the start frame's aspect ratio`
|
|
11735
|
+
});
|
|
11736
|
+
}
|
|
11737
|
+
delete req.aspectRatio;
|
|
11738
|
+
}
|
|
11739
|
+
}
|
|
11531
11740
|
const endFrameOnly = req.lastFrame !== void 0 && req.firstFrame === void 0;
|
|
11532
11741
|
if (id === H3_TURBO && endFrameOnly && req.aspectRatio !== void 0) {
|
|
11533
11742
|
if (callerRatio !== void 0 && callerRatio !== "adaptive") {
|
|
@@ -11653,7 +11862,7 @@ var minimaxH3MaxFamily = {
|
|
|
11653
11862
|
|
|
11654
11863
|
// src/adapters/fal-omnihuman.ts
|
|
11655
11864
|
var OMNIHUMAN_V22 = "bytedance/omnihuman/v2";
|
|
11656
|
-
function
|
|
11865
|
+
function plan2(req, ctx) {
|
|
11657
11866
|
const [image] = req.referenceImages ?? [];
|
|
11658
11867
|
const [audio] = req.referenceAudios ?? [];
|
|
11659
11868
|
if (image === void 0 || audio === void 0) {
|
|
@@ -11664,14 +11873,14 @@ function plan(req, ctx) {
|
|
|
11664
11873
|
return { endpoint: OMNIHUMAN_V22, input, seconds: inputLengthSeconds(req, audio) };
|
|
11665
11874
|
}
|
|
11666
11875
|
var OMNIHUMAN_MODEL_IDS = /* @__PURE__ */ new Set([OMNIHUMAN_V22]);
|
|
11667
|
-
var omnihumanFamily = { ids: OMNIHUMAN_MODEL_IDS, plan };
|
|
11876
|
+
var omnihumanFamily = { ids: OMNIHUMAN_MODEL_IDS, plan: plan2 };
|
|
11668
11877
|
|
|
11669
11878
|
// src/adapters/fal-vidu.ts
|
|
11670
11879
|
var FAMILY2 = "fal-ai/vidu/q4";
|
|
11671
11880
|
function viduTier(resolution) {
|
|
11672
11881
|
return resolution === "2k" || resolution === "4k" ? upperTier(resolution) : resolution;
|
|
11673
11882
|
}
|
|
11674
|
-
function
|
|
11883
|
+
function plan3(req, ctx) {
|
|
11675
11884
|
const images = urls(req.referenceImages);
|
|
11676
11885
|
const audios = urls(req.referenceAudios);
|
|
11677
11886
|
const duration = wholeSeconds(req, ctx);
|
|
@@ -11698,11 +11907,13 @@ function plan2(req, ctx) {
|
|
|
11698
11907
|
return { endpoint, input, resolution, seconds: requestedSeconds(duration) };
|
|
11699
11908
|
}
|
|
11700
11909
|
var VIDU_MODEL_IDS = /* @__PURE__ */ new Set([FAMILY2]);
|
|
11701
|
-
var viduFamily = { ids: VIDU_MODEL_IDS, plan:
|
|
11910
|
+
var viduFamily = { ids: VIDU_MODEL_IDS, plan: plan3 };
|
|
11702
11911
|
|
|
11703
11912
|
// src/adapters/fal-video-families.ts
|
|
11704
11913
|
var FAMILIES2 = [
|
|
11705
11914
|
klingV3Family,
|
|
11915
|
+
klingOmniFamily,
|
|
11916
|
+
klingV4Family,
|
|
11706
11917
|
minimaxH3MaxFamily,
|
|
11707
11918
|
happyHorseFamily,
|
|
11708
11919
|
viduFamily,
|
|
@@ -11989,8 +12200,8 @@ async function collectFalImages(payload, ctx, req, label) {
|
|
|
11989
12200
|
};
|
|
11990
12201
|
}
|
|
11991
12202
|
async function generateSpecImage(req, ctx, deps, spec) {
|
|
11992
|
-
const
|
|
11993
|
-
const endpoint =
|
|
12203
|
+
const hasReferences2 = (req.references ?? []).length > 0;
|
|
12204
|
+
const endpoint = hasReferences2 && spec.spec.editEndpoint !== void 0 ? spec.spec.editEndpoint : ctx.model.providerModelId;
|
|
11994
12205
|
const payload = await runJob(ctx, deps, endpoint, spec.input);
|
|
11995
12206
|
return collectFalImages(payload, ctx, req, `fal ${endpoint}`);
|
|
11996
12207
|
}
|
|
@@ -12179,7 +12390,7 @@ function extractVideoUrl(result, endpoint, model) {
|
|
|
12179
12390
|
}
|
|
12180
12391
|
async function generateFalVideo(req, ctx, deps) {
|
|
12181
12392
|
const providerModelId = ctx.model.providerModelId;
|
|
12182
|
-
const
|
|
12393
|
+
const plan4 = planFalFamilyVideo(req, ctx);
|
|
12183
12394
|
const start = (endpoint2, input, usageOf2) => startFalVideoJob(
|
|
12184
12395
|
ctx,
|
|
12185
12396
|
() => falClientOf(ctx, deps),
|
|
@@ -12187,7 +12398,7 @@ async function generateFalVideo(req, ctx, deps) {
|
|
|
12187
12398
|
input,
|
|
12188
12399
|
videoFileDecoder(ctx, req, endpoint2, usageOf2)
|
|
12189
12400
|
);
|
|
12190
|
-
if (
|
|
12401
|
+
if (plan4 !== void 0) return start(plan4.endpoint, plan4.input, planUsage(ctx, plan4));
|
|
12191
12402
|
if (isKling(providerModelId)) return start(KLING_O1_ENDPOINT, klingO1Input(req));
|
|
12192
12403
|
if (isWan(providerModelId)) {
|
|
12193
12404
|
const { endpoint: endpoint2, input } = wanVideo(req, providerModelId.toLowerCase());
|
|
@@ -12237,9 +12448,9 @@ function videoFileDecoder(ctx, req, endpoint, usageOf2) {
|
|
|
12237
12448
|
raw: payload
|
|
12238
12449
|
});
|
|
12239
12450
|
}
|
|
12240
|
-
function planUsage(ctx,
|
|
12451
|
+
function planUsage(ctx, plan4) {
|
|
12241
12452
|
return (payload) => {
|
|
12242
|
-
const seconds3 =
|
|
12453
|
+
const seconds3 = plan4.seconds(payload);
|
|
12243
12454
|
return {
|
|
12244
12455
|
model: ctx.model.id,
|
|
12245
12456
|
provider: "fal",
|
|
@@ -12247,7 +12458,7 @@ function planUsage(ctx, plan3) {
|
|
|
12247
12458
|
unit: "seconds",
|
|
12248
12459
|
quantity: seconds3,
|
|
12249
12460
|
durationSeconds: seconds3,
|
|
12250
|
-
...
|
|
12461
|
+
...plan4.resolution !== void 0 && { resolution: plan4.resolution }
|
|
12251
12462
|
};
|
|
12252
12463
|
};
|
|
12253
12464
|
}
|
|
@@ -14335,8 +14546,8 @@ function imageBody(req, ctx, outputFormat) {
|
|
|
14335
14546
|
function videoBody(req, ctx, mode) {
|
|
14336
14547
|
const prompt = checkPrompt(req, ctx);
|
|
14337
14548
|
const model = lumaModel(ctx);
|
|
14338
|
-
const
|
|
14339
|
-
if (
|
|
14549
|
+
const hasReferences2 = (req.referenceImages ?? []).length + (req.referenceVideos ?? []).length + (req.referenceAudios ?? []).length > 0;
|
|
14550
|
+
if (hasReferences2) {
|
|
14340
14551
|
refuseOrDrop(
|
|
14341
14552
|
ctx,
|
|
14342
14553
|
"referenceImages",
|
|
@@ -16699,10 +16910,10 @@ function resolveVideoOptions(model, request, onUnsupported = "error") {
|
|
|
16699
16910
|
warnings
|
|
16700
16911
|
);
|
|
16701
16912
|
if (aspectRatio !== void 0) merged.aspectRatio = aspectRatio;
|
|
16702
|
-
|
|
16913
|
+
fillKlingModeResolution(model, merged);
|
|
16703
16914
|
const resolution = resolveVideoResolution(merged.resolution, model, onUnsupported, warnings);
|
|
16704
16915
|
if (resolution !== void 0) merged.resolution = resolution;
|
|
16705
|
-
if (
|
|
16916
|
+
if (takesKlingMode(model)) delete merged.mode;
|
|
16706
16917
|
const duration = resolveDuration(
|
|
16707
16918
|
merged.durationSeconds,
|
|
16708
16919
|
c.durations,
|