@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.js
CHANGED
|
@@ -4706,6 +4706,8 @@ function range(min, max) {
|
|
|
4706
4706
|
}
|
|
4707
4707
|
var KLING_PROMPT = { referenceSyntax: "numbered", maxChars: 2500 };
|
|
4708
4708
|
var H3_PROMPT = { referenceSyntax: "numbered", maxChars: 5e4 };
|
|
4709
|
+
var KLING_V4_PROMPT = { referenceSyntax: "numbered", maxChars: 2500 };
|
|
4710
|
+
var KLING_V4_AUDIO = "always";
|
|
4709
4711
|
var NO_REFERENCES = { images: 0, videos: 0, audios: 0 };
|
|
4710
4712
|
function klingMotionControl(tier) {
|
|
4711
4713
|
const label = tier === "pro" ? "Pro" : "Standard";
|
|
@@ -4806,6 +4808,79 @@ var VIDEO_FAMILY_MODELS = [
|
|
|
4806
4808
|
},
|
|
4807
4809
|
capabilities: { acceptsSourceVideo: true, videoEdit: true }
|
|
4808
4810
|
},
|
|
4811
|
+
{
|
|
4812
|
+
// https://fal.ai/models/kling/v4/reference-to-video/api (+ /text-to-video,
|
|
4813
|
+
// /image-to-video): one row; references (images or videos) go to reference-to-video,
|
|
4814
|
+
// else a start frame to image-to-video, else text-to-video. Reference images: 10, the
|
|
4815
|
+
// start frame included (fal: "counts toward the image reference limit"), 300 px min.
|
|
4816
|
+
// Reference videos: 5, 3-30.05 s each and 30 s combined, 700 px min, 23.9-60.05 fps.
|
|
4817
|
+
// The prompt names references as @Image1, @Video1 (no space; @Element1 for elements,
|
|
4818
|
+
// which the kit does not send). No sound switch on any endpoint.
|
|
4819
|
+
id: "kling-4.0",
|
|
4820
|
+
aliases: ["kling-4", "kling-v4"],
|
|
4821
|
+
label: "Kling 4.0",
|
|
4822
|
+
type: "video",
|
|
4823
|
+
adapter: "fal",
|
|
4824
|
+
providerModelId: "kling/v4",
|
|
4825
|
+
lifecycle: "active",
|
|
4826
|
+
exposure: ["cowork", "space_builder"],
|
|
4827
|
+
constraints: {
|
|
4828
|
+
aspectRatios: ["adaptive", "16:9", "9:16", "1:1", "21:9"],
|
|
4829
|
+
resolutions: ["720p", "1080p"],
|
|
4830
|
+
durations: { min: 3, max: 30 },
|
|
4831
|
+
durationPresets: [5, 10, 15, 30],
|
|
4832
|
+
references: {
|
|
4833
|
+
...NO_REFERENCES,
|
|
4834
|
+
images: 10,
|
|
4835
|
+
videos: 5,
|
|
4836
|
+
videoSeconds: { min: 3, max: 30.05, total: 30 }
|
|
4837
|
+
},
|
|
4838
|
+
supports: ["lastFrame"],
|
|
4839
|
+
prompt: KLING_V4_PROMPT,
|
|
4840
|
+
audio: KLING_V4_AUDIO
|
|
4841
|
+
},
|
|
4842
|
+
defaults: { durationSeconds: 5, resolution: "1080p", aspectRatio: "16:9" },
|
|
4843
|
+
usage: { ...VIDEO_USAGE },
|
|
4844
|
+
pricingKind: "video_per_second",
|
|
4845
|
+
display: {
|
|
4846
|
+
provider: "kuaishou",
|
|
4847
|
+
logo: KLING_LOGO,
|
|
4848
|
+
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."
|
|
4849
|
+
},
|
|
4850
|
+
capabilities: { lastFrameRequiresFirstFrame: true }
|
|
4851
|
+
},
|
|
4852
|
+
{
|
|
4853
|
+
// https://fal.ai/models/kling/v4/video-to-video/edit/api: source 3-30.05 s (700 px
|
|
4854
|
+
// min, 23.9-60.05 fps), up to 10 reference images. duration 3-30, or left out for the
|
|
4855
|
+
// source's length. The prompt names the source @Video1 and images @Image1, @Image2.
|
|
4856
|
+
id: "kling-4.0-edit",
|
|
4857
|
+
aliases: ["kling-4-edit", "kling-v4-edit"],
|
|
4858
|
+
label: "Kling 4.0 Edit",
|
|
4859
|
+
type: "video",
|
|
4860
|
+
adapter: "fal",
|
|
4861
|
+
providerModelId: "kling/v4/video-to-video/edit",
|
|
4862
|
+
lifecycle: "active",
|
|
4863
|
+
exposure: ["cowork", "space_builder"],
|
|
4864
|
+
constraints: {
|
|
4865
|
+
resolutions: ["720p", "1080p"],
|
|
4866
|
+
durations: { min: 3, max: 30 },
|
|
4867
|
+
references: { ...NO_REFERENCES, images: 10 },
|
|
4868
|
+
requires: ["sourceVideo"],
|
|
4869
|
+
sourceVideoSeconds: { min: 3, max: 30.05 },
|
|
4870
|
+
supports: [],
|
|
4871
|
+
prompt: KLING_V4_PROMPT,
|
|
4872
|
+
audio: KLING_V4_AUDIO
|
|
4873
|
+
},
|
|
4874
|
+
defaults: { resolution: "1080p" },
|
|
4875
|
+
usage: { ...VIDEO_USAGE },
|
|
4876
|
+
pricingKind: "video_per_second",
|
|
4877
|
+
display: {
|
|
4878
|
+
provider: "kuaishou",
|
|
4879
|
+
logo: KLING_LOGO,
|
|
4880
|
+
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."
|
|
4881
|
+
},
|
|
4882
|
+
capabilities: { acceptsSourceVideo: true, videoEdit: true }
|
|
4883
|
+
},
|
|
4809
4884
|
{
|
|
4810
4885
|
// https://fal.ai/models/minimax/h3-max-turbo/text-to-video/api (+ /image-to-video).
|
|
4811
4886
|
// image-to-video takes a start frame, an end frame, or both, and no aspect_ratio.
|
|
@@ -5664,38 +5739,38 @@ var VIDEO_MODELS = [
|
|
|
5664
5739
|
capabilities: { ...FRAMES_EXCLUDE_REFERENCES }
|
|
5665
5740
|
},
|
|
5666
5741
|
{
|
|
5667
|
-
// mode standard/pro/4k selects 720p/1080p/4K
|
|
5668
|
-
//
|
|
5669
|
-
//
|
|
5670
|
-
//
|
|
5742
|
+
// fal Kling O3 (adapters/fal-kling-omni.ts): mode standard/pro/4k selects 720p/1080p/4K
|
|
5743
|
+
// in the endpoint path. Moved off Replicate kwaivgi/kling-v3-omni-video, which fal sells
|
|
5744
|
+
// at half the price; the id and inputs stay. The Replicate mapper stays for deployed
|
|
5745
|
+
// model_catalog rows not yet switched. Frames and reference images share fal's cap of 7.
|
|
5746
|
+
// Reference video, multi-shot and keep-sound were never wired, so stay off.
|
|
5671
5747
|
id: "kling-v3-omni-video",
|
|
5672
5748
|
aliases: ["kwaivgi/kling-v3-omni-video", "kling-v3-omni"],
|
|
5673
5749
|
label: "Kling V3 Omni",
|
|
5674
5750
|
type: "video",
|
|
5675
|
-
adapter: "
|
|
5676
|
-
providerModelId: "
|
|
5751
|
+
adapter: "fal",
|
|
5752
|
+
providerModelId: "fal-ai/kling-video/o3",
|
|
5677
5753
|
lifecycle: "active",
|
|
5678
5754
|
exposure: ["cowork", "space_builder"],
|
|
5679
5755
|
constraints: {
|
|
5680
5756
|
aspectRatios: [...KLING_OMNI_RATIOS],
|
|
5681
5757
|
resolutions: ["720p", "1080p", "4k"],
|
|
5682
5758
|
durations: { min: 3, max: 15 },
|
|
5683
|
-
references: { images: 7,
|
|
5759
|
+
references: { images: 7, videos: 0, audios: 0 },
|
|
5684
5760
|
supports: ["generateAudio", "lastFrame"],
|
|
5685
5761
|
prompt: KLING_PROMPT2,
|
|
5686
5762
|
audio: "optional"
|
|
5687
5763
|
},
|
|
5688
5764
|
defaults: { durationSeconds: 5, aspectRatio: "16:9", generateAudio: true, mode: "pro" },
|
|
5689
|
-
usage: {
|
|
5765
|
+
usage: { ...VIDEO_USAGE3 },
|
|
5690
5766
|
pricingKind: "video_per_second",
|
|
5691
5767
|
display: {
|
|
5692
5768
|
provider: "kuaishou",
|
|
5693
5769
|
logo: "https://cdn.jsdelivr.net/npm/@lobehub/icons-static-png@1.97.0/light/kling-color.png",
|
|
5694
|
-
description: "Kuaishou Kling Video 3.0 Omni
|
|
5770
|
+
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."
|
|
5695
5771
|
}
|
|
5696
|
-
//
|
|
5697
|
-
//
|
|
5698
|
-
// the adapter sends as start_image.
|
|
5772
|
+
// No lastFrameRequiresFirstFrame: fal image-to-video needs a start frame, so the adapter
|
|
5773
|
+
// sends a lone end frame as the start frame, as the Replicate model took it.
|
|
5699
5774
|
},
|
|
5700
5775
|
{
|
|
5701
5776
|
id: "minimax-h3",
|
|
@@ -9310,11 +9385,11 @@ function toolInput(ctx, req, output) {
|
|
|
9310
9385
|
}
|
|
9311
9386
|
var EXR_DEFAULT_PROMPT = "The same video in high dynamic range, with unchanged content, motion, framing and timing.";
|
|
9312
9387
|
async function submitFalVideoTool(req, ctx, opts) {
|
|
9313
|
-
const
|
|
9314
|
-
if (!
|
|
9388
|
+
const plan4 = planVideoTool(ctx.model, req);
|
|
9389
|
+
if (!plan4.ok) {
|
|
9315
9390
|
throw new ModelKitError({
|
|
9316
9391
|
code: "unsupported_option",
|
|
9317
|
-
message:
|
|
9392
|
+
message: plan4.error,
|
|
9318
9393
|
provider: "fal",
|
|
9319
9394
|
model: ctx.model.id,
|
|
9320
9395
|
retryable: false
|
|
@@ -9322,7 +9397,7 @@ async function submitFalVideoTool(req, ctx, opts) {
|
|
|
9322
9397
|
}
|
|
9323
9398
|
const target = new URL(`${FAL_QUEUE_ORIGIN}/${ctx.model.providerModelId}`);
|
|
9324
9399
|
if (opts.webhookUrl !== void 0) target.searchParams.set("fal_webhook", opts.webhookUrl);
|
|
9325
|
-
const res = await queueFetch(ctx, target.toString(), "POST", toolInput(ctx, req,
|
|
9400
|
+
const res = await queueFetch(ctx, target.toString(), "POST", toolInput(ctx, req, plan4.output));
|
|
9326
9401
|
const parsed = submitResponseSchema.safeParse(await readJson(ctx, res));
|
|
9327
9402
|
if (!parsed.success) {
|
|
9328
9403
|
throw new ModelKitError({
|
|
@@ -9340,7 +9415,7 @@ async function submitFalVideoTool(req, ctx, opts) {
|
|
|
9340
9415
|
statusUrl: parsed.data.status_url,
|
|
9341
9416
|
responseUrl: parsed.data.response_url,
|
|
9342
9417
|
cancelUrl: parsed.data.cancel_url,
|
|
9343
|
-
output:
|
|
9418
|
+
output: plan4.output
|
|
9344
9419
|
};
|
|
9345
9420
|
}
|
|
9346
9421
|
async function falVideoToolStatus(sub, ctx) {
|
|
@@ -10029,14 +10104,14 @@ function planFalImage(req, providerModelId, model) {
|
|
|
10029
10104
|
const exact = falExactSize(spec, req);
|
|
10030
10105
|
const call = { label: spec.label, req, refs, edit: edit2, ...exact !== void 0 && { exact } };
|
|
10031
10106
|
const built = family.build(call, model);
|
|
10032
|
-
const
|
|
10107
|
+
const plan4 = {
|
|
10033
10108
|
endpoint: edit2 && family.editEndpoint !== void 0 ? family.editEndpoint : id,
|
|
10034
10109
|
input: built.input,
|
|
10035
10110
|
output: family.output ?? "images"
|
|
10036
10111
|
};
|
|
10037
|
-
if (built.imageQuality !== void 0)
|
|
10038
|
-
if (built.imageSize !== void 0)
|
|
10039
|
-
return
|
|
10112
|
+
if (built.imageQuality !== void 0) plan4.imageQuality = built.imageQuality;
|
|
10113
|
+
if (built.imageSize !== void 0) plan4.imageSize = built.imageSize;
|
|
10114
|
+
return plan4;
|
|
10040
10115
|
}
|
|
10041
10116
|
var FalFileSchema = z14.object({ url: z14.string(), content_type: z14.string().nullish() });
|
|
10042
10117
|
var ImagesPayloadSchema = z14.object({ images: z14.array(FalFileSchema) });
|
|
@@ -10058,18 +10133,18 @@ async function downloadFalFile(ctx, file) {
|
|
|
10058
10133
|
const mime = res.headers.get("content-type") ?? file.content_type ?? "";
|
|
10059
10134
|
return { bytes: new Uint8Array(await res.arrayBuffer()), mime };
|
|
10060
10135
|
}
|
|
10061
|
-
function filesOf(payload,
|
|
10062
|
-
if (
|
|
10136
|
+
function filesOf(payload, plan4) {
|
|
10137
|
+
if (plan4.output === "image") {
|
|
10063
10138
|
const parsed2 = ImagePayloadSchema.safeParse(payload);
|
|
10064
10139
|
return parsed2.success ? [parsed2.data.image] : [];
|
|
10065
10140
|
}
|
|
10066
10141
|
const parsed = ImagesPayloadSchema.safeParse(payload);
|
|
10067
10142
|
return parsed.success ? parsed.data.images : [];
|
|
10068
10143
|
}
|
|
10069
|
-
async function collectFalPlanImages(payload,
|
|
10070
|
-
const files = filesOf(payload,
|
|
10144
|
+
async function collectFalPlanImages(payload, plan4, ctx, req) {
|
|
10145
|
+
const files = filesOf(payload, plan4);
|
|
10071
10146
|
if (files.length === 0) {
|
|
10072
|
-
throw fail2(ctx.model.id, `fal ${
|
|
10147
|
+
throw fail2(ctx.model.id, `fal ${plan4.endpoint} returned no image`, "provider_rejected");
|
|
10073
10148
|
}
|
|
10074
10149
|
const images = await Promise.all(
|
|
10075
10150
|
files.map(async (file) => {
|
|
@@ -10084,18 +10159,18 @@ async function collectFalPlanImages(payload, plan3, ctx, req) {
|
|
|
10084
10159
|
unit: "images",
|
|
10085
10160
|
quantity: images.length
|
|
10086
10161
|
};
|
|
10087
|
-
const billedSize =
|
|
10162
|
+
const billedSize = plan4.imageSize ?? req.size;
|
|
10088
10163
|
if (billedSize !== void 0 && ctx.model.type === "image") usage3.imageSize = billedSize;
|
|
10089
|
-
if (
|
|
10164
|
+
if (plan4.imageQuality !== void 0) usage3.imageQuality = plan4.imageQuality;
|
|
10090
10165
|
const result = { images, usage: usage3, raw: payload };
|
|
10091
10166
|
const remote = files.find((f) => !f.url.startsWith("data:"));
|
|
10092
10167
|
if (remote !== void 0) result.outputUrl = remote.url;
|
|
10093
10168
|
return result;
|
|
10094
10169
|
}
|
|
10095
10170
|
async function generateFalFamilyImage(req, ctx, run) {
|
|
10096
|
-
const
|
|
10097
|
-
const payload = await run(
|
|
10098
|
-
return collectFalPlanImages(payload,
|
|
10171
|
+
const plan4 = planFalImage(req, ctx.model.providerModelId, ctx.model.id);
|
|
10172
|
+
const payload = await run(plan4.endpoint, plan4.input);
|
|
10173
|
+
return collectFalPlanImages(payload, plan4, ctx, req);
|
|
10099
10174
|
}
|
|
10100
10175
|
|
|
10101
10176
|
// src/adapters/fal-mask.ts
|
|
@@ -11113,6 +11188,8 @@ var MOTION_PRO = "fal-ai/kling-video/v3/pro/motion-control";
|
|
|
11113
11188
|
var MOTION_STANDARD = "fal-ai/kling-video/v3/standard/motion-control";
|
|
11114
11189
|
var O3_REFERENCE = "fal-ai/kling-video/o3/pro/reference-to-video";
|
|
11115
11190
|
var O3_EDIT = "fal-ai/kling-video/o3/pro/video-to-video/edit";
|
|
11191
|
+
var V4_FAMILY = "kling/v4";
|
|
11192
|
+
var V4_EDIT = "kling/v4/video-to-video/edit";
|
|
11116
11193
|
function motionControl(endpoint, req, ctx) {
|
|
11117
11194
|
const [character] = req.referenceImages ?? [];
|
|
11118
11195
|
const [motion] = req.referenceVideos ?? [];
|
|
@@ -11172,6 +11249,61 @@ var klingV3Family = {
|
|
|
11172
11249
|
return motionControl(id, req, ctx);
|
|
11173
11250
|
}
|
|
11174
11251
|
};
|
|
11252
|
+
function v4Generate(req, ctx) {
|
|
11253
|
+
const images = urls(req.referenceImages);
|
|
11254
|
+
const videos = urls(req.referenceVideos);
|
|
11255
|
+
const duration = wholeSeconds(req, ctx);
|
|
11256
|
+
const resolution = resolutionOf(req, ctx);
|
|
11257
|
+
const input = { prompt: req.prompt.trim(), duration, resolution };
|
|
11258
|
+
let endpoint;
|
|
11259
|
+
if (images.length + videos.length > 0) {
|
|
11260
|
+
endpoint = `${V4_FAMILY}/reference-to-video`;
|
|
11261
|
+
if (images.length > 0) input["image_urls"] = images;
|
|
11262
|
+
if (videos.length > 0) input["video_urls"] = videos;
|
|
11263
|
+
if (req.firstFrame) input["start_image_url"] = refToUrl(req.firstFrame);
|
|
11264
|
+
if (req.aspectRatio !== void 0) {
|
|
11265
|
+
input["aspect_ratio"] = req.aspectRatio === "adaptive" ? "auto" : req.aspectRatio;
|
|
11266
|
+
}
|
|
11267
|
+
} else if (req.firstFrame) {
|
|
11268
|
+
endpoint = `${V4_FAMILY}/image-to-video`;
|
|
11269
|
+
input["start_image_url"] = refToUrl(req.firstFrame);
|
|
11270
|
+
if (req.lastFrame) input["end_image_url"] = refToUrl(req.lastFrame);
|
|
11271
|
+
} else {
|
|
11272
|
+
endpoint = `${V4_FAMILY}/text-to-video`;
|
|
11273
|
+
const ratio = concreteRatio(req);
|
|
11274
|
+
if (ratio !== void 0) input["aspect_ratio"] = ratio;
|
|
11275
|
+
}
|
|
11276
|
+
return { endpoint, input, resolution, seconds: requestedSeconds(duration) };
|
|
11277
|
+
}
|
|
11278
|
+
function v4Edit(req, ctx) {
|
|
11279
|
+
if (req.sourceVideo === void 0) throw refusal(ctx, "needs a source video", "missing_input");
|
|
11280
|
+
const resolution = resolutionOf(req, ctx);
|
|
11281
|
+
const input = {
|
|
11282
|
+
prompt: req.prompt.trim(),
|
|
11283
|
+
video_url: refToUrl(req.sourceVideo),
|
|
11284
|
+
resolution
|
|
11285
|
+
};
|
|
11286
|
+
const images = urls(req.referenceImages);
|
|
11287
|
+
if (images.length > 0) input["image_urls"] = images;
|
|
11288
|
+
if (req.durationSeconds === void 0) {
|
|
11289
|
+
return {
|
|
11290
|
+
endpoint: V4_EDIT,
|
|
11291
|
+
input,
|
|
11292
|
+
resolution,
|
|
11293
|
+
seconds: inputLengthSeconds(req, req.sourceVideo)
|
|
11294
|
+
};
|
|
11295
|
+
}
|
|
11296
|
+
const duration = wholeSeconds(req, ctx);
|
|
11297
|
+
input["duration"] = duration;
|
|
11298
|
+
return { endpoint: V4_EDIT, input, resolution, seconds: requestedSeconds(duration) };
|
|
11299
|
+
}
|
|
11300
|
+
var KLING_V4_VIDEO_IDS = /* @__PURE__ */ new Set([V4_FAMILY, V4_EDIT]);
|
|
11301
|
+
var klingV4Family = {
|
|
11302
|
+
ids: KLING_V4_VIDEO_IDS,
|
|
11303
|
+
plan(req, ctx) {
|
|
11304
|
+
return ctx.model.providerModelId.toLowerCase() === V4_EDIT ? v4Edit(req, ctx) : v4Generate(req, ctx);
|
|
11305
|
+
}
|
|
11306
|
+
};
|
|
11175
11307
|
|
|
11176
11308
|
// src/replicate-video-kinds.ts
|
|
11177
11309
|
function replicateBaseModelId(providerModelId) {
|
|
@@ -11193,15 +11325,57 @@ var KLING_TIERS = [
|
|
|
11193
11325
|
{ mode: "pro", resolution: "1080p" },
|
|
11194
11326
|
{ mode: "4k", resolution: "4k" }
|
|
11195
11327
|
];
|
|
11328
|
+
var KLING_O3_OMNI = "fal-ai/kling-video/o3";
|
|
11196
11329
|
function klingTier(req) {
|
|
11197
11330
|
return KLING_TIERS.find((tier) => tier.resolution === req.resolution) ?? KLING_TIERS.find((tier) => tier.mode === req.mode) ?? KLING_TIERS[0];
|
|
11198
11331
|
}
|
|
11199
11332
|
|
|
11333
|
+
// src/adapters/fal-kling-omni.ts
|
|
11334
|
+
function plan(req, ctx) {
|
|
11335
|
+
const tier = klingTier(req);
|
|
11336
|
+
const duration = wholeSeconds(req, ctx);
|
|
11337
|
+
const input = {
|
|
11338
|
+
prompt: req.prompt.trim(),
|
|
11339
|
+
duration: String(duration),
|
|
11340
|
+
generate_audio: req.generateAudio ?? true
|
|
11341
|
+
};
|
|
11342
|
+
const start = req.firstFrame ?? req.lastFrame;
|
|
11343
|
+
const end = req.firstFrame ? req.lastFrame : void 0;
|
|
11344
|
+
const images = urls(req.referenceImages);
|
|
11345
|
+
let task;
|
|
11346
|
+
if (images.length > 0) {
|
|
11347
|
+
task = "reference-to-video";
|
|
11348
|
+
input["image_urls"] = images;
|
|
11349
|
+
if (start) input["start_image_url"] = refToUrl(start);
|
|
11350
|
+
if (end) input["end_image_url"] = refToUrl(end);
|
|
11351
|
+
} else if (start) {
|
|
11352
|
+
task = "image-to-video";
|
|
11353
|
+
input["image_url"] = refToUrl(start);
|
|
11354
|
+
if (end) input["end_image_url"] = refToUrl(end);
|
|
11355
|
+
} else {
|
|
11356
|
+
task = "text-to-video";
|
|
11357
|
+
}
|
|
11358
|
+
const ratio = concreteRatio(req);
|
|
11359
|
+
if (ratio !== void 0 && start === void 0) input["aspect_ratio"] = ratio;
|
|
11360
|
+
return {
|
|
11361
|
+
endpoint: `${KLING_O3_OMNI}/${tier.mode}/${task}`,
|
|
11362
|
+
input,
|
|
11363
|
+
resolution: tier.resolution,
|
|
11364
|
+
seconds: requestedSeconds(duration)
|
|
11365
|
+
};
|
|
11366
|
+
}
|
|
11367
|
+
var klingOmniFamily = {
|
|
11368
|
+
ids: /* @__PURE__ */ new Set([KLING_O3_OMNI]),
|
|
11369
|
+
plan
|
|
11370
|
+
};
|
|
11371
|
+
|
|
11200
11372
|
// src/resolve-video-rules.ts
|
|
11201
11373
|
var MOTION_PRO2 = "fal-ai/kling-video/v3/pro/motion-control";
|
|
11202
11374
|
var MOTION_STANDARD2 = "fal-ai/kling-video/v3/standard/motion-control";
|
|
11203
11375
|
var O3_REFERENCE2 = "fal-ai/kling-video/o3/pro/reference-to-video";
|
|
11204
11376
|
var O3_EDIT2 = "fal-ai/kling-video/o3/pro/video-to-video/edit";
|
|
11377
|
+
var KLING_V4 = "kling/v4";
|
|
11378
|
+
var KLING_V4_EDIT = "kling/v4/video-to-video/edit";
|
|
11205
11379
|
var H3_TURBO = "minimax/h3-max-turbo";
|
|
11206
11380
|
var H3_RECAST = "minimax/h3-max/recast";
|
|
11207
11381
|
var H3_RELIGHT = "minimax/h3-max/relight";
|
|
@@ -11210,6 +11384,7 @@ var HAPPY_HORSE_EDIT = "alibaba/happy-horse/video-edit";
|
|
|
11210
11384
|
var VIDU_Q4 = "fal-ai/vidu/q4";
|
|
11211
11385
|
var OMNIHUMAN_V2 = "bytedance/omnihuman/v2";
|
|
11212
11386
|
var KLING_O3_IMAGE_CAP = 7;
|
|
11387
|
+
var KLING_V4_IMAGE_CAP = 10;
|
|
11213
11388
|
var TURBO_AUDIO_MIN_SECONDS = 2;
|
|
11214
11389
|
var OMNIHUMAN_AUDIO_SECONDS = { min: 4, max: 300 };
|
|
11215
11390
|
function missing(message) {
|
|
@@ -11265,6 +11440,23 @@ function o3Reference2(req) {
|
|
|
11265
11440
|
}
|
|
11266
11441
|
return needsPrompt(req);
|
|
11267
11442
|
}
|
|
11443
|
+
function hasReferences(req) {
|
|
11444
|
+
return count(req.referenceImages) + count(req.referenceVideos) > 0;
|
|
11445
|
+
}
|
|
11446
|
+
function klingV4(req) {
|
|
11447
|
+
if (hasReferences(req)) {
|
|
11448
|
+
if (req.lastFrame !== void 0) {
|
|
11449
|
+
return unsupported2("takes an end frame only without reference images or videos");
|
|
11450
|
+
}
|
|
11451
|
+
const images = count(req.referenceImages) + (req.firstFrame === void 0 ? 0 : 1);
|
|
11452
|
+
if (images > KLING_V4_IMAGE_CAP) {
|
|
11453
|
+
return unsupported2(
|
|
11454
|
+
`takes up to ${KLING_V4_IMAGE_CAP} images in all, the start frame included; this request has ${images}`
|
|
11455
|
+
);
|
|
11456
|
+
}
|
|
11457
|
+
}
|
|
11458
|
+
return needsPrompt(req);
|
|
11459
|
+
}
|
|
11268
11460
|
function h3Turbo(req) {
|
|
11269
11461
|
if (count(req.referenceImages) + count(req.referenceVideos) > 0) {
|
|
11270
11462
|
return unsupported2("takes no reference images or videos");
|
|
@@ -11341,7 +11533,10 @@ var RULES = /* @__PURE__ */ new Map([
|
|
|
11341
11533
|
[MOTION_PRO2, motionControl2],
|
|
11342
11534
|
[MOTION_STANDARD2, motionControl2],
|
|
11343
11535
|
[O3_REFERENCE2, o3Reference2],
|
|
11536
|
+
[KLING_O3_OMNI, o3Reference2],
|
|
11344
11537
|
[O3_EDIT2, (req) => needsSource(req) ?? needsPrompt(req)],
|
|
11538
|
+
[KLING_V4, klingV4],
|
|
11539
|
+
[KLING_V4_EDIT, (req) => needsSource(req) ?? needsPrompt(req)],
|
|
11345
11540
|
[H3_TURBO, h3Turbo],
|
|
11346
11541
|
[MINIMAX_H3_INSERT, h3Insert],
|
|
11347
11542
|
[H3_RECAST, h3Recast],
|
|
@@ -11370,13 +11565,14 @@ function h3EndFrameRatioWarning(model, ratio) {
|
|
|
11370
11565
|
message: `${model.id} follows the end frame's aspect ratio`
|
|
11371
11566
|
};
|
|
11372
11567
|
}
|
|
11373
|
-
function
|
|
11568
|
+
function takesKlingMode(model) {
|
|
11569
|
+
if (model.adapter === "fal") return model.providerModelId.toLowerCase() === KLING_O3_OMNI;
|
|
11374
11570
|
if (model.adapter !== "replicate") return false;
|
|
11375
11571
|
const kind = videoKind(model.providerModelId);
|
|
11376
11572
|
return kind === "kling" || kind === "kling-omni";
|
|
11377
11573
|
}
|
|
11378
|
-
function
|
|
11379
|
-
if (
|
|
11574
|
+
function fillKlingModeResolution(model, req) {
|
|
11575
|
+
if (takesKlingMode(model) && req.resolution === void 0) {
|
|
11380
11576
|
req.resolution = klingTier(req).resolution;
|
|
11381
11577
|
}
|
|
11382
11578
|
}
|
|
@@ -11390,6 +11586,19 @@ function applyFalVideoRules(model, req, callerRatio, warnings) {
|
|
|
11390
11586
|
warnings.push(viduSilentWarning(model));
|
|
11391
11587
|
req.generateAudio = false;
|
|
11392
11588
|
}
|
|
11589
|
+
if (id === KLING_V4 && req.firstFrame !== void 0 && !hasReferences(req)) {
|
|
11590
|
+
if (req.aspectRatio !== void 0) {
|
|
11591
|
+
if (callerRatio !== void 0) {
|
|
11592
|
+
warnings.push({
|
|
11593
|
+
code: "ratio_dropped",
|
|
11594
|
+
field: "aspectRatio",
|
|
11595
|
+
from: req.aspectRatio,
|
|
11596
|
+
message: `${model.id} follows the start frame's aspect ratio`
|
|
11597
|
+
});
|
|
11598
|
+
}
|
|
11599
|
+
delete req.aspectRatio;
|
|
11600
|
+
}
|
|
11601
|
+
}
|
|
11393
11602
|
const endFrameOnly = req.lastFrame !== void 0 && req.firstFrame === void 0;
|
|
11394
11603
|
if (id === H3_TURBO && endFrameOnly && req.aspectRatio !== void 0) {
|
|
11395
11604
|
if (callerRatio !== void 0 && callerRatio !== "adaptive") {
|
|
@@ -11515,7 +11724,7 @@ var minimaxH3MaxFamily = {
|
|
|
11515
11724
|
|
|
11516
11725
|
// src/adapters/fal-omnihuman.ts
|
|
11517
11726
|
var OMNIHUMAN_V22 = "bytedance/omnihuman/v2";
|
|
11518
|
-
function
|
|
11727
|
+
function plan2(req, ctx) {
|
|
11519
11728
|
const [image] = req.referenceImages ?? [];
|
|
11520
11729
|
const [audio] = req.referenceAudios ?? [];
|
|
11521
11730
|
if (image === void 0 || audio === void 0) {
|
|
@@ -11526,14 +11735,14 @@ function plan(req, ctx) {
|
|
|
11526
11735
|
return { endpoint: OMNIHUMAN_V22, input, seconds: inputLengthSeconds(req, audio) };
|
|
11527
11736
|
}
|
|
11528
11737
|
var OMNIHUMAN_MODEL_IDS = /* @__PURE__ */ new Set([OMNIHUMAN_V22]);
|
|
11529
|
-
var omnihumanFamily = { ids: OMNIHUMAN_MODEL_IDS, plan };
|
|
11738
|
+
var omnihumanFamily = { ids: OMNIHUMAN_MODEL_IDS, plan: plan2 };
|
|
11530
11739
|
|
|
11531
11740
|
// src/adapters/fal-vidu.ts
|
|
11532
11741
|
var FAMILY2 = "fal-ai/vidu/q4";
|
|
11533
11742
|
function viduTier(resolution) {
|
|
11534
11743
|
return resolution === "2k" || resolution === "4k" ? upperTier(resolution) : resolution;
|
|
11535
11744
|
}
|
|
11536
|
-
function
|
|
11745
|
+
function plan3(req, ctx) {
|
|
11537
11746
|
const images = urls(req.referenceImages);
|
|
11538
11747
|
const audios = urls(req.referenceAudios);
|
|
11539
11748
|
const duration = wholeSeconds(req, ctx);
|
|
@@ -11560,11 +11769,13 @@ function plan2(req, ctx) {
|
|
|
11560
11769
|
return { endpoint, input, resolution, seconds: requestedSeconds(duration) };
|
|
11561
11770
|
}
|
|
11562
11771
|
var VIDU_MODEL_IDS = /* @__PURE__ */ new Set([FAMILY2]);
|
|
11563
|
-
var viduFamily = { ids: VIDU_MODEL_IDS, plan:
|
|
11772
|
+
var viduFamily = { ids: VIDU_MODEL_IDS, plan: plan3 };
|
|
11564
11773
|
|
|
11565
11774
|
// src/adapters/fal-video-families.ts
|
|
11566
11775
|
var FAMILIES2 = [
|
|
11567
11776
|
klingV3Family,
|
|
11777
|
+
klingOmniFamily,
|
|
11778
|
+
klingV4Family,
|
|
11568
11779
|
minimaxH3MaxFamily,
|
|
11569
11780
|
happyHorseFamily,
|
|
11570
11781
|
viduFamily,
|
|
@@ -11851,8 +12062,8 @@ async function collectFalImages(payload, ctx, req, label) {
|
|
|
11851
12062
|
};
|
|
11852
12063
|
}
|
|
11853
12064
|
async function generateSpecImage(req, ctx, deps, spec) {
|
|
11854
|
-
const
|
|
11855
|
-
const endpoint =
|
|
12065
|
+
const hasReferences2 = (req.references ?? []).length > 0;
|
|
12066
|
+
const endpoint = hasReferences2 && spec.spec.editEndpoint !== void 0 ? spec.spec.editEndpoint : ctx.model.providerModelId;
|
|
11856
12067
|
const payload = await runJob(ctx, deps, endpoint, spec.input);
|
|
11857
12068
|
return collectFalImages(payload, ctx, req, `fal ${endpoint}`);
|
|
11858
12069
|
}
|
|
@@ -12041,7 +12252,7 @@ function extractVideoUrl(result, endpoint, model) {
|
|
|
12041
12252
|
}
|
|
12042
12253
|
async function generateFalVideo(req, ctx, deps) {
|
|
12043
12254
|
const providerModelId = ctx.model.providerModelId;
|
|
12044
|
-
const
|
|
12255
|
+
const plan4 = planFalFamilyVideo(req, ctx);
|
|
12045
12256
|
const start = (endpoint2, input, usageOf2) => startFalVideoJob(
|
|
12046
12257
|
ctx,
|
|
12047
12258
|
() => falClientOf(ctx, deps),
|
|
@@ -12049,7 +12260,7 @@ async function generateFalVideo(req, ctx, deps) {
|
|
|
12049
12260
|
input,
|
|
12050
12261
|
videoFileDecoder(ctx, req, endpoint2, usageOf2)
|
|
12051
12262
|
);
|
|
12052
|
-
if (
|
|
12263
|
+
if (plan4 !== void 0) return start(plan4.endpoint, plan4.input, planUsage(ctx, plan4));
|
|
12053
12264
|
if (isKling(providerModelId)) return start(KLING_O1_ENDPOINT, klingO1Input(req));
|
|
12054
12265
|
if (isWan(providerModelId)) {
|
|
12055
12266
|
const { endpoint: endpoint2, input } = wanVideo(req, providerModelId.toLowerCase());
|
|
@@ -12099,9 +12310,9 @@ function videoFileDecoder(ctx, req, endpoint, usageOf2) {
|
|
|
12099
12310
|
raw: payload
|
|
12100
12311
|
});
|
|
12101
12312
|
}
|
|
12102
|
-
function planUsage(ctx,
|
|
12313
|
+
function planUsage(ctx, plan4) {
|
|
12103
12314
|
return (payload) => {
|
|
12104
|
-
const seconds3 =
|
|
12315
|
+
const seconds3 = plan4.seconds(payload);
|
|
12105
12316
|
return {
|
|
12106
12317
|
model: ctx.model.id,
|
|
12107
12318
|
provider: "fal",
|
|
@@ -12109,7 +12320,7 @@ function planUsage(ctx, plan3) {
|
|
|
12109
12320
|
unit: "seconds",
|
|
12110
12321
|
quantity: seconds3,
|
|
12111
12322
|
durationSeconds: seconds3,
|
|
12112
|
-
...
|
|
12323
|
+
...plan4.resolution !== void 0 && { resolution: plan4.resolution }
|
|
12113
12324
|
};
|
|
12114
12325
|
};
|
|
12115
12326
|
}
|
|
@@ -14199,8 +14410,8 @@ function imageBody(req, ctx, outputFormat) {
|
|
|
14199
14410
|
function videoBody(req, ctx, mode) {
|
|
14200
14411
|
const prompt = checkPrompt(req, ctx);
|
|
14201
14412
|
const model = lumaModel(ctx);
|
|
14202
|
-
const
|
|
14203
|
-
if (
|
|
14413
|
+
const hasReferences2 = (req.referenceImages ?? []).length + (req.referenceVideos ?? []).length + (req.referenceAudios ?? []).length > 0;
|
|
14414
|
+
if (hasReferences2) {
|
|
14204
14415
|
refuseOrDrop(
|
|
14205
14416
|
ctx,
|
|
14206
14417
|
"referenceImages",
|
|
@@ -16563,10 +16774,10 @@ function resolveVideoOptions(model, request, onUnsupported = "error") {
|
|
|
16563
16774
|
warnings
|
|
16564
16775
|
);
|
|
16565
16776
|
if (aspectRatio !== void 0) merged.aspectRatio = aspectRatio;
|
|
16566
|
-
|
|
16777
|
+
fillKlingModeResolution(model, merged);
|
|
16567
16778
|
const resolution = resolveVideoResolution(merged.resolution, model, onUnsupported, warnings);
|
|
16568
16779
|
if (resolution !== void 0) merged.resolution = resolution;
|
|
16569
|
-
if (
|
|
16780
|
+
if (takesKlingMode(model)) delete merged.mode;
|
|
16570
16781
|
const duration = resolveDuration(
|
|
16571
16782
|
merged.durationSeconds,
|
|
16572
16783
|
c.durations,
|