@shop-os/modelkit 0.7.7 → 0.7.10
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 +18 -0
- package/dist/catalog.cjs +26 -21
- package/dist/catalog.cjs.map +1 -1
- package/dist/catalog.js +26 -21
- package/dist/catalog.js.map +1 -1
- package/dist/index.cjs +112 -51
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +112 -51
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5129,8 +5129,10 @@ var RAY_RESOLUTIONS = ["360p", "720p", "1080p"];
|
|
|
5129
5129
|
var RAY_PROMPT = { referenceSyntax: "numbered", maxChars: 6e3 };
|
|
5130
5130
|
var LUMA_VIDEO_MODELS = [
|
|
5131
5131
|
{
|
|
5132
|
-
// https://docs.agents.lumalabs.ai: type "video" with a
|
|
5133
|
-
// firstFrame and lastFrame ride as start_frame and end_frame.
|
|
5132
|
+
// https://docs.agents.lumalabs.ai: type "video" with a 5 s or 10 s duration;
|
|
5133
|
+
// firstFrame and lastFrame ride as start_frame and end_frame. Luma bills a
|
|
5134
|
+
// 10 s clip at 3x the 5 s price; pro-backend prices it that way, so this row
|
|
5135
|
+
// must not offer 10 s before that pricing is deployed (ENG-3324).
|
|
5134
5136
|
id: "ray-3.2",
|
|
5135
5137
|
aliases: [],
|
|
5136
5138
|
label: "Ray 3.2",
|
|
@@ -5142,7 +5144,7 @@ var LUMA_VIDEO_MODELS = [
|
|
|
5142
5144
|
constraints: {
|
|
5143
5145
|
aspectRatios: ["adaptive", ...RAY_RATIOS],
|
|
5144
5146
|
resolutions: [...RAY_RESOLUTIONS],
|
|
5145
|
-
durations: [5],
|
|
5147
|
+
durations: [5, 10],
|
|
5146
5148
|
supports: ["lastFrame"],
|
|
5147
5149
|
prompt: { ...RAY_PROMPT },
|
|
5148
5150
|
audio: "never"
|
|
@@ -5152,7 +5154,7 @@ var LUMA_VIDEO_MODELS = [
|
|
|
5152
5154
|
pricingKind: "video_per_second",
|
|
5153
5155
|
display: {
|
|
5154
5156
|
provider: "luma",
|
|
5155
|
-
description: "Luma Ray 3.2 text- and image-to-video with optional first and last frames, 5-second clips at up to 1080p.",
|
|
5157
|
+
description: "Luma Ray 3.2 text- and image-to-video with optional first and last frames, 5- or 10-second clips at up to 1080p.",
|
|
5156
5158
|
logo: LUMA_LOGO2
|
|
5157
5159
|
},
|
|
5158
5160
|
capabilities: {}
|
|
@@ -5662,38 +5664,38 @@ var VIDEO_MODELS = [
|
|
|
5662
5664
|
capabilities: { ...FRAMES_EXCLUDE_REFERENCES }
|
|
5663
5665
|
},
|
|
5664
5666
|
{
|
|
5665
|
-
// mode standard/pro/4k selects 720p/1080p/4K
|
|
5666
|
-
//
|
|
5667
|
-
//
|
|
5668
|
-
//
|
|
5667
|
+
// fal Kling O3 (adapters/fal-kling-omni.ts): mode standard/pro/4k selects 720p/1080p/4K
|
|
5668
|
+
// in the endpoint path. Moved off Replicate kwaivgi/kling-v3-omni-video, which fal sells
|
|
5669
|
+
// at half the price; the id and inputs stay. The Replicate mapper stays for deployed
|
|
5670
|
+
// model_catalog rows not yet switched. Frames and reference images share fal's cap of 7.
|
|
5671
|
+
// Reference video, multi-shot and keep-sound were never wired, so stay off.
|
|
5669
5672
|
id: "kling-v3-omni-video",
|
|
5670
5673
|
aliases: ["kwaivgi/kling-v3-omni-video", "kling-v3-omni"],
|
|
5671
5674
|
label: "Kling V3 Omni",
|
|
5672
5675
|
type: "video",
|
|
5673
|
-
adapter: "
|
|
5674
|
-
providerModelId: "
|
|
5676
|
+
adapter: "fal",
|
|
5677
|
+
providerModelId: "fal-ai/kling-video/o3",
|
|
5675
5678
|
lifecycle: "active",
|
|
5676
5679
|
exposure: ["cowork", "space_builder"],
|
|
5677
5680
|
constraints: {
|
|
5678
5681
|
aspectRatios: [...KLING_OMNI_RATIOS],
|
|
5679
5682
|
resolutions: ["720p", "1080p", "4k"],
|
|
5680
5683
|
durations: { min: 3, max: 15 },
|
|
5681
|
-
references: { images: 7,
|
|
5684
|
+
references: { images: 7, videos: 0, audios: 0 },
|
|
5682
5685
|
supports: ["generateAudio", "lastFrame"],
|
|
5683
5686
|
prompt: KLING_PROMPT2,
|
|
5684
5687
|
audio: "optional"
|
|
5685
5688
|
},
|
|
5686
5689
|
defaults: { durationSeconds: 5, aspectRatio: "16:9", generateAudio: true, mode: "pro" },
|
|
5687
|
-
usage: {
|
|
5690
|
+
usage: { ...VIDEO_USAGE3 },
|
|
5688
5691
|
pricingKind: "video_per_second",
|
|
5689
5692
|
display: {
|
|
5690
5693
|
provider: "kuaishou",
|
|
5691
5694
|
logo: "https://cdn.jsdelivr.net/npm/@lobehub/icons-static-png@1.97.0/light/kling-color.png",
|
|
5692
|
-
description: "Kuaishou Kling Video 3.0 Omni
|
|
5695
|
+
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."
|
|
5693
5696
|
}
|
|
5694
|
-
//
|
|
5695
|
-
//
|
|
5696
|
-
// the adapter sends as start_image.
|
|
5697
|
+
// No lastFrameRequiresFirstFrame: fal image-to-video needs a start frame, so the adapter
|
|
5698
|
+
// sends a lone end frame as the start frame, as the Replicate model took it.
|
|
5697
5699
|
},
|
|
5698
5700
|
{
|
|
5699
5701
|
id: "minimax-h3",
|
|
@@ -9308,11 +9310,11 @@ function toolInput(ctx, req, output) {
|
|
|
9308
9310
|
}
|
|
9309
9311
|
var EXR_DEFAULT_PROMPT = "The same video in high dynamic range, with unchanged content, motion, framing and timing.";
|
|
9310
9312
|
async function submitFalVideoTool(req, ctx, opts) {
|
|
9311
|
-
const
|
|
9312
|
-
if (!
|
|
9313
|
+
const plan4 = planVideoTool(ctx.model, req);
|
|
9314
|
+
if (!plan4.ok) {
|
|
9313
9315
|
throw new ModelKitError({
|
|
9314
9316
|
code: "unsupported_option",
|
|
9315
|
-
message:
|
|
9317
|
+
message: plan4.error,
|
|
9316
9318
|
provider: "fal",
|
|
9317
9319
|
model: ctx.model.id,
|
|
9318
9320
|
retryable: false
|
|
@@ -9320,7 +9322,7 @@ async function submitFalVideoTool(req, ctx, opts) {
|
|
|
9320
9322
|
}
|
|
9321
9323
|
const target = new URL(`${FAL_QUEUE_ORIGIN}/${ctx.model.providerModelId}`);
|
|
9322
9324
|
if (opts.webhookUrl !== void 0) target.searchParams.set("fal_webhook", opts.webhookUrl);
|
|
9323
|
-
const res = await queueFetch(ctx, target.toString(), "POST", toolInput(ctx, req,
|
|
9325
|
+
const res = await queueFetch(ctx, target.toString(), "POST", toolInput(ctx, req, plan4.output));
|
|
9324
9326
|
const parsed = submitResponseSchema.safeParse(await readJson(ctx, res));
|
|
9325
9327
|
if (!parsed.success) {
|
|
9326
9328
|
throw new ModelKitError({
|
|
@@ -9338,7 +9340,7 @@ async function submitFalVideoTool(req, ctx, opts) {
|
|
|
9338
9340
|
statusUrl: parsed.data.status_url,
|
|
9339
9341
|
responseUrl: parsed.data.response_url,
|
|
9340
9342
|
cancelUrl: parsed.data.cancel_url,
|
|
9341
|
-
output:
|
|
9343
|
+
output: plan4.output
|
|
9342
9344
|
};
|
|
9343
9345
|
}
|
|
9344
9346
|
async function falVideoToolStatus(sub, ctx) {
|
|
@@ -10027,14 +10029,14 @@ function planFalImage(req, providerModelId, model) {
|
|
|
10027
10029
|
const exact = falExactSize(spec, req);
|
|
10028
10030
|
const call = { label: spec.label, req, refs, edit: edit2, ...exact !== void 0 && { exact } };
|
|
10029
10031
|
const built = family.build(call, model);
|
|
10030
|
-
const
|
|
10032
|
+
const plan4 = {
|
|
10031
10033
|
endpoint: edit2 && family.editEndpoint !== void 0 ? family.editEndpoint : id,
|
|
10032
10034
|
input: built.input,
|
|
10033
10035
|
output: family.output ?? "images"
|
|
10034
10036
|
};
|
|
10035
|
-
if (built.imageQuality !== void 0)
|
|
10036
|
-
if (built.imageSize !== void 0)
|
|
10037
|
-
return
|
|
10037
|
+
if (built.imageQuality !== void 0) plan4.imageQuality = built.imageQuality;
|
|
10038
|
+
if (built.imageSize !== void 0) plan4.imageSize = built.imageSize;
|
|
10039
|
+
return plan4;
|
|
10038
10040
|
}
|
|
10039
10041
|
var FalFileSchema = z14.object({ url: z14.string(), content_type: z14.string().nullish() });
|
|
10040
10042
|
var ImagesPayloadSchema = z14.object({ images: z14.array(FalFileSchema) });
|
|
@@ -10056,18 +10058,18 @@ async function downloadFalFile(ctx, file) {
|
|
|
10056
10058
|
const mime = res.headers.get("content-type") ?? file.content_type ?? "";
|
|
10057
10059
|
return { bytes: new Uint8Array(await res.arrayBuffer()), mime };
|
|
10058
10060
|
}
|
|
10059
|
-
function filesOf(payload,
|
|
10060
|
-
if (
|
|
10061
|
+
function filesOf(payload, plan4) {
|
|
10062
|
+
if (plan4.output === "image") {
|
|
10061
10063
|
const parsed2 = ImagePayloadSchema.safeParse(payload);
|
|
10062
10064
|
return parsed2.success ? [parsed2.data.image] : [];
|
|
10063
10065
|
}
|
|
10064
10066
|
const parsed = ImagesPayloadSchema.safeParse(payload);
|
|
10065
10067
|
return parsed.success ? parsed.data.images : [];
|
|
10066
10068
|
}
|
|
10067
|
-
async function collectFalPlanImages(payload,
|
|
10068
|
-
const files = filesOf(payload,
|
|
10069
|
+
async function collectFalPlanImages(payload, plan4, ctx, req) {
|
|
10070
|
+
const files = filesOf(payload, plan4);
|
|
10069
10071
|
if (files.length === 0) {
|
|
10070
|
-
throw fail2(ctx.model.id, `fal ${
|
|
10072
|
+
throw fail2(ctx.model.id, `fal ${plan4.endpoint} returned no image`, "provider_rejected");
|
|
10071
10073
|
}
|
|
10072
10074
|
const images = await Promise.all(
|
|
10073
10075
|
files.map(async (file) => {
|
|
@@ -10082,18 +10084,18 @@ async function collectFalPlanImages(payload, plan3, ctx, req) {
|
|
|
10082
10084
|
unit: "images",
|
|
10083
10085
|
quantity: images.length
|
|
10084
10086
|
};
|
|
10085
|
-
const billedSize =
|
|
10087
|
+
const billedSize = plan4.imageSize ?? req.size;
|
|
10086
10088
|
if (billedSize !== void 0 && ctx.model.type === "image") usage3.imageSize = billedSize;
|
|
10087
|
-
if (
|
|
10089
|
+
if (plan4.imageQuality !== void 0) usage3.imageQuality = plan4.imageQuality;
|
|
10088
10090
|
const result = { images, usage: usage3, raw: payload };
|
|
10089
10091
|
const remote = files.find((f) => !f.url.startsWith("data:"));
|
|
10090
10092
|
if (remote !== void 0) result.outputUrl = remote.url;
|
|
10091
10093
|
return result;
|
|
10092
10094
|
}
|
|
10093
10095
|
async function generateFalFamilyImage(req, ctx, run) {
|
|
10094
|
-
const
|
|
10095
|
-
const payload = await run(
|
|
10096
|
-
return collectFalPlanImages(payload,
|
|
10096
|
+
const plan4 = planFalImage(req, ctx.model.providerModelId, ctx.model.id);
|
|
10097
|
+
const payload = await run(plan4.endpoint, plan4.input);
|
|
10098
|
+
return collectFalPlanImages(payload, plan4, ctx, req);
|
|
10097
10099
|
}
|
|
10098
10100
|
|
|
10099
10101
|
// src/adapters/fal-mask.ts
|
|
@@ -11191,10 +11193,50 @@ var KLING_TIERS = [
|
|
|
11191
11193
|
{ mode: "pro", resolution: "1080p" },
|
|
11192
11194
|
{ mode: "4k", resolution: "4k" }
|
|
11193
11195
|
];
|
|
11196
|
+
var KLING_O3_OMNI = "fal-ai/kling-video/o3";
|
|
11194
11197
|
function klingTier(req) {
|
|
11195
11198
|
return KLING_TIERS.find((tier) => tier.resolution === req.resolution) ?? KLING_TIERS.find((tier) => tier.mode === req.mode) ?? KLING_TIERS[0];
|
|
11196
11199
|
}
|
|
11197
11200
|
|
|
11201
|
+
// src/adapters/fal-kling-omni.ts
|
|
11202
|
+
function plan(req, ctx) {
|
|
11203
|
+
const tier = klingTier(req);
|
|
11204
|
+
const duration = wholeSeconds(req, ctx);
|
|
11205
|
+
const input = {
|
|
11206
|
+
prompt: req.prompt.trim(),
|
|
11207
|
+
duration: String(duration),
|
|
11208
|
+
generate_audio: req.generateAudio ?? true
|
|
11209
|
+
};
|
|
11210
|
+
const start = req.firstFrame ?? req.lastFrame;
|
|
11211
|
+
const end = req.firstFrame ? req.lastFrame : void 0;
|
|
11212
|
+
const images = urls(req.referenceImages);
|
|
11213
|
+
let task;
|
|
11214
|
+
if (images.length > 0) {
|
|
11215
|
+
task = "reference-to-video";
|
|
11216
|
+
input["image_urls"] = images;
|
|
11217
|
+
if (start) input["start_image_url"] = refToUrl(start);
|
|
11218
|
+
if (end) input["end_image_url"] = refToUrl(end);
|
|
11219
|
+
} else if (start) {
|
|
11220
|
+
task = "image-to-video";
|
|
11221
|
+
input["image_url"] = refToUrl(start);
|
|
11222
|
+
if (end) input["end_image_url"] = refToUrl(end);
|
|
11223
|
+
} else {
|
|
11224
|
+
task = "text-to-video";
|
|
11225
|
+
}
|
|
11226
|
+
const ratio = concreteRatio(req);
|
|
11227
|
+
if (ratio !== void 0 && start === void 0) input["aspect_ratio"] = ratio;
|
|
11228
|
+
return {
|
|
11229
|
+
endpoint: `${KLING_O3_OMNI}/${tier.mode}/${task}`,
|
|
11230
|
+
input,
|
|
11231
|
+
resolution: tier.resolution,
|
|
11232
|
+
seconds: requestedSeconds(duration)
|
|
11233
|
+
};
|
|
11234
|
+
}
|
|
11235
|
+
var klingOmniFamily = {
|
|
11236
|
+
ids: /* @__PURE__ */ new Set([KLING_O3_OMNI]),
|
|
11237
|
+
plan
|
|
11238
|
+
};
|
|
11239
|
+
|
|
11198
11240
|
// src/resolve-video-rules.ts
|
|
11199
11241
|
var MOTION_PRO2 = "fal-ai/kling-video/v3/pro/motion-control";
|
|
11200
11242
|
var MOTION_STANDARD2 = "fal-ai/kling-video/v3/standard/motion-control";
|
|
@@ -11339,6 +11381,7 @@ var RULES = /* @__PURE__ */ new Map([
|
|
|
11339
11381
|
[MOTION_PRO2, motionControl2],
|
|
11340
11382
|
[MOTION_STANDARD2, motionControl2],
|
|
11341
11383
|
[O3_REFERENCE2, o3Reference2],
|
|
11384
|
+
[KLING_O3_OMNI, o3Reference2],
|
|
11342
11385
|
[O3_EDIT2, (req) => needsSource(req) ?? needsPrompt(req)],
|
|
11343
11386
|
[H3_TURBO, h3Turbo],
|
|
11344
11387
|
[MINIMAX_H3_INSERT, h3Insert],
|
|
@@ -11368,13 +11411,14 @@ function h3EndFrameRatioWarning(model, ratio) {
|
|
|
11368
11411
|
message: `${model.id} follows the end frame's aspect ratio`
|
|
11369
11412
|
};
|
|
11370
11413
|
}
|
|
11371
|
-
function
|
|
11414
|
+
function takesKlingMode(model) {
|
|
11415
|
+
if (model.adapter === "fal") return model.providerModelId.toLowerCase() === KLING_O3_OMNI;
|
|
11372
11416
|
if (model.adapter !== "replicate") return false;
|
|
11373
11417
|
const kind = videoKind(model.providerModelId);
|
|
11374
11418
|
return kind === "kling" || kind === "kling-omni";
|
|
11375
11419
|
}
|
|
11376
|
-
function
|
|
11377
|
-
if (
|
|
11420
|
+
function fillKlingModeResolution(model, req) {
|
|
11421
|
+
if (takesKlingMode(model) && req.resolution === void 0) {
|
|
11378
11422
|
req.resolution = klingTier(req).resolution;
|
|
11379
11423
|
}
|
|
11380
11424
|
}
|
|
@@ -11513,7 +11557,7 @@ var minimaxH3MaxFamily = {
|
|
|
11513
11557
|
|
|
11514
11558
|
// src/adapters/fal-omnihuman.ts
|
|
11515
11559
|
var OMNIHUMAN_V22 = "bytedance/omnihuman/v2";
|
|
11516
|
-
function
|
|
11560
|
+
function plan2(req, ctx) {
|
|
11517
11561
|
const [image] = req.referenceImages ?? [];
|
|
11518
11562
|
const [audio] = req.referenceAudios ?? [];
|
|
11519
11563
|
if (image === void 0 || audio === void 0) {
|
|
@@ -11524,14 +11568,14 @@ function plan(req, ctx) {
|
|
|
11524
11568
|
return { endpoint: OMNIHUMAN_V22, input, seconds: inputLengthSeconds(req, audio) };
|
|
11525
11569
|
}
|
|
11526
11570
|
var OMNIHUMAN_MODEL_IDS = /* @__PURE__ */ new Set([OMNIHUMAN_V22]);
|
|
11527
|
-
var omnihumanFamily = { ids: OMNIHUMAN_MODEL_IDS, plan };
|
|
11571
|
+
var omnihumanFamily = { ids: OMNIHUMAN_MODEL_IDS, plan: plan2 };
|
|
11528
11572
|
|
|
11529
11573
|
// src/adapters/fal-vidu.ts
|
|
11530
11574
|
var FAMILY2 = "fal-ai/vidu/q4";
|
|
11531
11575
|
function viduTier(resolution) {
|
|
11532
11576
|
return resolution === "2k" || resolution === "4k" ? upperTier(resolution) : resolution;
|
|
11533
11577
|
}
|
|
11534
|
-
function
|
|
11578
|
+
function plan3(req, ctx) {
|
|
11535
11579
|
const images = urls(req.referenceImages);
|
|
11536
11580
|
const audios = urls(req.referenceAudios);
|
|
11537
11581
|
const duration = wholeSeconds(req, ctx);
|
|
@@ -11558,11 +11602,12 @@ function plan2(req, ctx) {
|
|
|
11558
11602
|
return { endpoint, input, resolution, seconds: requestedSeconds(duration) };
|
|
11559
11603
|
}
|
|
11560
11604
|
var VIDU_MODEL_IDS = /* @__PURE__ */ new Set([FAMILY2]);
|
|
11561
|
-
var viduFamily = { ids: VIDU_MODEL_IDS, plan:
|
|
11605
|
+
var viduFamily = { ids: VIDU_MODEL_IDS, plan: plan3 };
|
|
11562
11606
|
|
|
11563
11607
|
// src/adapters/fal-video-families.ts
|
|
11564
11608
|
var FAMILIES2 = [
|
|
11565
11609
|
klingV3Family,
|
|
11610
|
+
klingOmniFamily,
|
|
11566
11611
|
minimaxH3MaxFamily,
|
|
11567
11612
|
happyHorseFamily,
|
|
11568
11613
|
viduFamily,
|
|
@@ -12039,7 +12084,7 @@ function extractVideoUrl(result, endpoint, model) {
|
|
|
12039
12084
|
}
|
|
12040
12085
|
async function generateFalVideo(req, ctx, deps) {
|
|
12041
12086
|
const providerModelId = ctx.model.providerModelId;
|
|
12042
|
-
const
|
|
12087
|
+
const plan4 = planFalFamilyVideo(req, ctx);
|
|
12043
12088
|
const start = (endpoint2, input, usageOf2) => startFalVideoJob(
|
|
12044
12089
|
ctx,
|
|
12045
12090
|
() => falClientOf(ctx, deps),
|
|
@@ -12047,7 +12092,7 @@ async function generateFalVideo(req, ctx, deps) {
|
|
|
12047
12092
|
input,
|
|
12048
12093
|
videoFileDecoder(ctx, req, endpoint2, usageOf2)
|
|
12049
12094
|
);
|
|
12050
|
-
if (
|
|
12095
|
+
if (plan4 !== void 0) return start(plan4.endpoint, plan4.input, planUsage(ctx, plan4));
|
|
12051
12096
|
if (isKling(providerModelId)) return start(KLING_O1_ENDPOINT, klingO1Input(req));
|
|
12052
12097
|
if (isWan(providerModelId)) {
|
|
12053
12098
|
const { endpoint: endpoint2, input } = wanVideo(req, providerModelId.toLowerCase());
|
|
@@ -12097,9 +12142,9 @@ function videoFileDecoder(ctx, req, endpoint, usageOf2) {
|
|
|
12097
12142
|
raw: payload
|
|
12098
12143
|
});
|
|
12099
12144
|
}
|
|
12100
|
-
function planUsage(ctx,
|
|
12145
|
+
function planUsage(ctx, plan4) {
|
|
12101
12146
|
return (payload) => {
|
|
12102
|
-
const seconds3 =
|
|
12147
|
+
const seconds3 = plan4.seconds(payload);
|
|
12103
12148
|
return {
|
|
12104
12149
|
model: ctx.model.id,
|
|
12105
12150
|
provider: "fal",
|
|
@@ -12107,7 +12152,7 @@ function planUsage(ctx, plan3) {
|
|
|
12107
12152
|
unit: "seconds",
|
|
12108
12153
|
quantity: seconds3,
|
|
12109
12154
|
durationSeconds: seconds3,
|
|
12110
|
-
...
|
|
12155
|
+
...plan4.resolution !== void 0 && { resolution: plan4.resolution }
|
|
12111
12156
|
};
|
|
12112
12157
|
};
|
|
12113
12158
|
}
|
|
@@ -14132,6 +14177,21 @@ function imageUsage2(ctx) {
|
|
|
14132
14177
|
};
|
|
14133
14178
|
}
|
|
14134
14179
|
var GENERATE_SECONDS = 5;
|
|
14180
|
+
var GENERATE_LENGTHS = [5, 10];
|
|
14181
|
+
function generateSeconds(req) {
|
|
14182
|
+
return req.durationSeconds ?? GENERATE_SECONDS;
|
|
14183
|
+
}
|
|
14184
|
+
function checkGenerateSeconds(req, ctx) {
|
|
14185
|
+
const seconds3 = generateSeconds(req);
|
|
14186
|
+
if (GENERATE_LENGTHS.includes(seconds3)) return;
|
|
14187
|
+
throw new ModelKitError({
|
|
14188
|
+
code: "unsupported_option",
|
|
14189
|
+
message: `${ctx.model.id} renders ${GENERATE_LENGTHS.join(" or ")} s clips, not ${seconds3} s`,
|
|
14190
|
+
provider: "luma",
|
|
14191
|
+
model: ctx.model.id,
|
|
14192
|
+
retryable: false
|
|
14193
|
+
});
|
|
14194
|
+
}
|
|
14135
14195
|
var MAX_PLAUSIBLE_SECONDS = 60;
|
|
14136
14196
|
function editedSeconds(req, bytes) {
|
|
14137
14197
|
const measured = mp4DurationSeconds(bytes);
|
|
@@ -14197,7 +14257,7 @@ function videoBody(req, ctx, mode) {
|
|
|
14197
14257
|
prompt,
|
|
14198
14258
|
video: {
|
|
14199
14259
|
...req.resolution !== void 0 && { resolution: req.resolution },
|
|
14200
|
-
duration:
|
|
14260
|
+
duration: `${generateSeconds(req)}s`,
|
|
14201
14261
|
...req.firstFrame !== void 0 && { start_frame: imageRef(req.firstFrame) },
|
|
14202
14262
|
...req.lastFrame !== void 0 && { end_frame: imageRef(req.lastFrame) }
|
|
14203
14263
|
}
|
|
@@ -14306,7 +14366,7 @@ function lumaVideoJob(ctx, req, mode, id) {
|
|
|
14306
14366
|
if (mode === "generate") {
|
|
14307
14367
|
const result2 = {
|
|
14308
14368
|
video: { url, expiresAt: new Date(Date.now() + OUTPUT_URL_TTL_MS) },
|
|
14309
|
-
usage: videoUsage4(jobCtx, req, mode,
|
|
14369
|
+
usage: videoUsage4(jobCtx, req, mode, generateSeconds(req)),
|
|
14310
14370
|
raw: { id }
|
|
14311
14371
|
};
|
|
14312
14372
|
return result2;
|
|
@@ -14334,6 +14394,7 @@ async function generateLumaVideo(req, ctx) {
|
|
|
14334
14394
|
});
|
|
14335
14395
|
}
|
|
14336
14396
|
const mode = lumaVideoMode(ctx);
|
|
14397
|
+
if (mode === "generate") checkGenerateSeconds(req, ctx);
|
|
14337
14398
|
const created = await submitGeneration(ctx, videoBody(req, ctx, mode));
|
|
14338
14399
|
return lumaVideoJob(ctx, req, mode, created.id);
|
|
14339
14400
|
}
|
|
@@ -16545,10 +16606,10 @@ function resolveVideoOptions(model, request, onUnsupported = "error") {
|
|
|
16545
16606
|
warnings
|
|
16546
16607
|
);
|
|
16547
16608
|
if (aspectRatio !== void 0) merged.aspectRatio = aspectRatio;
|
|
16548
|
-
|
|
16609
|
+
fillKlingModeResolution(model, merged);
|
|
16549
16610
|
const resolution = resolveVideoResolution(merged.resolution, model, onUnsupported, warnings);
|
|
16550
16611
|
if (resolution !== void 0) merged.resolution = resolution;
|
|
16551
|
-
if (
|
|
16612
|
+
if (takesKlingMode(model)) delete merged.mode;
|
|
16552
16613
|
const duration = resolveDuration(
|
|
16553
16614
|
merged.durationSeconds,
|
|
16554
16615
|
c.durations,
|