climage 0.4.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -6
- package/dist/cli.js +53 -11
- package/dist/cli.js.map +1 -1
- package/dist/index.js +53 -11
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -256,8 +256,7 @@ async function generateXaiVideo(req, apiKey) {
|
|
|
256
256
|
prompt: req.prompt,
|
|
257
257
|
model,
|
|
258
258
|
...req.aspectRatio ? { aspect_ratio: req.aspectRatio } : {},
|
|
259
|
-
|
|
260
|
-
...imageUrl ? { image_url: imageUrl } : {},
|
|
259
|
+
...imageUrl ? { image: { url: imageUrl } } : {},
|
|
261
260
|
// Add duration (xAI supports 1-15 seconds)
|
|
262
261
|
...req.duration !== void 0 ? { duration: req.duration } : {}
|
|
263
262
|
};
|
|
@@ -265,7 +264,7 @@ async function generateXaiVideo(req, apiKey) {
|
|
|
265
264
|
"Request body:",
|
|
266
265
|
JSON.stringify({
|
|
267
266
|
...createBody,
|
|
268
|
-
|
|
267
|
+
image: createBody.image ? { url: `...(${String(createBody.image.url).length} chars)` } : void 0
|
|
269
268
|
})
|
|
270
269
|
);
|
|
271
270
|
log("Calling xAI videos/generations...");
|
|
@@ -409,8 +408,15 @@ var DEFAULT_IMAGE_MODEL = "fal-ai/flux/dev";
|
|
|
409
408
|
var DEFAULT_IMAGE_TO_IMAGE_MODEL = "fal-ai/flux/dev/image-to-image";
|
|
410
409
|
var DEFAULT_VIDEO_MODEL = "fal-ai/ltxv-2/text-to-video/fast";
|
|
411
410
|
var DEFAULT_IMAGE_TO_VIDEO_MODEL = "fal-ai/vidu/q2/image-to-video";
|
|
411
|
+
var KLING_V3_PRO_IMAGE_TO_VIDEO_MODEL = "fal-ai/kling-video/v3/pro/image-to-video";
|
|
412
412
|
var DEFAULT_START_END_VIDEO_MODEL = "fal-ai/vidu/start-end-to-video";
|
|
413
413
|
var DEFAULT_REFERENCE_VIDEO_MODEL = "fal-ai/vidu/q2/reference-to-video";
|
|
414
|
+
function isKlingV3Model(model) {
|
|
415
|
+
return model === KLING_V3_PRO_IMAGE_TO_VIDEO_MODEL || model.startsWith("fal-ai/kling-video/v3/");
|
|
416
|
+
}
|
|
417
|
+
function isViduModel(model) {
|
|
418
|
+
return model.includes("/vidu/");
|
|
419
|
+
}
|
|
414
420
|
function selectVideoModel(req) {
|
|
415
421
|
if (req.model) return req.model;
|
|
416
422
|
if (req.startFrame && req.endFrame) {
|
|
@@ -429,9 +435,12 @@ function selectImageModel(req) {
|
|
|
429
435
|
if (req.inputImages?.length) return DEFAULT_IMAGE_TO_IMAGE_MODEL;
|
|
430
436
|
return DEFAULT_IMAGE_MODEL;
|
|
431
437
|
}
|
|
432
|
-
function mapAspectRatio(aspectRatio) {
|
|
438
|
+
function mapAspectRatio(aspectRatio, model) {
|
|
433
439
|
if (!aspectRatio) return void 0;
|
|
434
440
|
const ar = aspectRatio.trim();
|
|
441
|
+
if (model && isKlingV3Model(model)) {
|
|
442
|
+
return ar;
|
|
443
|
+
}
|
|
435
444
|
if (ar === "1:1") return "square";
|
|
436
445
|
if (ar === "4:3") return "landscape_4_3";
|
|
437
446
|
if (ar === "16:9") return "landscape_16_9";
|
|
@@ -439,29 +448,50 @@ function mapAspectRatio(aspectRatio) {
|
|
|
439
448
|
if (ar === "9:16") return "portrait_16_9";
|
|
440
449
|
return ar;
|
|
441
450
|
}
|
|
442
|
-
function buildVideoInput(req) {
|
|
451
|
+
function buildVideoInput(req, model) {
|
|
443
452
|
const input = {
|
|
444
453
|
prompt: req.prompt
|
|
445
454
|
};
|
|
446
455
|
if (req.startFrame && req.endFrame) {
|
|
447
456
|
input.start_image_url = req.startFrame;
|
|
448
457
|
input.end_image_url = req.endFrame;
|
|
458
|
+
const ar = mapAspectRatio(req.aspectRatio, model);
|
|
459
|
+
if (ar) input.aspect_ratio = ar;
|
|
460
|
+
if (req.duration) input.duration = String(req.duration);
|
|
449
461
|
return input;
|
|
450
462
|
}
|
|
451
463
|
if (req.inputImages?.length && !req.startFrame) {
|
|
464
|
+
if (isKlingV3Model(model)) {
|
|
465
|
+
input.start_image_url = req.inputImages[0];
|
|
466
|
+
const ar2 = mapAspectRatio(req.aspectRatio, model);
|
|
467
|
+
if (ar2) input.aspect_ratio = ar2;
|
|
468
|
+
if (req.duration) input.duration = String(req.duration);
|
|
469
|
+
return input;
|
|
470
|
+
}
|
|
452
471
|
input.reference_image_urls = req.inputImages.slice(0, 7);
|
|
453
|
-
const ar = mapAspectRatio(req.aspectRatio);
|
|
472
|
+
const ar = mapAspectRatio(req.aspectRatio, model);
|
|
454
473
|
if (ar) input.aspect_ratio = ar;
|
|
455
474
|
if (req.duration) input.duration = String(req.duration);
|
|
456
475
|
return input;
|
|
457
476
|
}
|
|
458
477
|
const imageUrl = req.startFrame ?? req.inputImages?.[0];
|
|
459
478
|
if (imageUrl) {
|
|
460
|
-
|
|
479
|
+
if (isKlingV3Model(model)) {
|
|
480
|
+
input.start_image_url = imageUrl;
|
|
481
|
+
const ar = mapAspectRatio(req.aspectRatio, model);
|
|
482
|
+
if (ar) input.aspect_ratio = ar;
|
|
483
|
+
} else {
|
|
484
|
+
input.image_url = imageUrl;
|
|
485
|
+
}
|
|
461
486
|
if (req.duration) input.duration = String(req.duration);
|
|
462
487
|
return input;
|
|
463
488
|
}
|
|
464
|
-
|
|
489
|
+
if (isKlingV3Model(model)) {
|
|
490
|
+
throw new Error(
|
|
491
|
+
`Model ${model} requires --start-frame (or --input) because it is image-to-video only`
|
|
492
|
+
);
|
|
493
|
+
}
|
|
494
|
+
const imageSize = mapAspectRatio(req.aspectRatio, model);
|
|
465
495
|
if (imageSize) input.image_size = imageSize;
|
|
466
496
|
if (req.n) input.num_videos = req.n;
|
|
467
497
|
return input;
|
|
@@ -486,8 +516,8 @@ var falCapabilities = {
|
|
|
486
516
|
supportsCustomAspectRatio: true,
|
|
487
517
|
supportsVideoInterpolation: true,
|
|
488
518
|
// Vidu start-end-to-video
|
|
489
|
-
videoDurationRange: [2,
|
|
490
|
-
//
|
|
519
|
+
videoDurationRange: [2, 15],
|
|
520
|
+
// Most models are 2-8; Kling v3 supports up to 15
|
|
491
521
|
supportsImageEditing: true
|
|
492
522
|
};
|
|
493
523
|
var falProvider = {
|
|
@@ -515,7 +545,19 @@ var falProvider = {
|
|
|
515
545
|
fal.config({ credentials: key });
|
|
516
546
|
const model = req.kind === "video" ? selectVideoModel(req) : selectImageModel(req);
|
|
517
547
|
log2(verbose, "Selected model:", model);
|
|
518
|
-
|
|
548
|
+
if (req.kind === "video" && req.duration !== void 0) {
|
|
549
|
+
if (isKlingV3Model(model) && (req.duration < 3 || req.duration > 15)) {
|
|
550
|
+
throw new Error(
|
|
551
|
+
`Model ${model} supports video duration 3-15s, but ${req.duration}s requested`
|
|
552
|
+
);
|
|
553
|
+
}
|
|
554
|
+
if (isViduModel(model) && (req.duration < 2 || req.duration > 8)) {
|
|
555
|
+
throw new Error(
|
|
556
|
+
`Model ${model} supports video duration 2-8s, but ${req.duration}s requested`
|
|
557
|
+
);
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
const input = req.kind === "video" ? buildVideoInput(req, model) : buildImageInput(req);
|
|
519
561
|
const inputSummary = { ...input };
|
|
520
562
|
for (const key2 of ["image_url", "start_image_url", "end_image_url"]) {
|
|
521
563
|
if (typeof inputSummary[key2] === "string" && inputSummary[key2].startsWith("data:")) {
|