@vibeframe/cli 0.105.2 → 0.106.2
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/commands/_shared/edit/silence-cut.d.ts +1 -1
- package/dist/commands/_shared/render-inspect.d.ts +1 -1
- package/dist/commands/_shared/scene-html-emit.d.ts +24 -0
- package/dist/commands/ai-analyze.d.ts +2 -2
- package/dist/commands/ai-motion.d.ts +1 -1
- package/dist/commands/ai-review.d.ts +1 -1
- package/dist/commands/ai-video.d.ts +1 -1
- package/dist/commands/generate/video-status.d.ts +2 -2
- package/dist/commands/generate.d.ts +1 -1
- package/dist/commands/scene.d.ts +4 -1
- package/dist/index.js +398 -96
- package/dist/tools/manifest/edit.d.ts +11 -11
- package/dist/tools/manifest/generate.d.ts +9 -6
- package/dist/tools/manifest/index.js +380 -88
- package/dist/tools/manifest/inspect.d.ts +12 -12
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -7299,6 +7299,39 @@ var init_whisper = __esm({
|
|
|
7299
7299
|
}
|
|
7300
7300
|
});
|
|
7301
7301
|
|
|
7302
|
+
// ../ai-providers/dist/gemini/gemini-models.js
|
|
7303
|
+
function isGeminiTextModelAlias(model) {
|
|
7304
|
+
return Object.prototype.hasOwnProperty.call(GEMINI_TEXT_MODEL_ALIASES, model);
|
|
7305
|
+
}
|
|
7306
|
+
function resolveGeminiTextModel(model) {
|
|
7307
|
+
const trimmed = model?.trim();
|
|
7308
|
+
if (!trimmed)
|
|
7309
|
+
return GEMINI_DEFAULT_TEXT_MODEL;
|
|
7310
|
+
if (isGeminiTextModelAlias(trimmed))
|
|
7311
|
+
return GEMINI_TEXT_MODEL_ALIASES[trimmed];
|
|
7312
|
+
if (trimmed.startsWith("gemini-"))
|
|
7313
|
+
return trimmed;
|
|
7314
|
+
return GEMINI_DEFAULT_TEXT_MODEL;
|
|
7315
|
+
}
|
|
7316
|
+
var GEMINI_DEFAULT_TEXT_MODEL, GEMINI_AGENT_DEFAULT_TEXT_MODEL, GEMINI_TEXT_MODEL_ALIASES, GEMINI_TEXT_MODEL_HELP;
|
|
7317
|
+
var init_gemini_models = __esm({
|
|
7318
|
+
"../ai-providers/dist/gemini/gemini-models.js"() {
|
|
7319
|
+
"use strict";
|
|
7320
|
+
GEMINI_DEFAULT_TEXT_MODEL = "gemini-3.5-flash";
|
|
7321
|
+
GEMINI_AGENT_DEFAULT_TEXT_MODEL = "gemini-2.5-flash";
|
|
7322
|
+
GEMINI_TEXT_MODEL_ALIASES = {
|
|
7323
|
+
flash: GEMINI_DEFAULT_TEXT_MODEL,
|
|
7324
|
+
latest: GEMINI_DEFAULT_TEXT_MODEL,
|
|
7325
|
+
"flash-3.5": GEMINI_DEFAULT_TEXT_MODEL,
|
|
7326
|
+
"flash-3": "gemini-3-flash-preview",
|
|
7327
|
+
"flash-2.5": "gemini-2.5-flash",
|
|
7328
|
+
pro: "gemini-2.5-pro",
|
|
7329
|
+
"pro-3.1": "gemini-3.1-pro-preview"
|
|
7330
|
+
};
|
|
7331
|
+
GEMINI_TEXT_MODEL_HELP = "flash/latest (Gemini 3.5 Flash), flash-3.5, flash-3, flash-2.5, pro, pro-3.1, or a full gemini-* model ID";
|
|
7332
|
+
}
|
|
7333
|
+
});
|
|
7334
|
+
|
|
7302
7335
|
// ../ai-providers/dist/gemini/gemini-motion.js
|
|
7303
7336
|
function buildMotionSystemPrompt(width, height, fps, duration, durationInFrames, stylePreset) {
|
|
7304
7337
|
return `You are a world-class broadcast motion graphics designer (like Apple Keynote, Netflix intros, ESPN graphics). Create STUNNING, jaw-dropping overlays that make viewers go "wow".
|
|
@@ -7452,7 +7485,7 @@ async function generateMotion(api, description, options = {}) {
|
|
|
7452
7485
|
const duration = options.duration || 5;
|
|
7453
7486
|
const durationInFrames = Math.round(duration * fps);
|
|
7454
7487
|
const stylePreset = options.style || "modern and clean";
|
|
7455
|
-
const modelId = options.model
|
|
7488
|
+
const modelId = resolveGeminiTextModel(options.model);
|
|
7456
7489
|
let systemPrompt = buildMotionSystemPrompt(width, height, fps, duration, durationInFrames, stylePreset);
|
|
7457
7490
|
if (options.videoContext) {
|
|
7458
7491
|
const sourceLabel = options.sourceType === "image" ? "IMAGE" : "VIDEO";
|
|
@@ -7533,7 +7566,7 @@ async function refineMotion(api, existingCode, instructions, options = {}) {
|
|
|
7533
7566
|
const fps = options.fps || 30;
|
|
7534
7567
|
const duration = options.duration || 5;
|
|
7535
7568
|
const durationInFrames = Math.round(duration * fps);
|
|
7536
|
-
const modelId = options.model
|
|
7569
|
+
const modelId = resolveGeminiTextModel(options.model);
|
|
7537
7570
|
const systemPrompt = `You are a world-class broadcast motion graphics designer. Modify the provided Remotion component based on instructions.
|
|
7538
7571
|
|
|
7539
7572
|
CANVAS: ${width}\xD7${height}px | ${fps}fps | ${durationInFrames} frames (${duration}s)
|
|
@@ -7628,9 +7661,18 @@ var GEMINI_MOTION_MODELS, STYLE_USER_INSTRUCTIONS;
|
|
|
7628
7661
|
var init_gemini_motion = __esm({
|
|
7629
7662
|
"../ai-providers/dist/gemini/gemini-motion.js"() {
|
|
7630
7663
|
"use strict";
|
|
7664
|
+
init_gemini_models();
|
|
7631
7665
|
GEMINI_MOTION_MODELS = {
|
|
7666
|
+
gemini: GEMINI_DEFAULT_TEXT_MODEL,
|
|
7667
|
+
flash: GEMINI_DEFAULT_TEXT_MODEL,
|
|
7668
|
+
latest: GEMINI_DEFAULT_TEXT_MODEL,
|
|
7669
|
+
"flash-3.5": GEMINI_DEFAULT_TEXT_MODEL,
|
|
7670
|
+
"flash-3": "gemini-3-flash-preview",
|
|
7671
|
+
"flash-2.5": "gemini-2.5-flash",
|
|
7632
7672
|
pro: "gemini-2.5-pro",
|
|
7633
|
-
"
|
|
7673
|
+
"2.5-pro": "gemini-2.5-pro",
|
|
7674
|
+
"3.1-pro": "gemini-3.1-pro-preview",
|
|
7675
|
+
"pro-3.1": "gemini-3.1-pro-preview"
|
|
7634
7676
|
};
|
|
7635
7677
|
STYLE_USER_INSTRUCTIONS = {
|
|
7636
7678
|
minimal: "CENTER-ALIGNED pure typography. Thin lines + large title + subtitle. NO glass panels, NO bokeh, NO dark bars. Breathing pulse during hold.",
|
|
@@ -7753,7 +7795,7 @@ async function analyzeContent(api, content, targetDuration, options) {
|
|
|
7753
7795
|
maxOutputTokens: 4096
|
|
7754
7796
|
}
|
|
7755
7797
|
};
|
|
7756
|
-
const response = await fetch(`${api.baseUrl}/models
|
|
7798
|
+
const response = await fetch(`${api.baseUrl}/models/${GEMINI_DEFAULT_TEXT_MODEL}:generateContent?key=${api.apiKey}`, {
|
|
7757
7799
|
method: "POST",
|
|
7758
7800
|
headers: { "Content-Type": "application/json" },
|
|
7759
7801
|
body: JSON.stringify(payload)
|
|
@@ -7786,6 +7828,7 @@ var init_gemini_storyboard = __esm({
|
|
|
7786
7828
|
"../ai-providers/dist/gemini/gemini-storyboard.js"() {
|
|
7787
7829
|
"use strict";
|
|
7788
7830
|
init_storyboard_prompt();
|
|
7831
|
+
init_gemini_models();
|
|
7789
7832
|
}
|
|
7790
7833
|
});
|
|
7791
7834
|
|
|
@@ -7824,6 +7867,7 @@ var init_GeminiProvider = __esm({
|
|
|
7824
7867
|
"../ai-providers/dist/gemini/GeminiProvider.js"() {
|
|
7825
7868
|
"use strict";
|
|
7826
7869
|
init_gemini_motion();
|
|
7870
|
+
init_gemini_models();
|
|
7827
7871
|
init_gemini_storyboard();
|
|
7828
7872
|
init_http();
|
|
7829
7873
|
MODEL_MAP = {
|
|
@@ -8332,7 +8376,7 @@ var init_GeminiProvider = __esm({
|
|
|
8332
8376
|
error: "Google API key not configured"
|
|
8333
8377
|
};
|
|
8334
8378
|
}
|
|
8335
|
-
const modelId = options.model
|
|
8379
|
+
const modelId = resolveGeminiTextModel(options.model);
|
|
8336
8380
|
try {
|
|
8337
8381
|
let videoPart;
|
|
8338
8382
|
if (typeof videoData === "string") {
|
|
@@ -8439,7 +8483,7 @@ var init_GeminiProvider = __esm({
|
|
|
8439
8483
|
error: "Google API key not configured"
|
|
8440
8484
|
};
|
|
8441
8485
|
}
|
|
8442
|
-
const modelId = options.model
|
|
8486
|
+
const modelId = resolveGeminiTextModel(options.model);
|
|
8443
8487
|
try {
|
|
8444
8488
|
const buffers = Array.isArray(imageData) ? imageData : [imageData];
|
|
8445
8489
|
const imageParts = buffers.map((buf) => ({
|
|
@@ -8541,7 +8585,7 @@ Example response:
|
|
|
8541
8585
|
[{"type":"trim","description":"Trim intro to 3 seconds","clipIds":["clip-1"],"params":{"newDuration":3},"confidence":0.9}]
|
|
8542
8586
|
|
|
8543
8587
|
Respond with ONLY the JSON array, no other text.`;
|
|
8544
|
-
const response = await fetch(`${this.baseUrl}/models
|
|
8588
|
+
const response = await fetch(`${this.baseUrl}/models/${GEMINI_DEFAULT_TEXT_MODEL}:generateContent?key=${this.apiKey}`, {
|
|
8545
8589
|
method: "POST",
|
|
8546
8590
|
headers: {
|
|
8547
8591
|
"Content-Type": "application/json"
|
|
@@ -8663,6 +8707,7 @@ var init_gemini = __esm({
|
|
|
8663
8707
|
"use strict";
|
|
8664
8708
|
init_GeminiProvider();
|
|
8665
8709
|
init_gemini_motion();
|
|
8710
|
+
init_gemini_models();
|
|
8666
8711
|
init_define_provider();
|
|
8667
8712
|
defineProvider({
|
|
8668
8713
|
id: "gemini",
|
|
@@ -18026,6 +18071,10 @@ __export(dist_exports2, {
|
|
|
18026
18071
|
ClaudeProvider: () => ClaudeProvider,
|
|
18027
18072
|
ElevenLabsProvider: () => ElevenLabsProvider,
|
|
18028
18073
|
FalProvider: () => FalProvider,
|
|
18074
|
+
GEMINI_AGENT_DEFAULT_TEXT_MODEL: () => GEMINI_AGENT_DEFAULT_TEXT_MODEL,
|
|
18075
|
+
GEMINI_DEFAULT_TEXT_MODEL: () => GEMINI_DEFAULT_TEXT_MODEL,
|
|
18076
|
+
GEMINI_TEXT_MODEL_ALIASES: () => GEMINI_TEXT_MODEL_ALIASES,
|
|
18077
|
+
GEMINI_TEXT_MODEL_HELP: () => GEMINI_TEXT_MODEL_HELP,
|
|
18029
18078
|
GeminiProvider: () => GeminiProvider,
|
|
18030
18079
|
GrokProvider: () => GrokProvider,
|
|
18031
18080
|
KNOWN_VOICES: () => KNOWN_VOICES,
|
|
@@ -18056,6 +18105,7 @@ __export(dist_exports2, {
|
|
|
18056
18105
|
getProvidersFor: () => getProvidersFor,
|
|
18057
18106
|
getSetupProviders: () => getSetupProviders,
|
|
18058
18107
|
grokProvider: () => grokProvider,
|
|
18108
|
+
isGeminiTextModelAlias: () => isGeminiTextModelAlias,
|
|
18059
18109
|
klingProvider: () => klingProvider,
|
|
18060
18110
|
kokoroProvider: () => kokoroProvider,
|
|
18061
18111
|
ollamaProvider: () => ollamaProvider,
|
|
@@ -18063,6 +18113,7 @@ __export(dist_exports2, {
|
|
|
18063
18113
|
openaiProvider: () => openaiProvider,
|
|
18064
18114
|
providerRegistry: () => providerRegistry,
|
|
18065
18115
|
replicateProvider: () => replicateProvider,
|
|
18116
|
+
resolveGeminiTextModel: () => resolveGeminiTextModel,
|
|
18066
18117
|
resolveVoiceId: () => resolveVoiceId,
|
|
18067
18118
|
runwayProvider: () => runwayProvider,
|
|
18068
18119
|
whisperProvider: () => whisperProvider
|
|
@@ -27471,6 +27522,52 @@ function buildPreset(input) {
|
|
|
27471
27522
|
}
|
|
27472
27523
|
}
|
|
27473
27524
|
}
|
|
27525
|
+
function lottieOverlayStyle(input) {
|
|
27526
|
+
const pos = input.position ?? "full";
|
|
27527
|
+
const rawScale = input.scale ?? (pos === "full" ? 1 : 0.25);
|
|
27528
|
+
const scale = Math.max(0.01, Math.min(2, rawScale));
|
|
27529
|
+
const opacity = Math.max(0, Math.min(1, input.opacity ?? 1));
|
|
27530
|
+
const base = [
|
|
27531
|
+
"position:absolute",
|
|
27532
|
+
"pointer-events:none",
|
|
27533
|
+
`opacity:${opacity}`
|
|
27534
|
+
];
|
|
27535
|
+
if (pos === "full") {
|
|
27536
|
+
base.push("inset:0", "width:100%", "height:100%");
|
|
27537
|
+
} else {
|
|
27538
|
+
const pct = scale * 100;
|
|
27539
|
+
base.push(`width:${pct}%`, `height:${pct}%`);
|
|
27540
|
+
switch (pos) {
|
|
27541
|
+
case "center":
|
|
27542
|
+
base.push("top:50%", "left:50%", "transform:translate(-50%,-50%)");
|
|
27543
|
+
break;
|
|
27544
|
+
case "top-left":
|
|
27545
|
+
base.push("top:4%", "left:4%");
|
|
27546
|
+
break;
|
|
27547
|
+
case "top-right":
|
|
27548
|
+
base.push("top:4%", "right:4%");
|
|
27549
|
+
break;
|
|
27550
|
+
case "bottom-left":
|
|
27551
|
+
base.push("bottom:4%", "left:4%");
|
|
27552
|
+
break;
|
|
27553
|
+
case "bottom-right":
|
|
27554
|
+
base.push("bottom:4%", "right:4%");
|
|
27555
|
+
break;
|
|
27556
|
+
}
|
|
27557
|
+
}
|
|
27558
|
+
return base.join(";");
|
|
27559
|
+
}
|
|
27560
|
+
function buildLottieOverlay(input, sceneId) {
|
|
27561
|
+
const loop = input.loop ?? true ? " loop" : "";
|
|
27562
|
+
const style = lottieOverlayStyle(input);
|
|
27563
|
+
const overlayId = `lottie-overlay-${sceneId}`;
|
|
27564
|
+
const markup = `<dotlottie-wc id="${overlayId}" src="${esc(input.src)}" autoplay${loop} style="${style}"></dotlottie-wc>`;
|
|
27565
|
+
const script = `<script type="module">
|
|
27566
|
+
import { setWasmUrl } from "${DOTLOTTIE_WC_CDN}";
|
|
27567
|
+
setWasmUrl("${DOTLOTTIE_WASM_CDN}");
|
|
27568
|
+
</script>`;
|
|
27569
|
+
return { markup, script };
|
|
27570
|
+
}
|
|
27474
27571
|
function emitSceneHtml(input) {
|
|
27475
27572
|
if (input.duration <= 0) {
|
|
27476
27573
|
throw new Error(`Scene duration must be > 0, got ${input.duration}`);
|
|
@@ -27491,15 +27588,20 @@ function emitSceneHtml(input) {
|
|
|
27491
27588
|
data-volume="1"
|
|
27492
27589
|
></audio>
|
|
27493
27590
|
` : "";
|
|
27591
|
+
const lottieLayer = input.lottie ? buildLottieOverlay(input.lottie, id) : null;
|
|
27592
|
+
const lottieMarkup = lottieLayer ? `
|
|
27593
|
+
${lottieLayer.markup}` : "";
|
|
27594
|
+
const lottieScript = lottieLayer ? `
|
|
27595
|
+
${lottieLayer.script}` : "";
|
|
27494
27596
|
return `<template id="scene-${id}-template">
|
|
27495
27597
|
<div data-composition-id="${id}" data-start="0" data-duration="${dur}" data-width="${input.width}" data-height="${input.height}">
|
|
27496
27598
|
<style>
|
|
27497
27599
|
${parts.css}
|
|
27498
27600
|
</style>
|
|
27499
27601
|
|
|
27500
|
-
${parts.body}
|
|
27602
|
+
${parts.body}${lottieMarkup}
|
|
27501
27603
|
${audioBlock}
|
|
27502
|
-
<script src="${GSAP_CDN}"></script
|
|
27604
|
+
<script src="${GSAP_CDN}"></script>${lottieScript}
|
|
27503
27605
|
<script>
|
|
27504
27606
|
window.__timelines = window.__timelines || {};
|
|
27505
27607
|
const tl = gsap.timeline({ paused: true });
|
|
@@ -27561,7 +27663,7 @@ function readRootDims(rootHtml) {
|
|
|
27561
27663
|
if (!widthMatch || !heightMatch) return null;
|
|
27562
27664
|
return { width: parseInt(widthMatch[1], 10), height: parseInt(heightMatch[1], 10) };
|
|
27563
27665
|
}
|
|
27564
|
-
var SCENE_PRESETS, GSAP_CDN, SCENE_OVERLAP_SECONDS;
|
|
27666
|
+
var SCENE_PRESETS, LOTTIE_POSITIONS, GSAP_CDN, SCENE_OVERLAP_SECONDS, DOTLOTTIE_WC_VERSION, DOTLOTTIE_WEB_VERSION, DOTLOTTIE_WC_CDN, DOTLOTTIE_WASM_CDN;
|
|
27565
27667
|
var init_scene_html_emit = __esm({
|
|
27566
27668
|
"src/commands/_shared/scene-html-emit.ts"() {
|
|
27567
27669
|
"use strict";
|
|
@@ -27572,8 +27674,20 @@ var init_scene_html_emit = __esm({
|
|
|
27572
27674
|
"kinetic-type",
|
|
27573
27675
|
"product-shot"
|
|
27574
27676
|
];
|
|
27677
|
+
LOTTIE_POSITIONS = [
|
|
27678
|
+
"full",
|
|
27679
|
+
"center",
|
|
27680
|
+
"top-left",
|
|
27681
|
+
"top-right",
|
|
27682
|
+
"bottom-left",
|
|
27683
|
+
"bottom-right"
|
|
27684
|
+
];
|
|
27575
27685
|
GSAP_CDN = "https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js";
|
|
27576
27686
|
SCENE_OVERLAP_SECONDS = 0.4;
|
|
27687
|
+
DOTLOTTIE_WC_VERSION = "0.9.12";
|
|
27688
|
+
DOTLOTTIE_WEB_VERSION = "0.71.0";
|
|
27689
|
+
DOTLOTTIE_WC_CDN = `https://cdn.jsdelivr.net/npm/@lottiefiles/dotlottie-wc@${DOTLOTTIE_WC_VERSION}/dist/index.js`;
|
|
27690
|
+
DOTLOTTIE_WASM_CDN = `https://cdn.jsdelivr.net/npm/@lottiefiles/dotlottie-web@${DOTLOTTIE_WEB_VERSION}/dist/dotlottie-player.wasm`;
|
|
27577
27691
|
}
|
|
27578
27692
|
});
|
|
27579
27693
|
|
|
@@ -29607,6 +29721,7 @@ var MODEL_SETTINGS_BY_PROVIDER, ComposeBeatError, defaultCallLLM, CONFIG_PROVIDE
|
|
|
29607
29721
|
var init_compose_scenes_skills = __esm({
|
|
29608
29722
|
"src/commands/_shared/compose-scenes-skills.ts"() {
|
|
29609
29723
|
"use strict";
|
|
29724
|
+
init_dist2();
|
|
29610
29725
|
init_config();
|
|
29611
29726
|
init_bundle();
|
|
29612
29727
|
init_scene_lint();
|
|
@@ -29628,12 +29743,12 @@ var init_compose_scenes_skills = __esm({
|
|
|
29628
29743
|
medium: { model: "gpt-5", maxTokens: 6e3, costPerMTokIn: 1.25, costPerMTokOut: 10 },
|
|
29629
29744
|
high: { model: "gpt-5", maxTokens: 8e3, costPerMTokIn: 1.25, costPerMTokOut: 10 }
|
|
29630
29745
|
},
|
|
29631
|
-
// Google Gemini
|
|
29632
|
-
//
|
|
29746
|
+
// Google Gemini 3.5 Flash — current one-shot Gemini default for
|
|
29747
|
+
// analysis/composition. Keep agent loops on their explicit 2.5 Flash default.
|
|
29633
29748
|
gemini: {
|
|
29634
|
-
low: { model:
|
|
29635
|
-
medium: { model:
|
|
29636
|
-
high: { model:
|
|
29749
|
+
low: { model: GEMINI_DEFAULT_TEXT_MODEL, maxTokens: 4e3, costPerMTokIn: 1.5, costPerMTokOut: 9 },
|
|
29750
|
+
medium: { model: GEMINI_DEFAULT_TEXT_MODEL, maxTokens: 6e3, costPerMTokIn: 1.5, costPerMTokOut: 9 },
|
|
29751
|
+
high: { model: GEMINI_DEFAULT_TEXT_MODEL, maxTokens: 8e3, costPerMTokIn: 1.5, costPerMTokOut: 9 }
|
|
29637
29752
|
}
|
|
29638
29753
|
};
|
|
29639
29754
|
ComposeBeatError = class extends Error {
|
|
@@ -30579,6 +30694,30 @@ async function executeSceneAdd(opts) {
|
|
|
30579
30694
|
await writeFile11(imageAbsPath, buffer);
|
|
30580
30695
|
}
|
|
30581
30696
|
}
|
|
30697
|
+
let lottieRelPath;
|
|
30698
|
+
let lottieAbsPath;
|
|
30699
|
+
let lottieInput;
|
|
30700
|
+
if (opts.lottie) {
|
|
30701
|
+
const sourceAbs = resolve15(opts.lottie.src);
|
|
30702
|
+
if (!await pathExists2(sourceAbs)) {
|
|
30703
|
+
return errResult(`Lottie file not found: ${sourceAbs}`);
|
|
30704
|
+
}
|
|
30705
|
+
const ext = (sourceAbs.match(/\.([a-z0-9]+)$/i)?.[1] ?? "json").toLowerCase();
|
|
30706
|
+
if (ext !== "json" && ext !== "lottie") {
|
|
30707
|
+
return errResult(`Unsupported Lottie file extension: .${ext}. Use .json or .lottie.`);
|
|
30708
|
+
}
|
|
30709
|
+
lottieRelPath = `assets/lottie-${id}.${ext}`;
|
|
30710
|
+
lottieAbsPath = resolve15(projectDir, lottieRelPath);
|
|
30711
|
+
await mkdir6(dirname3(lottieAbsPath), { recursive: true });
|
|
30712
|
+
await copyFile(sourceAbs, lottieAbsPath);
|
|
30713
|
+
lottieInput = {
|
|
30714
|
+
src: lottieRelPath,
|
|
30715
|
+
position: opts.lottie.position,
|
|
30716
|
+
scale: opts.lottie.scale,
|
|
30717
|
+
opacity: opts.lottie.opacity,
|
|
30718
|
+
loop: opts.lottie.loop
|
|
30719
|
+
};
|
|
30720
|
+
}
|
|
30582
30721
|
const cfg = await loadVibeProjectConfig(projectDir);
|
|
30583
30722
|
const fallback2 = cfg?.defaultSceneDuration ?? 5;
|
|
30584
30723
|
const NARRATION_TAIL_BUFFER = 0.5;
|
|
@@ -30607,7 +30746,8 @@ async function executeSceneAdd(opts) {
|
|
|
30607
30746
|
kicker: opts.kicker,
|
|
30608
30747
|
imagePath: imageRelPath,
|
|
30609
30748
|
audioPath: audioRelPath,
|
|
30610
|
-
transcript: transcriptWords
|
|
30749
|
+
transcript: transcriptWords,
|
|
30750
|
+
lottie: lottieInput
|
|
30611
30751
|
});
|
|
30612
30752
|
await mkdir6(dirname3(scenePath), { recursive: true });
|
|
30613
30753
|
await writeFile11(scenePath, sceneHtml, "utf-8");
|
|
@@ -30628,6 +30768,7 @@ async function executeSceneAdd(opts) {
|
|
|
30628
30768
|
rootPath: relative6(process.cwd(), rootPath) || rootPath,
|
|
30629
30769
|
audioPath: audioAbsPath ? relative6(process.cwd(), audioAbsPath) || audioAbsPath : void 0,
|
|
30630
30770
|
imagePath: imageAbsPath ? relative6(process.cwd(), imageAbsPath) || imageAbsPath : void 0,
|
|
30771
|
+
lottiePath: lottieAbsPath ? relative6(process.cwd(), lottieAbsPath) || lottieAbsPath : void 0,
|
|
30631
30772
|
transcriptPath: transcriptAbsPath ? relative6(process.cwd(), transcriptAbsPath) || transcriptAbsPath : void 0,
|
|
30632
30773
|
transcriptWordCount
|
|
30633
30774
|
};
|
|
@@ -30905,9 +31046,40 @@ Run 'vibe schema scene.<command>' for structured parameter info.`
|
|
|
30905
31046
|
).option("--no-image", "Skip image generation even when --visuals is provided").option(
|
|
30906
31047
|
"--no-transcribe",
|
|
30907
31048
|
"Skip Whisper word-level transcribe step (no transcript-<id>.json emitted)"
|
|
30908
|
-
).option("--transcribe-language <code>", "BCP-47 language code passed to Whisper (e.g. en, ko)").option("--force", "Overwrite an existing compositions/scene-<id>.html").option("--
|
|
31049
|
+
).option("--transcribe-language <code>", "BCP-47 language code passed to Whisper (e.g. en, ko)").option("--force", "Overwrite an existing compositions/scene-<id>.html").option("--lottie <path>", "Lottie animation file (.json/.lottie) to overlay on the scene").option(
|
|
31050
|
+
"--lottie-position <position>",
|
|
31051
|
+
`Lottie position: ${LOTTIE_POSITIONS.join(", ")}`,
|
|
31052
|
+
"full"
|
|
31053
|
+
).option("--lottie-scale <number>", "Lottie overlay scale (0.01-2)").option("--lottie-opacity <number>", "Lottie overlay opacity (0-1)", "1").option("--lottie-no-loop", "Do not loop the Lottie animation").option("--dry-run", "Preview parameters without writing files or calling APIs").action(async (name, options) => {
|
|
30909
31054
|
const startedAt = Date.now();
|
|
30910
31055
|
if (options.style) options.style = validatePreset(options.style);
|
|
31056
|
+
if (options.lottiePosition) {
|
|
31057
|
+
if (!LOTTIE_POSITIONS.includes(options.lottiePosition)) {
|
|
31058
|
+
exitWithError(
|
|
31059
|
+
usageError(
|
|
31060
|
+
`Invalid --lottie-position "${options.lottiePosition}". Valid: ${LOTTIE_POSITIONS.join(", ")}`
|
|
31061
|
+
)
|
|
31062
|
+
);
|
|
31063
|
+
}
|
|
31064
|
+
}
|
|
31065
|
+
let lottieScale;
|
|
31066
|
+
if (options.lottieScale !== void 0) {
|
|
31067
|
+
lottieScale = Number(options.lottieScale);
|
|
31068
|
+
if (!Number.isFinite(lottieScale) || lottieScale < 0.01 || lottieScale > 2) {
|
|
31069
|
+
exitWithError(
|
|
31070
|
+
usageError(`Invalid --lottie-scale "${options.lottieScale}". Must be between 0.01 and 2.`)
|
|
31071
|
+
);
|
|
31072
|
+
}
|
|
31073
|
+
}
|
|
31074
|
+
let lottieOpacity = 1;
|
|
31075
|
+
if (options.lottieOpacity !== void 0) {
|
|
31076
|
+
lottieOpacity = Number(options.lottieOpacity);
|
|
31077
|
+
if (!Number.isFinite(lottieOpacity) || lottieOpacity < 0 || lottieOpacity > 1) {
|
|
31078
|
+
exitWithError(
|
|
31079
|
+
usageError(`Invalid --lottie-opacity "${options.lottieOpacity}". Must be between 0 and 1.`)
|
|
31080
|
+
);
|
|
31081
|
+
}
|
|
31082
|
+
}
|
|
30911
31083
|
if (options.duration !== void 0) options.duration = validateDuration(options.duration);
|
|
30912
31084
|
let tts;
|
|
30913
31085
|
try {
|
|
@@ -30936,7 +31108,11 @@ Run 'vibe schema scene.<command>' for structured parameter info.`
|
|
|
30936
31108
|
imageProvider: options.imageProvider,
|
|
30937
31109
|
tts,
|
|
30938
31110
|
audio: options.audio,
|
|
30939
|
-
|
|
31111
|
+
lottie: options.lottie ?? null,
|
|
31112
|
+
lottiePosition: options.lottiePosition,
|
|
31113
|
+
lottieScale: lottieScale ?? null,
|
|
31114
|
+
lottieOpacity: options.lottieOpacity !== void 0 ? lottieOpacity : null,
|
|
31115
|
+
lottieLoop: !options.lottieNoLoop,
|
|
30940
31116
|
image: options.image
|
|
30941
31117
|
}
|
|
30942
31118
|
}
|
|
@@ -30964,6 +31140,13 @@ Run 'vibe schema scene.<command>' for structured parameter info.`
|
|
|
30964
31140
|
skipTranscribe: options.transcribe === false,
|
|
30965
31141
|
transcribeLanguage: options.transcribeLanguage,
|
|
30966
31142
|
force: !!options.force,
|
|
31143
|
+
lottie: options.lottie ? {
|
|
31144
|
+
src: options.lottie,
|
|
31145
|
+
position: options.lottiePosition ?? "full",
|
|
31146
|
+
scale: lottieScale,
|
|
31147
|
+
opacity: options.lottieOpacity !== void 0 ? lottieOpacity : 1,
|
|
31148
|
+
loop: !options.lottieNoLoop
|
|
31149
|
+
} : void 0,
|
|
30967
31150
|
onProgress: (msg) => {
|
|
30968
31151
|
if (spinner2) spinner2.text = msg;
|
|
30969
31152
|
}
|
|
@@ -32028,7 +32211,7 @@ Use this image analysis to inform the color palette, typography placement, and o
|
|
|
32028
32211
|
6. Recommended animation timing and entrance/exit style
|
|
32029
32212
|
7. Any moments where overlays should pause, fade, or stay minimal`;
|
|
32030
32213
|
const analysisResult = await gemini.analyzeVideo(videoBuffer, analysisPrompt, {
|
|
32031
|
-
model:
|
|
32214
|
+
model: GEMINI_DEFAULT_TEXT_MODEL,
|
|
32032
32215
|
fps: 1,
|
|
32033
32216
|
lowResolution: true
|
|
32034
32217
|
});
|
|
@@ -32197,7 +32380,7 @@ function registerMotionCommand(aiCommand) {
|
|
|
32197
32380
|
"auto"
|
|
32198
32381
|
).option("--understanding-prompt <text>", "Custom prompt for --video understanding").option("--from-tsx <path>", "Refine an existing TSX file instead of generating from scratch").option(
|
|
32199
32382
|
"-m, --model <alias>",
|
|
32200
|
-
"LLM model: sonnet (default), opus, gemini, gemini-3.1-pro",
|
|
32383
|
+
"LLM model: sonnet (default), opus, gemini, gemini-2.5-pro, gemini-3.1-pro",
|
|
32201
32384
|
"sonnet"
|
|
32202
32385
|
).option("--dry-run", "Preview parameters without executing").action(async (description, options) => {
|
|
32203
32386
|
const startedAt = Date.now();
|
|
@@ -32341,7 +32524,8 @@ var init_ai_motion = __esm({
|
|
|
32341
32524
|
sonnet: { provider: "claude", modelId: "claude-sonnet-4-6" },
|
|
32342
32525
|
opus: { provider: "claude", modelId: "claude-opus-4-7" },
|
|
32343
32526
|
"opus-4-6": { provider: "claude", modelId: "claude-opus-4-6" },
|
|
32344
|
-
gemini: { provider: "gemini", modelId:
|
|
32527
|
+
gemini: { provider: "gemini", modelId: GEMINI_DEFAULT_TEXT_MODEL },
|
|
32528
|
+
"gemini-2.5-pro": { provider: "gemini", modelId: "gemini-2.5-pro" },
|
|
32345
32529
|
"gemini-3.1-pro": { provider: "gemini", modelId: "gemini-3.1-pro-preview" }
|
|
32346
32530
|
};
|
|
32347
32531
|
}
|
|
@@ -34263,12 +34447,37 @@ async function executeVideoStatus(options) {
|
|
|
34263
34447
|
} = options;
|
|
34264
34448
|
try {
|
|
34265
34449
|
const envKeyMap = {
|
|
34450
|
+
grok: "XAI_API_KEY",
|
|
34266
34451
|
runway: "RUNWAY_API_SECRET",
|
|
34267
|
-
kling: "KLING_API_KEY"
|
|
34452
|
+
kling: "KLING_API_KEY",
|
|
34453
|
+
veo: "GOOGLE_API_KEY"
|
|
34268
34454
|
};
|
|
34269
34455
|
const key = apiKey || process.env[envKeyMap[provider] || ""];
|
|
34270
34456
|
if (!key) return { success: false, error: `${envKeyMap[provider]} required` };
|
|
34271
|
-
if (provider === "
|
|
34457
|
+
if (provider === "grok") {
|
|
34458
|
+
const grok = new GrokProvider();
|
|
34459
|
+
await grok.initialize({ apiKey: key });
|
|
34460
|
+
let result = await grok.getGenerationStatus(taskId);
|
|
34461
|
+
if (wait && result.status !== "completed" && result.status !== "failed") {
|
|
34462
|
+
result = await grok.waitForCompletion(taskId, () => {
|
|
34463
|
+
});
|
|
34464
|
+
}
|
|
34465
|
+
let outputPath;
|
|
34466
|
+
if (output && result.videoUrl) {
|
|
34467
|
+
const buffer = await downloadVideo(result.videoUrl);
|
|
34468
|
+
outputPath = resolve23(process.cwd(), output);
|
|
34469
|
+
await writeFile20(outputPath, buffer);
|
|
34470
|
+
}
|
|
34471
|
+
return {
|
|
34472
|
+
success: true,
|
|
34473
|
+
taskId,
|
|
34474
|
+
status: result.status,
|
|
34475
|
+
progress: result.progress,
|
|
34476
|
+
videoUrl: result.videoUrl,
|
|
34477
|
+
outputPath,
|
|
34478
|
+
error: result.error
|
|
34479
|
+
};
|
|
34480
|
+
} else if (provider === "runway") {
|
|
34272
34481
|
const runway = new RunwayProvider();
|
|
34273
34482
|
await runway.initialize({ apiKey: key });
|
|
34274
34483
|
let result = await runway.getGenerationStatus(taskId);
|
|
@@ -34310,7 +34519,31 @@ async function executeVideoStatus(options) {
|
|
|
34310
34519
|
status: result.status,
|
|
34311
34520
|
videoUrl: result.videoUrl,
|
|
34312
34521
|
duration: result.duration,
|
|
34313
|
-
outputPath
|
|
34522
|
+
outputPath,
|
|
34523
|
+
error: result.error
|
|
34524
|
+
};
|
|
34525
|
+
} else if (provider === "veo") {
|
|
34526
|
+
const gemini = new GeminiProvider();
|
|
34527
|
+
await gemini.initialize({ apiKey: key });
|
|
34528
|
+
let result = await gemini.getGenerationStatus(taskId);
|
|
34529
|
+
if (wait && result.status !== "completed" && result.status !== "failed" && result.status !== "cancelled") {
|
|
34530
|
+
result = await gemini.waitForVideoCompletion(taskId, () => {
|
|
34531
|
+
});
|
|
34532
|
+
}
|
|
34533
|
+
let outputPath;
|
|
34534
|
+
if (output && result.videoUrl) {
|
|
34535
|
+
const buffer = await downloadVideo(result.videoUrl, key);
|
|
34536
|
+
outputPath = resolve23(process.cwd(), output);
|
|
34537
|
+
await writeFile20(outputPath, buffer);
|
|
34538
|
+
}
|
|
34539
|
+
return {
|
|
34540
|
+
success: true,
|
|
34541
|
+
taskId,
|
|
34542
|
+
status: result.status,
|
|
34543
|
+
progress: result.progress,
|
|
34544
|
+
videoUrl: result.videoUrl,
|
|
34545
|
+
outputPath,
|
|
34546
|
+
error: result.error
|
|
34314
34547
|
};
|
|
34315
34548
|
}
|
|
34316
34549
|
return { success: false, error: `Unsupported provider: ${provider}` };
|
|
@@ -34840,7 +35073,7 @@ function resolveRefreshOutput(record, opts) {
|
|
|
34840
35073
|
return record.outputPath ? resolve24(record.outputPath) : void 0;
|
|
34841
35074
|
}
|
|
34842
35075
|
function liveSupport(record) {
|
|
34843
|
-
if (record.jobType === "generate-video" && (record.provider === "runway" || record.provider === "kling")) {
|
|
35076
|
+
if (record.jobType === "generate-video" && (record.provider === "grok" || record.provider === "runway" || record.provider === "kling" || record.provider === "veo")) {
|
|
34844
35077
|
return { supported: true };
|
|
34845
35078
|
}
|
|
34846
35079
|
if (record.jobType === "generate-music" && record.provider === "replicate") {
|
|
@@ -35222,7 +35455,9 @@ function isActiveStatus(status) {
|
|
|
35222
35455
|
}
|
|
35223
35456
|
function providerStatusCommand(record) {
|
|
35224
35457
|
if (record.jobType === "generate-video") {
|
|
35225
|
-
if (record.provider !== "runway" && record.provider !== "kling"
|
|
35458
|
+
if (record.provider !== "grok" && record.provider !== "runway" && record.provider !== "kling" && record.provider !== "veo") {
|
|
35459
|
+
return void 0;
|
|
35460
|
+
}
|
|
35226
35461
|
const type = record.provider === "kling" && record.providerTaskType ? ` --type ${record.providerTaskType}` : "";
|
|
35227
35462
|
return `vibe generate video-status ${record.providerTaskId} -p ${record.provider}${type} --json`;
|
|
35228
35463
|
}
|
|
@@ -35768,13 +36003,7 @@ async function executeThumbnailBestFrame(options) {
|
|
|
35768
36003
|
await gemini.initialize({ apiKey: googleKey });
|
|
35769
36004
|
const videoData = await readFile17(videoPath);
|
|
35770
36005
|
const analysisPrompt = prompt3 || 'Analyze this video and find the single best frame for a thumbnail. Look for frames that are visually striking, well-composed, emotionally engaging, and representative of the video content. Avoid blurry frames, transitions, or dark scenes. Return ONLY a JSON object: {"timestamp": <seconds as number>, "reason": "<brief explanation>"}';
|
|
35771
|
-
const
|
|
35772
|
-
flash: "gemini-3-flash-preview",
|
|
35773
|
-
latest: "gemini-2.5-flash",
|
|
35774
|
-
"flash-2.5": "gemini-2.5-flash",
|
|
35775
|
-
pro: "gemini-2.5-pro"
|
|
35776
|
-
};
|
|
35777
|
-
const modelId = modelMap[model] || "gemini-3-flash-preview";
|
|
36006
|
+
const modelId = resolveGeminiTextModel(model);
|
|
35778
36007
|
const result = await gemini.analyzeVideo(videoData, analysisPrompt, {
|
|
35779
36008
|
model: modelId,
|
|
35780
36009
|
fps: 1
|
|
@@ -35822,7 +36051,7 @@ import { resolve as resolve27, dirname as dirname8, basename as basename5, extna
|
|
|
35822
36051
|
import { existsSync as existsSync17 } from "node:fs";
|
|
35823
36052
|
import { writeFile as writeFile25, mkdir as mkdir12 } from "node:fs/promises";
|
|
35824
36053
|
function registerThumbnailCommand(parent) {
|
|
35825
|
-
parent.command("thumbnail").description("Generate video thumbnail (DALL-E) or extract best frame from video (Gemini)").argument("[description]", "Thumbnail description (for DALL-E generation)").option("-k, --api-key <key>", "API key (OpenAI for generation, Google for best-frame)").option("-o, --output <path>", "Output file path").option("--style <style>", "Platform style: youtube, instagram, tiktok, twitter").option("--best-frame <video>", "Extract best thumbnail frame from video using Gemini AI").option("--prompt <prompt>", "Custom prompt for best-frame analysis").option("--model <model>",
|
|
36054
|
+
parent.command("thumbnail").description("Generate video thumbnail (DALL-E) or extract best frame from video (Gemini)").argument("[description]", "Thumbnail description (for DALL-E generation)").option("-k, --api-key <key>", "API key (OpenAI for generation, Google for best-frame)").option("-o, --output <path>", "Output file path").option("--style <style>", "Platform style: youtube, instagram, tiktok, twitter").option("--best-frame <video>", "Extract best thumbnail frame from video using Gemini AI").option("--prompt <prompt>", "Custom prompt for best-frame analysis").option("--model <model>", `Gemini model: ${GEMINI_TEXT_MODEL_HELP}`, "flash").action(async (description, options) => {
|
|
35826
36055
|
const startedAt = Date.now();
|
|
35827
36056
|
try {
|
|
35828
36057
|
if (description) rejectControlChars(description);
|
|
@@ -35988,7 +36217,10 @@ function getStatusColor(status) {
|
|
|
35988
36217
|
}
|
|
35989
36218
|
}
|
|
35990
36219
|
function registerVideoStatusCommand(parent) {
|
|
35991
|
-
parent.command("video-status", { hidden: true }).description("Check video generation status (Grok, Runway, or
|
|
36220
|
+
parent.command("video-status", { hidden: true }).description("Check video generation status (Grok, Runway, Kling, or Veo)").argument("<task-id>", "Task ID from video generation").option("-p, --provider <provider>", "Provider: grok, runway, kling, veo", "grok").option(
|
|
36221
|
+
"-k, --api-key <key>",
|
|
36222
|
+
"API key (or set XAI_API_KEY / RUNWAY_API_SECRET / KLING_API_KEY / GOOGLE_API_KEY env)"
|
|
36223
|
+
).option("--type <type>", "Task type: text2video or image2video (Kling only)", "text2video").option("--wait", "Wait for completion").option("-o, --output <path>", "Download video when complete").action(async (taskId, options) => {
|
|
35992
36224
|
const startedAt = Date.now();
|
|
35993
36225
|
try {
|
|
35994
36226
|
const provider = (options.provider || "grok").toLowerCase();
|
|
@@ -36048,18 +36280,12 @@ function registerVideoStatusCommand(parent) {
|
|
|
36048
36280
|
downloadSpinner.succeed(source_default.green(`Saved to: ${outputPath}`));
|
|
36049
36281
|
} catch (err) {
|
|
36050
36282
|
downloadSpinner.fail(
|
|
36051
|
-
source_default.red(
|
|
36052
|
-
`Failed to download video: ${err instanceof Error ? err.message : err}`
|
|
36053
|
-
)
|
|
36283
|
+
source_default.red(`Failed to download video: ${err instanceof Error ? err.message : err}`)
|
|
36054
36284
|
);
|
|
36055
36285
|
}
|
|
36056
36286
|
}
|
|
36057
36287
|
} else if (provider === "runway") {
|
|
36058
|
-
const apiKey = await requireApiKey(
|
|
36059
|
-
"RUNWAY_API_SECRET",
|
|
36060
|
-
"Runway",
|
|
36061
|
-
options.apiKey
|
|
36062
|
-
);
|
|
36288
|
+
const apiKey = await requireApiKey("RUNWAY_API_SECRET", "Runway", options.apiKey);
|
|
36063
36289
|
const spinner2 = ora("Checking status...").start();
|
|
36064
36290
|
const runway = new RunwayProvider();
|
|
36065
36291
|
await runway.initialize({ apiKey });
|
|
@@ -36120,9 +36346,7 @@ function registerVideoStatusCommand(parent) {
|
|
|
36120
36346
|
downloadSpinner.succeed(source_default.green(`Saved to: ${outputPath}`));
|
|
36121
36347
|
} catch (err) {
|
|
36122
36348
|
downloadSpinner.fail(
|
|
36123
|
-
source_default.red(
|
|
36124
|
-
`Failed to download video: ${err instanceof Error ? err.message : err}`
|
|
36125
|
-
)
|
|
36349
|
+
source_default.red(`Failed to download video: ${err instanceof Error ? err.message : err}`)
|
|
36126
36350
|
);
|
|
36127
36351
|
}
|
|
36128
36352
|
}
|
|
@@ -36188,15 +36412,77 @@ function registerVideoStatusCommand(parent) {
|
|
|
36188
36412
|
downloadSpinner.succeed(source_default.green(`Saved to: ${outputPath}`));
|
|
36189
36413
|
} catch (err) {
|
|
36190
36414
|
downloadSpinner.fail(
|
|
36191
|
-
source_default.red(
|
|
36192
|
-
|
|
36193
|
-
|
|
36415
|
+
source_default.red(`Failed to download video: ${err instanceof Error ? err.message : err}`)
|
|
36416
|
+
);
|
|
36417
|
+
}
|
|
36418
|
+
}
|
|
36419
|
+
} else if (provider === "veo") {
|
|
36420
|
+
const apiKey = await requireApiKey("GOOGLE_API_KEY", "Google", options.apiKey);
|
|
36421
|
+
const spinner2 = ora("Checking status...").start();
|
|
36422
|
+
const gemini = new GeminiProvider();
|
|
36423
|
+
await gemini.initialize({ apiKey });
|
|
36424
|
+
let result = await gemini.getGenerationStatus(taskId);
|
|
36425
|
+
if (options.wait && result.status !== "completed" && result.status !== "failed" && result.status !== "cancelled") {
|
|
36426
|
+
spinner2.text = "Waiting for completion...";
|
|
36427
|
+
result = await gemini.waitForVideoCompletion(taskId, (status) => {
|
|
36428
|
+
spinner2.text = status.progress !== void 0 ? `Generating... ${status.progress}%` : `Generating... ${status.status}`;
|
|
36429
|
+
});
|
|
36430
|
+
}
|
|
36431
|
+
spinner2.stop();
|
|
36432
|
+
if (isJsonMode()) {
|
|
36433
|
+
let outputPath;
|
|
36434
|
+
if (options.output && result.videoUrl) {
|
|
36435
|
+
const buffer = await downloadVideo(result.videoUrl, apiKey);
|
|
36436
|
+
outputPath = resolve28(process.cwd(), options.output);
|
|
36437
|
+
await writeFile26(outputPath, buffer);
|
|
36438
|
+
}
|
|
36439
|
+
outputSuccess({
|
|
36440
|
+
command: "generate video-status",
|
|
36441
|
+
startedAt,
|
|
36442
|
+
data: {
|
|
36443
|
+
taskId,
|
|
36444
|
+
provider: "veo",
|
|
36445
|
+
status: result.status,
|
|
36446
|
+
videoUrl: result.videoUrl,
|
|
36447
|
+
progress: result.progress,
|
|
36448
|
+
error: result.error,
|
|
36449
|
+
outputPath
|
|
36450
|
+
}
|
|
36451
|
+
});
|
|
36452
|
+
return;
|
|
36453
|
+
}
|
|
36454
|
+
console.log();
|
|
36455
|
+
console.log(source_default.bold.cyan("Generation Status"));
|
|
36456
|
+
console.log(source_default.dim("\u2500".repeat(60)));
|
|
36457
|
+
console.log(`Task ID: ${taskId}`);
|
|
36458
|
+
console.log(`Provider: Veo`);
|
|
36459
|
+
console.log(`Status: ${getStatusColor(result.status)}`);
|
|
36460
|
+
if (result.progress !== void 0) {
|
|
36461
|
+
console.log(`Progress: ${result.progress}%`);
|
|
36462
|
+
}
|
|
36463
|
+
if (result.videoUrl) {
|
|
36464
|
+
console.log(`Video URL: ${result.videoUrl}`);
|
|
36465
|
+
}
|
|
36466
|
+
if (result.error) {
|
|
36467
|
+
console.log(`Error: ${source_default.red(result.error)}`);
|
|
36468
|
+
}
|
|
36469
|
+
console.log();
|
|
36470
|
+
if (options.output && result.videoUrl) {
|
|
36471
|
+
const downloadSpinner = ora("Downloading video...").start();
|
|
36472
|
+
try {
|
|
36473
|
+
const buffer = await downloadVideo(result.videoUrl, apiKey);
|
|
36474
|
+
const outputPath = resolve28(process.cwd(), options.output);
|
|
36475
|
+
await writeFile26(outputPath, buffer);
|
|
36476
|
+
downloadSpinner.succeed(source_default.green(`Saved to: ${outputPath}`));
|
|
36477
|
+
} catch (err) {
|
|
36478
|
+
downloadSpinner.fail(
|
|
36479
|
+
source_default.red(`Failed to download video: ${err instanceof Error ? err.message : err}`)
|
|
36194
36480
|
);
|
|
36195
36481
|
}
|
|
36196
36482
|
}
|
|
36197
36483
|
} else {
|
|
36198
36484
|
exitWithError(
|
|
36199
|
-
usageError(`Invalid provider: ${provider}. Use grok, runway, or
|
|
36485
|
+
usageError(`Invalid provider: ${provider}. Use grok, runway, kling, or veo.`)
|
|
36200
36486
|
);
|
|
36201
36487
|
}
|
|
36202
36488
|
} catch (error) {
|
|
@@ -37977,7 +38263,7 @@ function registerVideoCommand(parent) {
|
|
|
37977
38263
|
"--seedance-model <model>",
|
|
37978
38264
|
"Seedance variant: quality or fast (fal.ai only)",
|
|
37979
38265
|
"quality"
|
|
37980
|
-
).option("--negative <prompt>", "Negative prompt - what to avoid (Kling/Veo)").option("--resolution <res>", "Video resolution: 720p, 1080p, 4k
|
|
38266
|
+
).option("--negative <prompt>", "Negative prompt - what to avoid (Kling/Veo)").option("--resolution <res>", "Video resolution: 480p, 720p, 1080p, or 4k depending on provider").option("--last-frame <path>", "Last frame image for frame interpolation (Veo) or Seedance end frame").option("--end-image <path>", "Ending frame image for Seedance image-to-video").option(
|
|
37981
38267
|
"--ref-images <paths...>",
|
|
37982
38268
|
"Reference images for Seedance reference-to-video or Veo character consistency"
|
|
37983
38269
|
).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(
|
|
@@ -38438,6 +38724,30 @@ Examples:
|
|
|
38438
38724
|
exitWithError(apiError(message, true));
|
|
38439
38725
|
}
|
|
38440
38726
|
}
|
|
38727
|
+
let seedanceEndImage;
|
|
38728
|
+
const seedanceEndImagePath = options.endImage ?? options.lastFrame;
|
|
38729
|
+
if (seedanceEndImagePath && seedanceReferences.length === 0) {
|
|
38730
|
+
try {
|
|
38731
|
+
const absEndImagePath = resolve31(process.cwd(), seedanceEndImagePath);
|
|
38732
|
+
const endImageBuffer = await readFile18(absEndImagePath);
|
|
38733
|
+
const ext = seedanceEndImagePath.toLowerCase().split(".").pop();
|
|
38734
|
+
const mimeType = ext === "jpg" || ext === "jpeg" ? "image/jpeg" : `image/${ext || "png"}`;
|
|
38735
|
+
const uploadHost = await resolveUploadHost();
|
|
38736
|
+
spinner2.text = `Uploading end image via ${uploadHost.provider} for Seedance...`;
|
|
38737
|
+
const upload = await uploadHost.uploadImage(endImageBuffer, {
|
|
38738
|
+
filename: seedanceEndImagePath,
|
|
38739
|
+
mimeType
|
|
38740
|
+
});
|
|
38741
|
+
seedanceEndImage = upload.url;
|
|
38742
|
+
} catch (err) {
|
|
38743
|
+
spinner2.fail("End image upload failed");
|
|
38744
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
38745
|
+
if (message.includes("IMGBB_API_KEY")) {
|
|
38746
|
+
exitWithError(authError("IMGBB_API_KEY", "ImgBB"));
|
|
38747
|
+
}
|
|
38748
|
+
exitWithError(apiError(message, true));
|
|
38749
|
+
}
|
|
38750
|
+
}
|
|
38441
38751
|
spinner2.text = "Generating video with fal.ai Seedance 2.0 (this may take 1-3 minutes)...";
|
|
38442
38752
|
const seedanceModel = String(options.seedanceModel ?? "quality").toLowerCase();
|
|
38443
38753
|
const falModel = seedanceModel === "fast" || seedanceModel === "seedance-2.0-fast" ? "seedance-2.0-fast" : "seedance-2.0";
|
|
@@ -38450,7 +38760,8 @@ Examples:
|
|
|
38450
38760
|
negativePrompt: options.negative,
|
|
38451
38761
|
model: falModel,
|
|
38452
38762
|
resolution: options.resolution,
|
|
38453
|
-
generateAudio: options.generateAudio
|
|
38763
|
+
generateAudio: options.generateAudio,
|
|
38764
|
+
lastFrame: seedanceEndImage
|
|
38454
38765
|
});
|
|
38455
38766
|
finalResult = result;
|
|
38456
38767
|
}
|
|
@@ -38760,12 +39071,7 @@ async function detectSilencePeriodsWithGemini(videoPath, minDuration, options) {
|
|
|
38760
39071
|
const gemini = new GeminiProvider();
|
|
38761
39072
|
await gemini.initialize({ apiKey: geminiApiKey });
|
|
38762
39073
|
const videoBuffer = await readFile19(videoPath);
|
|
38763
|
-
const
|
|
38764
|
-
flash: "gemini-3-flash-preview",
|
|
38765
|
-
"flash-2.5": "gemini-2.5-flash",
|
|
38766
|
-
pro: "gemini-2.5-pro"
|
|
38767
|
-
};
|
|
38768
|
-
const modelId = options.model ? modelMap[options.model] || modelMap.flash : void 0;
|
|
39074
|
+
const modelId = options.model ? resolveGeminiTextModel(options.model) : void 0;
|
|
38769
39075
|
const prompt3 = `Analyze this video and identify all silent or dead segments where there is NO meaningful content.
|
|
38770
39076
|
|
|
38771
39077
|
Detect these as silent/dead segments:
|
|
@@ -41671,7 +41977,7 @@ async function executeMotionOverlay(options) {
|
|
|
41671
41977
|
};
|
|
41672
41978
|
}
|
|
41673
41979
|
function registerMotionOverlayCommand(parent) {
|
|
41674
|
-
parent.command("motion-overlay").description("Apply designed motion graphics overlays to an existing video").argument("<video>", "Video file path").argument("[description]", "Motion overlay description (omit when using --asset)").option("--asset <path>", "User-provided .json/.lottie animation to overlay").option("-o, --output <path>", "Output video file path").option("-d, --duration <sec>", "Overlay/render duration in seconds").option("--start <sec>", "Overlay start time in seconds", "0").option("--style <style>", "Style preset for generated overlays: minimal, corporate, playful, cinematic").option("-m, --model <alias>", "LLM model for generated overlays: sonnet, opus, gemini, gemini-3.1-pro", "sonnet").option("--understand <mode>", "Analyze video before generated overlay: auto, off, required", "auto").option("--understanding-prompt <text>", "Custom prompt for video understanding").option("--position <position>", "Lottie position: full, center, top-left, top-right, bottom-left, bottom-right", "full").option("--scale <number>", "Lottie overlay scale (0.01-2)").option("--opacity <number>", "Lottie overlay opacity (0-1)", "1").option("--loop", "Loop Lottie overlay", true).option("--no-loop", "Do not loop Lottie overlay").option("--dry-run", "Preview parameters without executing").action(async (videoPath, description, options) => {
|
|
41980
|
+
parent.command("motion-overlay").description("Apply designed motion graphics overlays to an existing video").argument("<video>", "Video file path").argument("[description]", "Motion overlay description (omit when using --asset)").option("--asset <path>", "User-provided .json/.lottie animation to overlay").option("-o, --output <path>", "Output video file path").option("-d, --duration <sec>", "Overlay/render duration in seconds").option("--start <sec>", "Overlay start time in seconds", "0").option("--style <style>", "Style preset for generated overlays: minimal, corporate, playful, cinematic").option("-m, --model <alias>", "LLM model for generated overlays: sonnet, opus, gemini, gemini-2.5-pro, gemini-3.1-pro", "sonnet").option("--understand <mode>", "Analyze video before generated overlay: auto, off, required", "auto").option("--understanding-prompt <text>", "Custom prompt for video understanding").option("--position <position>", "Lottie position: full, center, top-left, top-right, bottom-left, bottom-right", "full").option("--scale <number>", "Lottie overlay scale (0.01-2)").option("--opacity <number>", "Lottie overlay opacity (0-1)", "1").option("--loop", "Loop Lottie overlay", true).option("--no-loop", "Do not loop Lottie overlay").option("--dry-run", "Preview parameters without executing").action(async (videoPath, description, options) => {
|
|
41675
41981
|
const startedAt = Date.now();
|
|
41676
41982
|
try {
|
|
41677
41983
|
if (options.output) validateOutputPath(options.output);
|
|
@@ -42761,12 +43067,7 @@ async function executeGeminiVideo(options) {
|
|
|
42761
43067
|
return { success: false, error: "Google API key required. Run 'vibe setup' or set GOOGLE_API_KEY in .env" };
|
|
42762
43068
|
}
|
|
42763
43069
|
const isYouTube = options.source.includes("youtube.com") || options.source.includes("youtu.be");
|
|
42764
|
-
const
|
|
42765
|
-
flash: "gemini-3-flash-preview",
|
|
42766
|
-
"flash-2.5": "gemini-2.5-flash",
|
|
42767
|
-
pro: "gemini-2.5-pro"
|
|
42768
|
-
};
|
|
42769
|
-
const modelId = modelMap[options.model || "flash"] || modelMap.flash;
|
|
43070
|
+
const modelId = resolveGeminiTextModel(options.model);
|
|
42770
43071
|
let videoData;
|
|
42771
43072
|
if (isYouTube) {
|
|
42772
43073
|
videoData = options.source;
|
|
@@ -42827,12 +43128,7 @@ async function executeAnalyze(options) {
|
|
|
42827
43128
|
error: "Cannot detect source type. Supported: images (.png/.jpg/.webp/.gif), videos (.mp4/.mov/.webm), YouTube URLs, image URLs."
|
|
42828
43129
|
};
|
|
42829
43130
|
}
|
|
42830
|
-
const
|
|
42831
|
-
flash: "gemini-3-flash-preview",
|
|
42832
|
-
"flash-2.5": "gemini-2.5-flash",
|
|
42833
|
-
pro: "gemini-2.5-pro"
|
|
42834
|
-
};
|
|
42835
|
-
const modelId = modelMap[options.model || "flash"] || modelMap.flash;
|
|
43131
|
+
const modelId = resolveGeminiTextModel(options.model);
|
|
42836
43132
|
const gemini = new GeminiProvider();
|
|
42837
43133
|
await gemini.initialize({ apiKey });
|
|
42838
43134
|
if (isImage) {
|
|
@@ -42912,7 +43208,7 @@ async function executeAnalyze(options) {
|
|
|
42912
43208
|
}
|
|
42913
43209
|
}
|
|
42914
43210
|
function registerAnalyzeCommands(aiCommand) {
|
|
42915
|
-
aiCommand.command("gemini-video").description("Analyze video using Gemini (summarize, Q&A, extract info)").argument("<source>", "Video file path or YouTube URL").argument("<prompt>", "Analysis prompt (e.g., 'Summarize this video')").option("-k, --api-key <key>", "Google API key (or set GOOGLE_API_KEY env)").option("-m, --model <model>",
|
|
43211
|
+
aiCommand.command("gemini-video").description("Analyze video using Gemini (summarize, Q&A, extract info)").argument("<source>", "Video file path or YouTube URL").argument("<prompt>", "Analysis prompt (e.g., 'Summarize this video')").option("-k, --api-key <key>", "Google API key (or set GOOGLE_API_KEY env)").option("-m, --model <model>", `Model: ${GEMINI_TEXT_MODEL_HELP}`, "flash").option("--fps <number>", "Frames per second (default: 1, higher for action)").option("--start <seconds>", "Start offset in seconds (for clipping)").option("--end <seconds>", "End offset in seconds (for clipping)").option("--low-res", "Use low resolution mode (fewer tokens, longer videos)").option("-v, --verbose", "Show token usage").action(async (source, prompt3, options) => {
|
|
42916
43212
|
try {
|
|
42917
43213
|
if (options.apiKey) {
|
|
42918
43214
|
process.env.GOOGLE_API_KEY = options.apiKey;
|
|
@@ -42955,7 +43251,7 @@ function registerAnalyzeCommands(aiCommand) {
|
|
|
42955
43251
|
exitWithError(apiError(`Video analysis failed: ${error instanceof Error ? error.message : String(error)}`, true));
|
|
42956
43252
|
}
|
|
42957
43253
|
});
|
|
42958
|
-
aiCommand.command("analyze").description("Analyze any media: images, videos, or YouTube URLs using Gemini").argument("<source>", "Image/video file path, image URL, or YouTube URL").argument("<prompt>", "Analysis prompt (e.g., 'Describe this image', 'Summarize this video')").option("-k, --api-key <key>", "Google API key (or set GOOGLE_API_KEY env)").option("-m, --model <model>",
|
|
43254
|
+
aiCommand.command("analyze").description("Analyze any media: images, videos, or YouTube URLs using Gemini").argument("<source>", "Image/video file path, image URL, or YouTube URL").argument("<prompt>", "Analysis prompt (e.g., 'Describe this image', 'Summarize this video')").option("-k, --api-key <key>", "Google API key (or set GOOGLE_API_KEY env)").option("-m, --model <model>", `Model: ${GEMINI_TEXT_MODEL_HELP}`, "flash").option("--fps <number>", "Frames per second for video (default: 1)").option("--start <seconds>", "Start offset in seconds (video only)").option("--end <seconds>", "End offset in seconds (video only)").option("--low-res", "Use low resolution mode (fewer tokens)").option("-v, --verbose", "Show token usage").action(async (source, prompt3, options) => {
|
|
42959
43255
|
try {
|
|
42960
43256
|
if (options.apiKey) {
|
|
42961
43257
|
process.env.GOOGLE_API_KEY = options.apiKey;
|
|
@@ -43076,12 +43372,7 @@ ${content}`;
|
|
|
43076
43372
|
|
|
43077
43373
|
Project context for beat-aware review:
|
|
43078
43374
|
${projectContext}` : "";
|
|
43079
|
-
const
|
|
43080
|
-
flash: "gemini-3-flash-preview",
|
|
43081
|
-
"flash-2.5": "gemini-2.5-flash",
|
|
43082
|
-
pro: "gemini-2.5-pro"
|
|
43083
|
-
};
|
|
43084
|
-
const modelId = modelMap[model] || modelMap.flash;
|
|
43375
|
+
const modelId = resolveGeminiTextModel(model);
|
|
43085
43376
|
const reviewPrompt = `You are a professional video editor reviewing this video for quality. Analyze the video and return a JSON review with the following structure. Return ONLY valid JSON, no extra text.
|
|
43086
43377
|
|
|
43087
43378
|
{
|
|
@@ -43188,7 +43479,7 @@ Score each category 1-10. Prefer beatIssues when you can map a problem to a stor
|
|
|
43188
43479
|
return result;
|
|
43189
43480
|
}
|
|
43190
43481
|
function registerReviewCommand(aiCommand) {
|
|
43191
|
-
aiCommand.command("review", { hidden: true }).description("Review video quality using Gemini AI and optionally auto-fix issues").argument("<source>", "Video file path").option("--storyboard <path>", "Storyboard JSON file for context").option("--auto-apply", "Automatically apply fixable corrections").option("--verify", "Run verification pass after applying fixes").option("-m, --model <model>",
|
|
43482
|
+
aiCommand.command("review", { hidden: true }).description("Review video quality using Gemini AI and optionally auto-fix issues").argument("<source>", "Video file path").option("--storyboard <path>", "Storyboard JSON file for context").option("--auto-apply", "Automatically apply fixable corrections").option("--verify", "Run verification pass after applying fixes").option("-m, --model <model>", `Gemini model: ${GEMINI_TEXT_MODEL_HELP}`, "flash").option("-o, --output <path>", "Output video file path (for auto-apply)").option("--dry-run", "Preview parameters without executing").action(async (videoPath, options) => {
|
|
43192
43483
|
const startedAt = Date.now();
|
|
43193
43484
|
try {
|
|
43194
43485
|
if (options.output) {
|
|
@@ -67614,7 +67905,7 @@ var init_edit = __esm({
|
|
|
67614
67905
|
duration: external_exports.number().optional().describe("Overlay/render duration in seconds"),
|
|
67615
67906
|
start: external_exports.number().optional().describe("Overlay start time in seconds"),
|
|
67616
67907
|
style: external_exports.string().optional().describe("Style preset for generated overlays"),
|
|
67617
|
-
model: external_exports.enum(["sonnet", "opus", "gemini", "gemini-3.1-pro"]).optional().describe("LLM model for generated overlays"),
|
|
67908
|
+
model: external_exports.enum(["sonnet", "opus", "gemini", "gemini-2.5-pro", "gemini-3.1-pro"]).optional().describe("LLM model for generated overlays"),
|
|
67618
67909
|
understand: external_exports.enum(["auto", "off", "required"]).optional().describe("Analyze video before generated overlay (default: auto)"),
|
|
67619
67910
|
understandingPrompt: external_exports.string().optional().describe("Custom prompt for video understanding"),
|
|
67620
67911
|
position: external_exports.enum(["full", "center", "top-left", "top-right", "bottom-left", "bottom-right"]).optional().describe("Lottie overlay position"),
|
|
@@ -67990,7 +68281,7 @@ var init_inspect = __esm({
|
|
|
67990
68281
|
outputPath: external_exports.string().optional().describe("Optional review report path. Defaults to <project>/review-report.json."),
|
|
67991
68282
|
report: external_exports.boolean().optional().describe("Write review-report.json. Default true."),
|
|
67992
68283
|
ai: external_exports.boolean().optional().describe("Also run Gemini video review and merge findings into review-report.json. Default false."),
|
|
67993
|
-
model: external_exports.enum(["flash", "flash-2.5", "pro"]).optional().describe("Gemini model variant for ai review. Default flash."),
|
|
68284
|
+
model: external_exports.enum(["flash", "latest", "flash-3", "flash-2.5", "pro", "pro-3.1"]).optional().describe("Gemini model variant for ai review. Default flash."),
|
|
67994
68285
|
dryRun: external_exports.boolean().optional().describe("Preview resolved inputs without probing video or calling Gemini.")
|
|
67995
68286
|
}),
|
|
67996
68287
|
async execute(args, ctx) {
|
|
@@ -68042,7 +68333,7 @@ var init_inspect = __esm({
|
|
|
68042
68333
|
schema: external_exports.object({
|
|
68043
68334
|
source: external_exports.string().describe("Path to image/video or YouTube URL"),
|
|
68044
68335
|
prompt: external_exports.string().describe("Analysis prompt (e.g., 'Describe the scene', 'Count people')"),
|
|
68045
|
-
model: external_exports.enum(["flash", "flash-2.5", "pro"]).optional().describe("Gemini model variant (default: flash)"),
|
|
68336
|
+
model: external_exports.enum(["flash", "latest", "flash-3", "flash-2.5", "pro", "pro-3.1"]).optional().describe("Gemini model variant (default: flash)"),
|
|
68046
68337
|
fps: external_exports.number().optional().describe("Frames per second for video sampling (default: 1)"),
|
|
68047
68338
|
start: external_exports.number().optional().describe("Start time in seconds for video analysis"),
|
|
68048
68339
|
end: external_exports.number().optional().describe("End time in seconds for video analysis"),
|
|
@@ -68070,7 +68361,7 @@ var init_inspect = __esm({
|
|
|
68070
68361
|
schema: external_exports.object({
|
|
68071
68362
|
source: external_exports.string().describe("Path to video file"),
|
|
68072
68363
|
prompt: external_exports.string().describe("Analysis prompt"),
|
|
68073
|
-
model: external_exports.enum(["flash", "flash-2.5", "pro"]).optional().describe("Gemini model variant (default: flash)"),
|
|
68364
|
+
model: external_exports.enum(["flash", "latest", "flash-3", "flash-2.5", "pro", "pro-3.1"]).optional().describe("Gemini model variant (default: flash)"),
|
|
68074
68365
|
fps: external_exports.number().optional().describe("Frames per second for sampling"),
|
|
68075
68366
|
start: external_exports.number().optional().describe("Start time in seconds"),
|
|
68076
68367
|
end: external_exports.number().optional().describe("End time in seconds"),
|
|
@@ -68100,7 +68391,7 @@ var init_inspect = __esm({
|
|
|
68100
68391
|
storyboardPath: external_exports.string().optional().describe("Path to storyboard.json for intent comparison"),
|
|
68101
68392
|
autoApply: external_exports.boolean().optional().describe("Automatically apply suggested fixes (default: false)"),
|
|
68102
68393
|
verify: external_exports.boolean().optional().describe("Re-review after applying fixes (default: false)"),
|
|
68103
|
-
model: external_exports.enum(["flash", "flash-2.5", "pro"]).optional().describe("Gemini model variant (default: flash)"),
|
|
68394
|
+
model: external_exports.enum(["flash", "latest", "flash-3", "flash-2.5", "pro", "pro-3.1"]).optional().describe("Gemini model variant (default: flash)"),
|
|
68104
68395
|
outputPath: external_exports.string().optional().describe("Output path for fixed video")
|
|
68105
68396
|
}),
|
|
68106
68397
|
async execute(args) {
|
|
@@ -68192,7 +68483,7 @@ var init_generate2 = __esm({
|
|
|
68192
68483
|
"Analyze the base video with Gemini before generating motion graphics: auto, off, or required (default: auto)"
|
|
68193
68484
|
),
|
|
68194
68485
|
understandingPrompt: external_exports.string().optional().describe("Custom prompt for video understanding when --video is provided"),
|
|
68195
|
-
model: external_exports.enum(["sonnet", "opus", "gemini", "gemini-3.1-pro"]).optional().describe("LLM model for code generation (default: sonnet)"),
|
|
68486
|
+
model: external_exports.enum(["sonnet", "opus", "gemini", "gemini-2.5-pro", "gemini-3.1-pro"]).optional().describe("LLM model for code generation (default: sonnet)"),
|
|
68196
68487
|
output: external_exports.string().optional().describe("Output path (TSX if code-only, MP4 if rendered)")
|
|
68197
68488
|
}),
|
|
68198
68489
|
async execute(args) {
|
|
@@ -68457,6 +68748,7 @@ var init_generate2 = __esm({
|
|
|
68457
68748
|
"Video provider (default: seedance when FAL_API_KEY is configured, otherwise first configured provider)"
|
|
68458
68749
|
),
|
|
68459
68750
|
image: external_exports.string().optional().describe("Reference image path for image-to-video"),
|
|
68751
|
+
endImage: external_exports.string().optional().describe("Ending frame image path for Seedance image-to-video"),
|
|
68460
68752
|
refImages: external_exports.array(external_exports.string()).optional().describe("Reference images for Seedance reference-to-video"),
|
|
68461
68753
|
refVideos: external_exports.array(external_exports.string()).optional().describe("Reference videos for Seedance reference-to-video"),
|
|
68462
68754
|
refAudio: external_exports.array(external_exports.string()).optional().describe("Reference audio files for Seedance reference-to-video"),
|
|
@@ -68464,7 +68756,7 @@ var init_generate2 = __esm({
|
|
|
68464
68756
|
ratio: external_exports.string().optional().describe("Aspect ratio: 16:9, 9:16, 1:1 (default: 16:9)"),
|
|
68465
68757
|
mode: external_exports.string().optional().describe("Kling mode: std or pro"),
|
|
68466
68758
|
negative: external_exports.string().optional().describe("Negative prompt (Seedance/Kling/Veo)"),
|
|
68467
|
-
resolution: external_exports.string().optional().describe("Resolution: 720p, 1080p, 4k
|
|
68759
|
+
resolution: external_exports.string().optional().describe("Resolution: 480p, 720p, 1080p, or 4k depending on provider"),
|
|
68468
68760
|
veoModel: external_exports.string().optional().describe("Veo model: 3.0, 3.1, 3.1-fast"),
|
|
68469
68761
|
runwayModel: external_exports.string().optional().describe("Runway model: gen4.5, gen4_turbo"),
|
|
68470
68762
|
seedanceModel: external_exports.string().optional().describe("Seedance variant: quality or fast (fal.ai only)"),
|
|
@@ -68510,10 +68802,10 @@ var init_generate2 = __esm({
|
|
|
68510
68802
|
name: "generate_video_status",
|
|
68511
68803
|
category: "generate",
|
|
68512
68804
|
cost: "free",
|
|
68513
|
-
description: "Check video generation status for Runway or
|
|
68805
|
+
description: "Check video generation status for Grok, Runway, Kling, or Veo tasks.",
|
|
68514
68806
|
schema: external_exports.object({
|
|
68515
68807
|
taskId: external_exports.string().describe("Task ID from video generation"),
|
|
68516
|
-
provider: external_exports.enum(["runway", "kling"]).optional().describe("Provider (default: runway)"),
|
|
68808
|
+
provider: external_exports.enum(["grok", "runway", "kling", "veo"]).optional().describe("Provider (default: runway)"),
|
|
68517
68809
|
taskType: external_exports.enum(["text2video", "image2video"]).optional().describe("Kling task type (default: text2video)"),
|
|
68518
68810
|
wait: external_exports.boolean().optional().describe("Wait for completion"),
|
|
68519
68811
|
output: external_exports.string().optional().describe("Download video when complete")
|
|
@@ -71702,7 +71994,7 @@ init_source();
|
|
|
71702
71994
|
// package.json
|
|
71703
71995
|
var package_default = {
|
|
71704
71996
|
name: "@vibeframe/cli",
|
|
71705
|
-
version: "0.
|
|
71997
|
+
version: "0.106.2",
|
|
71706
71998
|
description: "VibeFrame CLI - natural language video editing from the terminal",
|
|
71707
71999
|
private: false,
|
|
71708
72000
|
license: "MIT",
|
|
@@ -72801,7 +73093,14 @@ init_scene_inspect();
|
|
|
72801
73093
|
init_render_inspect();
|
|
72802
73094
|
import { readFile as readFile29, writeFile as writeFile36 } from "node:fs/promises";
|
|
72803
73095
|
import { resolve as resolve42 } from "node:path";
|
|
72804
|
-
var VALID_RENDER_AI_MODELS = [
|
|
73096
|
+
var VALID_RENDER_AI_MODELS = [
|
|
73097
|
+
"flash",
|
|
73098
|
+
"latest",
|
|
73099
|
+
"flash-3",
|
|
73100
|
+
"flash-2.5",
|
|
73101
|
+
"pro",
|
|
73102
|
+
"pro-3.1"
|
|
73103
|
+
];
|
|
72805
73104
|
var inspectCommand = new Command("inspect").description("Inspect projects, renders, and media").addHelpText(
|
|
72806
73105
|
"after",
|
|
72807
73106
|
`
|
|
@@ -72866,7 +73165,7 @@ inspectCommand.command("project").description(
|
|
|
72866
73165
|
}
|
|
72867
73166
|
});
|
|
72868
73167
|
applyTier(inspectCommand.commands[inspectCommand.commands.length - 1], "free");
|
|
72869
|
-
inspectCommand.command("render").description("Inspect a rendered project video with local checks and optional Gemini review").argument("[project-dir]", "VibeFrame project directory", ".").option("--cheap", "Run local checks only (default; no AI/API calls)").option("--ai", "Also run Gemini video review and merge findings into review-report.json").option("-m, --model <model>",
|
|
73168
|
+
inspectCommand.command("render").description("Inspect a rendered project video with local checks and optional Gemini review").argument("[project-dir]", "VibeFrame project directory", ".").option("--cheap", "Run local checks only (default; no AI/API calls)").option("--ai", "Also run Gemini video review and merge findings into review-report.json").option("-m, --model <model>", `Gemini model for --ai: ${GEMINI_TEXT_MODEL_HELP}`, "flash").option("--beat <id>", "Inspect a render for one storyboard beat").option(
|
|
72870
73169
|
"--video <path>",
|
|
72871
73170
|
"Rendered video path. Defaults to build-report outputPath or latest renders/* video."
|
|
72872
73171
|
).option(
|
|
@@ -72931,7 +73230,7 @@ inspectCommand.command("render").description("Inspect a rendered project video w
|
|
|
72931
73230
|
}
|
|
72932
73231
|
});
|
|
72933
73232
|
applyTier(inspectCommand.commands[inspectCommand.commands.length - 1], "low");
|
|
72934
|
-
inspectCommand.command("media").description("Analyze any media: images, videos, or YouTube URLs using Gemini").argument("<source>", "Image/video file path, image URL, or YouTube URL").argument("<prompt>", "Analysis prompt (e.g., 'Describe this image', 'Summarize this video')").option("-k, --api-key <key>", "Google API key (or set GOOGLE_API_KEY env)").option("-m, --model <model>",
|
|
73233
|
+
inspectCommand.command("media").description("Analyze any media: images, videos, or YouTube URLs using Gemini").argument("<source>", "Image/video file path, image URL, or YouTube URL").argument("<prompt>", "Analysis prompt (e.g., 'Describe this image', 'Summarize this video')").option("-k, --api-key <key>", "Google API key (or set GOOGLE_API_KEY env)").option("-m, --model <model>", `Model: ${GEMINI_TEXT_MODEL_HELP}`, "flash").option("--fps <number>", "Frames per second for video (default: 1)").option("--start <seconds>", "Start offset in seconds (video only)").option("--end <seconds>", "End offset in seconds (video only)").option("--low-res", "Use low resolution mode (fewer tokens)").option("--verbose", "Show token usage").option("--fields <fields>", "Comma-separated fields to include in output (e.g., response,model)").option("--dry-run", "Preview parameters without executing").action(async (source, prompt3, options) => {
|
|
72935
73234
|
const startedAt = Date.now();
|
|
72936
73235
|
try {
|
|
72937
73236
|
rejectControlChars(prompt3);
|
|
@@ -73034,14 +73333,17 @@ function printInspectSummary(title, status, score, issues, reportPath) {
|
|
|
73034
73333
|
}
|
|
73035
73334
|
}
|
|
73036
73335
|
function parseRenderAiModel(value) {
|
|
73037
|
-
if (
|
|
73336
|
+
if (isGeminiTextModelAlias(value) || value.startsWith("gemini-")) {
|
|
73038
73337
|
return value;
|
|
73039
73338
|
}
|
|
73040
73339
|
exitWithError(
|
|
73041
|
-
usageError(
|
|
73340
|
+
usageError(
|
|
73341
|
+
`Invalid --model: ${value}`,
|
|
73342
|
+
`Must be one of: ${VALID_RENDER_AI_MODELS.join(", ")}, or a full gemini-* model ID`
|
|
73343
|
+
)
|
|
73042
73344
|
);
|
|
73043
73345
|
}
|
|
73044
|
-
inspectCommand.command("video", { hidden: true }).description("Analyze video using Gemini (summarize, Q&A, extract info)").argument("<source>", "Video file path or YouTube URL").argument("<prompt>", "Analysis prompt (e.g., 'Summarize this video')").option("-k, --api-key <key>", "Google API key (or set GOOGLE_API_KEY env)").option("-m, --model <model>",
|
|
73346
|
+
inspectCommand.command("video", { hidden: true }).description("Analyze video using Gemini (summarize, Q&A, extract info)").argument("<source>", "Video file path or YouTube URL").argument("<prompt>", "Analysis prompt (e.g., 'Summarize this video')").option("-k, --api-key <key>", "Google API key (or set GOOGLE_API_KEY env)").option("-m, --model <model>", `Model: ${GEMINI_TEXT_MODEL_HELP}`, "flash").option("--fps <number>", "Frames per second (default: 1, higher for action)").option("--start <seconds>", "Start offset in seconds (for clipping)").option("--end <seconds>", "End offset in seconds (for clipping)").option("--low-res", "Use low resolution mode (fewer tokens, longer videos)").option("--verbose", "Show token usage").option("--fields <fields>", "Comma-separated fields to include in output (e.g., response,model)").option("--dry-run", "Preview parameters without executing").action(async (source, prompt3, options) => {
|
|
73045
73347
|
const startedAt = Date.now();
|
|
73046
73348
|
try {
|
|
73047
73349
|
rejectControlChars(prompt3);
|