@vibeframe/cli 0.104.3 → 0.105.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/dist/index.js +250 -34
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -17106,6 +17106,53 @@ function pickReferenceImageUrl(input) {
|
|
|
17106
17106
|
return input;
|
|
17107
17107
|
return void 0;
|
|
17108
17108
|
}
|
|
17109
|
+
function isFalFileInput(value) {
|
|
17110
|
+
return value.startsWith("http://") || value.startsWith("https://") || value.startsWith("data:");
|
|
17111
|
+
}
|
|
17112
|
+
async function normaliseReferences(input, client) {
|
|
17113
|
+
if (!input)
|
|
17114
|
+
return [];
|
|
17115
|
+
const references = [];
|
|
17116
|
+
for (const ref of input) {
|
|
17117
|
+
if (!isFalFileInput(ref.url))
|
|
17118
|
+
continue;
|
|
17119
|
+
references.push({
|
|
17120
|
+
...ref,
|
|
17121
|
+
url: ref.url.startsWith("data:") ? await uploadDataUri(client, ref.url) : ref.url
|
|
17122
|
+
});
|
|
17123
|
+
}
|
|
17124
|
+
return references;
|
|
17125
|
+
}
|
|
17126
|
+
async function uploadDataUri(client, dataUri) {
|
|
17127
|
+
const blob = dataUriToBlob(dataUri);
|
|
17128
|
+
return client.storage.upload(blob, {
|
|
17129
|
+
lifecycle: { expiresIn: "1h" }
|
|
17130
|
+
});
|
|
17131
|
+
}
|
|
17132
|
+
function dataUriToBlob(dataUri) {
|
|
17133
|
+
const match = /^data:([^;,]+)?(;base64)?,(.*)$/s.exec(dataUri);
|
|
17134
|
+
if (!match)
|
|
17135
|
+
throw new Error("Invalid data URI reference.");
|
|
17136
|
+
const mimeType = match[1] || "application/octet-stream";
|
|
17137
|
+
const isBase64 = Boolean(match[2]);
|
|
17138
|
+
const payload = match[3] ?? "";
|
|
17139
|
+
const buffer = isBase64 ? Buffer.from(payload, "base64") : Buffer.from(decodeURIComponent(payload), "utf-8");
|
|
17140
|
+
return new Blob([new Uint8Array(buffer)], { type: mimeType });
|
|
17141
|
+
}
|
|
17142
|
+
function groupReferences(references) {
|
|
17143
|
+
const image_urls = [];
|
|
17144
|
+
const video_urls = [];
|
|
17145
|
+
const audio_urls = [];
|
|
17146
|
+
for (const ref of references) {
|
|
17147
|
+
if (ref.kind === "image")
|
|
17148
|
+
image_urls.push(ref.url);
|
|
17149
|
+
if (ref.kind === "video")
|
|
17150
|
+
video_urls.push(ref.url);
|
|
17151
|
+
if (ref.kind === "audio")
|
|
17152
|
+
audio_urls.push(ref.url);
|
|
17153
|
+
}
|
|
17154
|
+
return { image_urls, video_urls, audio_urls };
|
|
17155
|
+
}
|
|
17109
17156
|
function normaliseAspect(value) {
|
|
17110
17157
|
if (!value)
|
|
17111
17158
|
return "auto";
|
|
@@ -17128,7 +17175,7 @@ function normaliseDuration(value) {
|
|
|
17128
17175
|
return "auto";
|
|
17129
17176
|
return Math.max(4, Math.min(15, Math.round(value)));
|
|
17130
17177
|
}
|
|
17131
|
-
var import_client, ENDPOINT_TEXT_TO_VIDEO, ENDPOINT_IMAGE_TO_VIDEO, DEFAULT_VARIANT, VALID_RESOLUTIONS, VALID_ASPECTS, FalProvider, falProvider;
|
|
17178
|
+
var import_client, ENDPOINT_TEXT_TO_VIDEO, ENDPOINT_IMAGE_TO_VIDEO, ENDPOINT_REFERENCE_TO_VIDEO, DEFAULT_VARIANT, VALID_RESOLUTIONS, VALID_ASPECTS, FalProvider, falProvider;
|
|
17132
17179
|
var init_FalProvider = __esm({
|
|
17133
17180
|
"../ai-providers/dist/fal/FalProvider.js"() {
|
|
17134
17181
|
"use strict";
|
|
@@ -17141,6 +17188,10 @@ var init_FalProvider = __esm({
|
|
|
17141
17188
|
"seedance-2.0": "bytedance/seedance-2.0/image-to-video",
|
|
17142
17189
|
"seedance-2.0-fast": "bytedance/seedance-2.0/fast/image-to-video"
|
|
17143
17190
|
};
|
|
17191
|
+
ENDPOINT_REFERENCE_TO_VIDEO = {
|
|
17192
|
+
"seedance-2.0": "bytedance/seedance-2.0/reference-to-video",
|
|
17193
|
+
"seedance-2.0-fast": "bytedance/seedance-2.0/fast/reference-to-video"
|
|
17194
|
+
};
|
|
17144
17195
|
DEFAULT_VARIANT = "seedance-2.0";
|
|
17145
17196
|
VALID_RESOLUTIONS = ["480p", "720p", "1080p"];
|
|
17146
17197
|
VALID_ASPECTS = ["21:9", "16:9", "4:3", "1:1", "3:4", "9:16", "auto"];
|
|
@@ -17149,7 +17200,7 @@ var init_FalProvider = __esm({
|
|
|
17149
17200
|
this.id = "seedance";
|
|
17150
17201
|
this.name = "fal.ai (Seedance 2.0)";
|
|
17151
17202
|
this.description = "fal.ai hosting ByteDance Seedance 2.0 \u2014 Artificial Analysis #2 on both text-to-video and image-to-video leaderboards";
|
|
17152
|
-
this.capabilities = ["text-to-video", "image-to-video"];
|
|
17203
|
+
this.capabilities = ["text-to-video", "image-to-video", "reference-to-video"];
|
|
17153
17204
|
this.iconUrl = "/icons/fal.svg";
|
|
17154
17205
|
this.isAvailable = true;
|
|
17155
17206
|
}
|
|
@@ -17188,9 +17239,11 @@ var init_FalProvider = __esm({
|
|
|
17188
17239
|
error: `Unknown Seedance variant: ${variant}. Valid: ${Object.keys(ENDPOINT_TEXT_TO_VIDEO).join(", ")}.`
|
|
17189
17240
|
};
|
|
17190
17241
|
}
|
|
17191
|
-
const
|
|
17242
|
+
const references = await normaliseReferences(options?.references, this.client);
|
|
17243
|
+
const hasReferences = references.length > 0;
|
|
17244
|
+
const referenceImage = hasReferences ? void 0 : pickReferenceImageUrl(options?.referenceImage);
|
|
17192
17245
|
const isImageToVideo = !!referenceImage;
|
|
17193
|
-
const endpointId = isImageToVideo ? ENDPOINT_IMAGE_TO_VIDEO[variant] : ENDPOINT_TEXT_TO_VIDEO[variant];
|
|
17246
|
+
const endpointId = hasReferences ? ENDPOINT_REFERENCE_TO_VIDEO[variant] : isImageToVideo ? ENDPOINT_IMAGE_TO_VIDEO[variant] : ENDPOINT_TEXT_TO_VIDEO[variant];
|
|
17194
17247
|
const aspect = normaliseAspect(options?.aspectRatio);
|
|
17195
17248
|
const resolution = normaliseResolution(options?.resolution);
|
|
17196
17249
|
const duration = normaliseDuration(options?.duration);
|
|
@@ -17200,13 +17253,26 @@ var init_FalProvider = __esm({
|
|
|
17200
17253
|
resolution,
|
|
17201
17254
|
duration
|
|
17202
17255
|
};
|
|
17203
|
-
if (
|
|
17256
|
+
if (hasReferences) {
|
|
17257
|
+
const grouped = groupReferences(references);
|
|
17258
|
+
if (grouped.image_urls.length > 0)
|
|
17259
|
+
input.image_urls = grouped.image_urls;
|
|
17260
|
+
if (grouped.video_urls.length > 0)
|
|
17261
|
+
input.video_urls = grouped.video_urls;
|
|
17262
|
+
if (grouped.audio_urls.length > 0)
|
|
17263
|
+
input.audio_urls = grouped.audio_urls;
|
|
17264
|
+
} else if (referenceImage) {
|
|
17204
17265
|
input.image_url = referenceImage;
|
|
17266
|
+
}
|
|
17205
17267
|
if (options?.negativePrompt)
|
|
17206
17268
|
input.negative_prompt = options.negativePrompt;
|
|
17207
17269
|
if (typeof options?.seed === "number")
|
|
17208
17270
|
input.seed = options.seed;
|
|
17209
|
-
if (options?.
|
|
17271
|
+
if (typeof options?.generateAudio === "boolean")
|
|
17272
|
+
input.generate_audio = options.generateAudio;
|
|
17273
|
+
if (options?.endUserId)
|
|
17274
|
+
input.end_user_id = options.endUserId;
|
|
17275
|
+
if (!hasReferences && options?.lastFrame)
|
|
17210
17276
|
input.end_image_url = options.lastFrame;
|
|
17211
17277
|
try {
|
|
17212
17278
|
const out = await this.client.subscribe(endpointId, { input, logs: false });
|
|
@@ -17253,14 +17319,15 @@ var init_fal = __esm({
|
|
|
17253
17319
|
// Review this alias at the 1.0 cut.
|
|
17254
17320
|
aliases: ["fal"],
|
|
17255
17321
|
models: ["seedance-2.0", "seedance-2.0-fast"],
|
|
17256
|
-
capabilities: ["text-to-video", "image-to-video", "native-audio"],
|
|
17322
|
+
capabilities: ["text-to-video", "image-to-video", "reference-to-video", "native-audio"],
|
|
17257
17323
|
apiKey: "fal",
|
|
17258
17324
|
kinds: ["video"],
|
|
17259
17325
|
resolverPriority: { video: 1 },
|
|
17260
17326
|
commandsUnlocked: [
|
|
17261
17327
|
"generate video -p seedance (Seedance 2.0 via fal.ai \u2014 default since v0.57)",
|
|
17262
17328
|
"generate video -p seedance --seedance-model fast (lower-latency variant)",
|
|
17263
|
-
"generate video -p seedance -i <image> (image-to-video)"
|
|
17329
|
+
"generate video -p seedance -i <image> (image-to-video)",
|
|
17330
|
+
"generate video -p seedance --ref-images <images...> (reference-to-video)"
|
|
17264
17331
|
]
|
|
17265
17332
|
});
|
|
17266
17333
|
}
|
|
@@ -26553,6 +26620,33 @@ consult this file \u2014 run the generate command directly.
|
|
|
26553
26620
|
Browse named styles: \`vibe scene list-styles\`. Re-seed from one with
|
|
26554
26621
|
\`vibe scene init . --visual-style "Swiss Pulse"\` (idempotent).
|
|
26555
26622
|
|
|
26623
|
+
## Brief and local media
|
|
26624
|
+
|
|
26625
|
+
\`brief.md\` is raw intent, not a strict schema. It may contain messy notes,
|
|
26626
|
+
pasted research, links, product requirements, or a one-line idea. \`vibe init
|
|
26627
|
+
--from brief.md\` uses it only to seed \`STORYBOARD.md\` and \`DESIGN.md\`;
|
|
26628
|
+
after init, those two files are the working source of truth.
|
|
26629
|
+
|
|
26630
|
+
Use \`media/\` for user-provided source files: product photos, screenshots,
|
|
26631
|
+
logos, B-roll, recorded narration, or reference clips. Keep those inputs
|
|
26632
|
+
inside this project so build references stay project-relative. Do not put user
|
|
26633
|
+
media in \`references/\`; that directory is reserved for local composition
|
|
26634
|
+
rules installed by VibeFrame.
|
|
26635
|
+
|
|
26636
|
+
When a beat should reuse a local file, reference it from \`STORYBOARD.md\`
|
|
26637
|
+
with a project-relative path:
|
|
26638
|
+
|
|
26639
|
+
\`\`\`yaml
|
|
26640
|
+
backdrop: "media/product-shot.png" # existing still image
|
|
26641
|
+
video: "media/broll.mp4" # existing video/B-roll
|
|
26642
|
+
narration: "media/voice.wav" # existing recorded narration
|
|
26643
|
+
asset: "media/logo.png" # generic local asset reference
|
|
26644
|
+
\`\`\`
|
|
26645
|
+
|
|
26646
|
+
Use text cues when you want VibeFrame to generate an asset. Use path cues
|
|
26647
|
+
when you want VibeFrame to reuse a local file. Avoid absolute paths or parent
|
|
26648
|
+
directory references; copy files into \`media/\` first.
|
|
26649
|
+
|
|
26556
26650
|
## Provider keys and project scope
|
|
26557
26651
|
|
|
26558
26652
|
Use VibeFrame CLI generation for project assets:
|
|
@@ -26600,9 +26694,11 @@ the framework-level minimum, not the cinematic craft layer.
|
|
|
26600
26694
|
|
|
26601
26695
|
- \`DESIGN.md\` \u2014 visual identity contract (palette, type, motion, transitions)
|
|
26602
26696
|
- \`STORYBOARD.md\` \u2014 per-beat narration/backdrop/duration cues for \`vibe build\`
|
|
26697
|
+
- \`media/\` \u2014 user-provided source files (photos, logos, clips, voice recordings)
|
|
26603
26698
|
- \`index.html\` \u2014 root composition (timeline)
|
|
26604
26699
|
- \`compositions/scene-*.html\` \u2014 per-scene HTML authored by you or the agent
|
|
26605
|
-
- \`assets/\` \u2014
|
|
26700
|
+
- \`assets/\` \u2014 generated/canonical build media (narration audio, images, video)
|
|
26701
|
+
- \`references/\` \u2014 composition rule docs installed by VibeFrame, not user media
|
|
26606
26702
|
- \`transcript.json\` \u2014 Whisper word-level transcript (if narration exists)
|
|
26607
26703
|
- \`hyperframes.json\` \u2014 HF registry config (speak to both toolchains)
|
|
26608
26704
|
- \`vibe.config.json\` \u2014 canonical VibeFrame config (providers, budget)
|
|
@@ -26750,7 +26846,11 @@ async function scaffoldSceneProject(opts) {
|
|
|
26750
26846
|
if (await pathExists(metaPath)) {
|
|
26751
26847
|
skipped2.push(metaPath);
|
|
26752
26848
|
} else {
|
|
26753
|
-
await writeFile4(
|
|
26849
|
+
await writeFile4(
|
|
26850
|
+
metaPath,
|
|
26851
|
+
JSON.stringify(buildHyperframesMeta(name, now), null, 2) + "\n",
|
|
26852
|
+
"utf-8"
|
|
26853
|
+
);
|
|
26754
26854
|
created.push(metaPath);
|
|
26755
26855
|
}
|
|
26756
26856
|
const rootPath = resolve7(dir, "index.html");
|
|
@@ -26765,11 +26865,7 @@ async function scaffoldSceneProject(opts) {
|
|
|
26765
26865
|
if (await pathExists(vibeConfigJsonPath)) {
|
|
26766
26866
|
skipped2.push(vibeConfigJsonPath);
|
|
26767
26867
|
} else {
|
|
26768
|
-
await writeFile4(
|
|
26769
|
-
vibeConfigJsonPath,
|
|
26770
|
-
projectConfigJson({ name, aspect }),
|
|
26771
|
-
"utf-8"
|
|
26772
|
-
);
|
|
26868
|
+
await writeFile4(vibeConfigJsonPath, projectConfigJson({ name, aspect }), "utf-8");
|
|
26773
26869
|
created.push(vibeConfigJsonPath);
|
|
26774
26870
|
}
|
|
26775
26871
|
const vibePath = resolve7(dir, "vibe.project.yaml");
|
|
@@ -26808,11 +26904,7 @@ ${existing}`, "utf-8");
|
|
|
26808
26904
|
if (await pathExists(designPath)) {
|
|
26809
26905
|
skipped2.push(designPath);
|
|
26810
26906
|
} else {
|
|
26811
|
-
await writeFile4(
|
|
26812
|
-
designPath,
|
|
26813
|
-
buildDesignMd({ name, style: opts.visualStyle }),
|
|
26814
|
-
"utf-8"
|
|
26815
|
-
);
|
|
26907
|
+
await writeFile4(designPath, buildDesignMd({ name, style: opts.visualStyle }), "utf-8");
|
|
26816
26908
|
created.push(designPath);
|
|
26817
26909
|
}
|
|
26818
26910
|
const storyboardPath2 = resolve7(dir, "STORYBOARD.md");
|
|
@@ -33820,6 +33912,9 @@ async function executeVideoGenerate(options) {
|
|
|
33820
33912
|
prompt: prompt3,
|
|
33821
33913
|
provider = "kling",
|
|
33822
33914
|
image,
|
|
33915
|
+
refImages,
|
|
33916
|
+
refVideos,
|
|
33917
|
+
refAudio,
|
|
33823
33918
|
duration = 5,
|
|
33824
33919
|
ratio = "16:9",
|
|
33825
33920
|
seed,
|
|
@@ -33828,6 +33923,7 @@ async function executeVideoGenerate(options) {
|
|
|
33828
33923
|
resolution,
|
|
33829
33924
|
veoModel = "3.1-fast",
|
|
33830
33925
|
seedanceModel = "quality",
|
|
33926
|
+
generateAudio,
|
|
33831
33927
|
output,
|
|
33832
33928
|
wait = true,
|
|
33833
33929
|
apiKey
|
|
@@ -33866,8 +33962,13 @@ async function executeVideoGenerate(options) {
|
|
|
33866
33962
|
if (provider === "seedance" || provider === "fal") {
|
|
33867
33963
|
const fal = new FalProvider();
|
|
33868
33964
|
await fal.initialize({ apiKey: key });
|
|
33965
|
+
const references = await prepareSeedanceReferences({
|
|
33966
|
+
refImages,
|
|
33967
|
+
refVideos,
|
|
33968
|
+
refAudio
|
|
33969
|
+
});
|
|
33869
33970
|
let falImage = referenceImage;
|
|
33870
|
-
if (falImage && falImage.startsWith("data:")) {
|
|
33971
|
+
if (falImage && falImage.startsWith("data:") && references.length === 0) {
|
|
33871
33972
|
const uploadHost = await resolveUploadHost();
|
|
33872
33973
|
const upload = await uploadHost.uploadImage(referenceImageBuffer, {
|
|
33873
33974
|
filename: image,
|
|
@@ -33878,11 +33979,14 @@ async function executeVideoGenerate(options) {
|
|
|
33878
33979
|
const model = seedanceModel === "fast" || seedanceModel === "seedance-2.0-fast" ? "seedance-2.0-fast" : "seedance-2.0";
|
|
33879
33980
|
const result = await fal.generateVideo(prompt3, {
|
|
33880
33981
|
prompt: prompt3,
|
|
33881
|
-
referenceImage: falImage,
|
|
33982
|
+
referenceImage: references.length > 0 ? void 0 : falImage,
|
|
33983
|
+
references: references.length > 0 ? references : void 0,
|
|
33882
33984
|
duration,
|
|
33883
33985
|
aspectRatio: ratio,
|
|
33884
33986
|
negativePrompt: negative,
|
|
33885
|
-
model
|
|
33987
|
+
model,
|
|
33988
|
+
resolution,
|
|
33989
|
+
generateAudio
|
|
33886
33990
|
});
|
|
33887
33991
|
if (result.status === "failed")
|
|
33888
33992
|
return { success: false, error: result.error || "Seedance generation failed" };
|
|
@@ -34059,6 +34163,54 @@ async function executeVideoGenerate(options) {
|
|
|
34059
34163
|
};
|
|
34060
34164
|
}
|
|
34061
34165
|
}
|
|
34166
|
+
async function prepareSeedanceReferences(opts) {
|
|
34167
|
+
const references = [];
|
|
34168
|
+
for (const sourcePath of opts.refImages ?? []) {
|
|
34169
|
+
references.push({
|
|
34170
|
+
kind: "image",
|
|
34171
|
+
url: await fileInputToUrlOrDataUri(sourcePath, "image/png"),
|
|
34172
|
+
sourcePath
|
|
34173
|
+
});
|
|
34174
|
+
}
|
|
34175
|
+
for (const sourcePath of opts.refVideos ?? []) {
|
|
34176
|
+
references.push({
|
|
34177
|
+
kind: "video",
|
|
34178
|
+
url: await fileInputToUrlOrDataUri(sourcePath, "video/mp4"),
|
|
34179
|
+
sourcePath
|
|
34180
|
+
});
|
|
34181
|
+
}
|
|
34182
|
+
for (const sourcePath of opts.refAudio ?? []) {
|
|
34183
|
+
references.push({
|
|
34184
|
+
kind: "audio",
|
|
34185
|
+
url: await fileInputToUrlOrDataUri(sourcePath, "audio/mpeg"),
|
|
34186
|
+
sourcePath
|
|
34187
|
+
});
|
|
34188
|
+
}
|
|
34189
|
+
return references;
|
|
34190
|
+
}
|
|
34191
|
+
async function fileInputToUrlOrDataUri(input, fallbackMimeType) {
|
|
34192
|
+
if (input.startsWith("http://") || input.startsWith("https://") || input.startsWith("data:")) {
|
|
34193
|
+
return input;
|
|
34194
|
+
}
|
|
34195
|
+
const absPath = resolve23(process.cwd(), input);
|
|
34196
|
+
const buffer = await readFile15(absPath);
|
|
34197
|
+
return `data:${mimeTypeForPath(input, fallbackMimeType)};base64,${buffer.toString("base64")}`;
|
|
34198
|
+
}
|
|
34199
|
+
function mimeTypeForPath(path2, fallback2) {
|
|
34200
|
+
const ext = path2.toLowerCase().split(".").pop();
|
|
34201
|
+
const mimeTypes2 = {
|
|
34202
|
+
jpg: "image/jpeg",
|
|
34203
|
+
jpeg: "image/jpeg",
|
|
34204
|
+
png: "image/png",
|
|
34205
|
+
gif: "image/gif",
|
|
34206
|
+
webp: "image/webp",
|
|
34207
|
+
mp4: "video/mp4",
|
|
34208
|
+
mov: "video/quicktime",
|
|
34209
|
+
mp3: "audio/mpeg",
|
|
34210
|
+
wav: "audio/wav"
|
|
34211
|
+
};
|
|
34212
|
+
return mimeTypes2[ext || ""] || fallback2;
|
|
34213
|
+
}
|
|
34062
34214
|
async function executeVideoStatus(options) {
|
|
34063
34215
|
const {
|
|
34064
34216
|
taskId,
|
|
@@ -36312,10 +36464,10 @@ var init_provider_resolver = __esm({
|
|
|
36312
36464
|
|
|
36313
36465
|
// src/commands/_shared/openai-image.ts
|
|
36314
36466
|
function resolveOpenAIImageModel(modelAlias) {
|
|
36315
|
-
const
|
|
36467
|
+
const isGptImage15 = modelAlias === "1.5" || modelAlias === "gpt-image-1.5";
|
|
36316
36468
|
return {
|
|
36317
|
-
openaiModel:
|
|
36318
|
-
modelLabel:
|
|
36469
|
+
openaiModel: isGptImage15 ? "gpt-image-1.5" : "gpt-image-2",
|
|
36470
|
+
modelLabel: isGptImage15 ? "GPT Image 1.5" : "GPT Image 2"
|
|
36319
36471
|
};
|
|
36320
36472
|
}
|
|
36321
36473
|
async function executeOpenAIImageGenerate(prompt3, options, ctx) {
|
|
@@ -36352,7 +36504,7 @@ function registerImageCommand(parent) {
|
|
|
36352
36504
|
"1:1"
|
|
36353
36505
|
).option("--quality <quality>", "Quality: standard, hd (openai only)", "standard").option("--style <style>", "Style: vivid, natural (openai only)", "vivid").option("--count <n>", "Number of images to generate", "1").option(
|
|
36354
36506
|
"-m, --model <model>",
|
|
36355
|
-
"Model. Gemini: flash, 3.1-flash, latest, pro. OpenAI:
|
|
36507
|
+
"Model. Gemini: flash, 3.1-flash, latest, pro. OpenAI: 2 (default), 1.5"
|
|
36356
36508
|
).option("--dry-run", "Preview parameters without executing").addHelpText(
|
|
36357
36509
|
"after",
|
|
36358
36510
|
`
|
|
@@ -37786,8 +37938,8 @@ function registerVideoCommand(parent) {
|
|
|
37786
37938
|
"quality"
|
|
37787
37939
|
).option("--negative <prompt>", "Negative prompt - what to avoid (Kling/Veo)").option("--resolution <res>", "Video resolution: 720p, 1080p, 4k (Veo only)").option("--last-frame <path>", "Last frame image for frame interpolation (Veo only)").option(
|
|
37788
37940
|
"--ref-images <paths...>",
|
|
37789
|
-
"Reference images for
|
|
37790
|
-
).option("--person <mode>", "Person generation: allow_all, allow_adult (Veo only)").option("--veo-model <model>", "Veo model: 3.0, 3.1, 3.1-fast (default: 3.1-fast)", "3.1-fast").option(
|
|
37941
|
+
"Reference images for Seedance reference-to-video or Veo character consistency"
|
|
37942
|
+
).option("--ref-videos <paths...>", "Reference videos for Seedance reference-to-video").option("--ref-audio <paths...>", "Reference audio for Seedance reference-to-video").option("--no-generate-audio", "Disable native audio when the provider supports it").option("--person <mode>", "Person generation: allow_all, allow_adult (Veo only)").option("--veo-model <model>", "Veo model: 3.0, 3.1, 3.1-fast (default: 3.1-fast)", "3.1-fast").option(
|
|
37791
37943
|
"--runway-model <model>",
|
|
37792
37944
|
"Runway model: gen4.5 (default, text+image-to-video), gen4_turbo (image-to-video only)",
|
|
37793
37945
|
"gen4.5"
|
|
@@ -37930,7 +38082,11 @@ Examples:
|
|
|
37930
38082
|
negative: options.negative,
|
|
37931
38083
|
resolution: options.resolution,
|
|
37932
38084
|
veoModel: options.veoModel,
|
|
37933
|
-
seedanceModel: options.seedanceModel
|
|
38085
|
+
seedanceModel: options.seedanceModel,
|
|
38086
|
+
refImages: options.refImages,
|
|
38087
|
+
refVideos: options.refVideos,
|
|
38088
|
+
refAudio: options.refAudio,
|
|
38089
|
+
generateAudio: options.generateAudio
|
|
37934
38090
|
}
|
|
37935
38091
|
}
|
|
37936
38092
|
});
|
|
@@ -38217,8 +38373,13 @@ Examples:
|
|
|
38217
38373
|
} else if (provider === "seedance") {
|
|
38218
38374
|
const fal = new FalProvider();
|
|
38219
38375
|
await fal.initialize({ apiKey });
|
|
38376
|
+
const seedanceReferences = await prepareSeedanceReferences2({
|
|
38377
|
+
refImages: options.refImages,
|
|
38378
|
+
refVideos: options.refVideos,
|
|
38379
|
+
refAudio: options.refAudio
|
|
38380
|
+
});
|
|
38220
38381
|
let falImage = referenceImage;
|
|
38221
|
-
if (falImage && falImage.startsWith("data:")) {
|
|
38382
|
+
if (falImage && falImage.startsWith("data:") && seedanceReferences.length === 0) {
|
|
38222
38383
|
try {
|
|
38223
38384
|
const uploadHost = await resolveUploadHost();
|
|
38224
38385
|
spinner2.text = `Uploading image via ${uploadHost.provider} for Seedance...`;
|
|
@@ -38241,11 +38402,14 @@ Examples:
|
|
|
38241
38402
|
const falModel = seedanceModel === "fast" || seedanceModel === "seedance-2.0-fast" ? "seedance-2.0-fast" : "seedance-2.0";
|
|
38242
38403
|
result = await fal.generateVideo(prompt3, {
|
|
38243
38404
|
prompt: prompt3,
|
|
38244
|
-
referenceImage: falImage,
|
|
38405
|
+
referenceImage: seedanceReferences.length > 0 ? void 0 : falImage,
|
|
38406
|
+
references: seedanceReferences.length > 0 ? seedanceReferences : void 0,
|
|
38245
38407
|
duration: options.duration ? parseInt(options.duration) : void 0,
|
|
38246
38408
|
aspectRatio: options.ratio,
|
|
38247
38409
|
negativePrompt: options.negative,
|
|
38248
|
-
model: falModel
|
|
38410
|
+
model: falModel,
|
|
38411
|
+
resolution: options.resolution,
|
|
38412
|
+
generateAudio: options.generateAudio
|
|
38249
38413
|
});
|
|
38250
38414
|
finalResult = result;
|
|
38251
38415
|
}
|
|
@@ -38300,6 +38464,54 @@ Examples:
|
|
|
38300
38464
|
}
|
|
38301
38465
|
});
|
|
38302
38466
|
}
|
|
38467
|
+
async function prepareSeedanceReferences2(opts) {
|
|
38468
|
+
const references = [];
|
|
38469
|
+
for (const sourcePath of opts.refImages ?? []) {
|
|
38470
|
+
references.push({
|
|
38471
|
+
kind: "image",
|
|
38472
|
+
url: await fileInputToUrlOrDataUri2(sourcePath, "image/png"),
|
|
38473
|
+
sourcePath
|
|
38474
|
+
});
|
|
38475
|
+
}
|
|
38476
|
+
for (const sourcePath of opts.refVideos ?? []) {
|
|
38477
|
+
references.push({
|
|
38478
|
+
kind: "video",
|
|
38479
|
+
url: await fileInputToUrlOrDataUri2(sourcePath, "video/mp4"),
|
|
38480
|
+
sourcePath
|
|
38481
|
+
});
|
|
38482
|
+
}
|
|
38483
|
+
for (const sourcePath of opts.refAudio ?? []) {
|
|
38484
|
+
references.push({
|
|
38485
|
+
kind: "audio",
|
|
38486
|
+
url: await fileInputToUrlOrDataUri2(sourcePath, "audio/mpeg"),
|
|
38487
|
+
sourcePath
|
|
38488
|
+
});
|
|
38489
|
+
}
|
|
38490
|
+
return references;
|
|
38491
|
+
}
|
|
38492
|
+
async function fileInputToUrlOrDataUri2(input, fallbackMimeType) {
|
|
38493
|
+
if (input.startsWith("http://") || input.startsWith("https://") || input.startsWith("data:")) {
|
|
38494
|
+
return input;
|
|
38495
|
+
}
|
|
38496
|
+
const absPath = resolve31(process.cwd(), input);
|
|
38497
|
+
const buffer = await readFile18(absPath);
|
|
38498
|
+
return `data:${mimeTypeForPath2(input, fallbackMimeType)};base64,${buffer.toString("base64")}`;
|
|
38499
|
+
}
|
|
38500
|
+
function mimeTypeForPath2(path2, fallback2) {
|
|
38501
|
+
const ext = path2.toLowerCase().split(".").pop();
|
|
38502
|
+
const mimeTypes2 = {
|
|
38503
|
+
jpg: "image/jpeg",
|
|
38504
|
+
jpeg: "image/jpeg",
|
|
38505
|
+
png: "image/png",
|
|
38506
|
+
gif: "image/gif",
|
|
38507
|
+
webp: "image/webp",
|
|
38508
|
+
mp4: "video/mp4",
|
|
38509
|
+
mov: "video/quicktime",
|
|
38510
|
+
mp3: "audio/mpeg",
|
|
38511
|
+
wav: "audio/wav"
|
|
38512
|
+
};
|
|
38513
|
+
return mimeTypes2[ext || ""] || fallback2;
|
|
38514
|
+
}
|
|
38303
38515
|
async function recordVideoNoWaitJob(opts) {
|
|
38304
38516
|
return createAndWriteJobRecord({
|
|
38305
38517
|
jobType: "generate-video",
|
|
@@ -68197,6 +68409,9 @@ var init_generate2 = __esm({
|
|
|
68197
68409
|
"Video provider (default: seedance when FAL_API_KEY is configured, otherwise first configured provider)"
|
|
68198
68410
|
),
|
|
68199
68411
|
image: external_exports.string().optional().describe("Reference image path for image-to-video"),
|
|
68412
|
+
refImages: external_exports.array(external_exports.string()).optional().describe("Reference images for Seedance reference-to-video"),
|
|
68413
|
+
refVideos: external_exports.array(external_exports.string()).optional().describe("Reference videos for Seedance reference-to-video"),
|
|
68414
|
+
refAudio: external_exports.array(external_exports.string()).optional().describe("Reference audio files for Seedance reference-to-video"),
|
|
68200
68415
|
duration: external_exports.number().optional().describe("Duration in seconds (default: 5; Seedance accepts 4-15)"),
|
|
68201
68416
|
ratio: external_exports.string().optional().describe("Aspect ratio: 16:9, 9:16, 1:1 (default: 16:9)"),
|
|
68202
68417
|
mode: external_exports.string().optional().describe("Kling mode: std or pro"),
|
|
@@ -68205,6 +68420,7 @@ var init_generate2 = __esm({
|
|
|
68205
68420
|
veoModel: external_exports.string().optional().describe("Veo model: 3.0, 3.1, 3.1-fast"),
|
|
68206
68421
|
runwayModel: external_exports.string().optional().describe("Runway model: gen4.5, gen4_turbo"),
|
|
68207
68422
|
seedanceModel: external_exports.string().optional().describe("Seedance variant: quality or fast (fal.ai only)"),
|
|
68423
|
+
generateAudio: external_exports.boolean().optional().describe("Generate native synchronized audio when supported"),
|
|
68208
68424
|
output: external_exports.string().optional().describe("Output file path (downloads video)"),
|
|
68209
68425
|
wait: external_exports.boolean().optional().describe("Wait for completion (default: true)")
|
|
68210
68426
|
}),
|
|
@@ -71438,7 +71654,7 @@ init_source();
|
|
|
71438
71654
|
// package.json
|
|
71439
71655
|
var package_default = {
|
|
71440
71656
|
name: "@vibeframe/cli",
|
|
71441
|
-
version: "0.
|
|
71657
|
+
version: "0.105.1",
|
|
71442
71658
|
description: "VibeFrame CLI - natural language video editing from the terminal",
|
|
71443
71659
|
private: false,
|
|
71444
71660
|
license: "MIT",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibeframe/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.105.1",
|
|
4
4
|
"description": "VibeFrame CLI - natural language video editing from the terminal",
|
|
5
5
|
"private": false,
|
|
6
6
|
"license": "MIT",
|
|
@@ -183,8 +183,8 @@
|
|
|
183
183
|
"tsx": "^4.21.0",
|
|
184
184
|
"typescript": "^5.3.3",
|
|
185
185
|
"vitest": "^1.2.2",
|
|
186
|
-
"@vibeframe/
|
|
187
|
-
"@vibeframe/
|
|
186
|
+
"@vibeframe/ai-providers": "0.105.1",
|
|
187
|
+
"@vibeframe/core": "0.105.1"
|
|
188
188
|
},
|
|
189
189
|
"engines": {
|
|
190
190
|
"node": ">=20"
|