vargai 0.4.0-alpha15 → 0.4.0-alpha17
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/package.json +1 -1
- package/src/ai-sdk/cache.ts +1 -1
- package/src/cli/commands/find.tsx +1 -0
- package/src/cli/commands/help.tsx +1 -4
- package/src/cli/commands/index.ts +1 -1
- package/src/cli/commands/list.tsx +1 -0
- package/src/cli/commands/render.ts +108 -89
- package/src/cli/commands/run.tsx +1 -0
- package/src/cli/commands/which.tsx +1 -0
- package/src/cli/index.ts +4 -0
- package/src/cli/ui/components/Badge.tsx +1 -0
- package/src/cli/ui/components/DataTable.tsx +1 -0
- package/src/cli/ui/components/Header.tsx +1 -0
- package/src/cli/ui/components/HelpBlock.tsx +1 -0
- package/src/cli/ui/components/KeyValue.tsx +1 -0
- package/src/cli/ui/components/OptionRow.tsx +1 -0
- package/src/cli/ui/components/Separator.tsx +1 -0
- package/src/cli/ui/components/StatusBox.tsx +1 -0
- package/src/cli/ui/components/VargBox.tsx +1 -0
- package/src/cli/ui/components/VargProgress.tsx +1 -0
- package/src/cli/ui/components/VargSpinner.tsx +1 -0
- package/src/cli/ui/components/VargText.tsx +1 -0
- package/src/react/examples/mcmeows.tsx +40 -0
- package/src/react/examples/music-defaults.tsx +24 -0
- package/src/react/renderers/music.ts +1 -1
- package/src/react/renderers/progress.ts +1 -1
- package/src/react/renderers/render.ts +2 -2
package/package.json
CHANGED
package/src/ai-sdk/cache.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { findCmd, showFindHelp } from "./find.tsx";
|
|
2
2
|
export { helpCmd, showHelp } from "./help.tsx";
|
|
3
3
|
export { listCmd, showListHelp } from "./list.tsx";
|
|
4
|
-
export { renderCmd } from "./render.ts";
|
|
4
|
+
export { fastCmd, previewCmd, renderCmd } from "./render.ts";
|
|
5
5
|
export { runCmd, showRunHelp, showTargetHelp } from "./run.tsx";
|
|
6
6
|
export { studioCmd } from "./studio.ts";
|
|
7
7
|
export { showWhichHelp, whichCmd } from "./which.tsx";
|
|
@@ -65,100 +65,119 @@ async function loadComponent(filePath: string): Promise<VargElement> {
|
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
const sharedArgs = {
|
|
69
|
+
file: {
|
|
70
|
+
type: "positional" as const,
|
|
71
|
+
description: "component file (.tsx)",
|
|
72
|
+
required: true,
|
|
73
|
+
},
|
|
74
|
+
output: {
|
|
75
|
+
type: "string" as const,
|
|
76
|
+
alias: "o",
|
|
77
|
+
description: "output path",
|
|
78
|
+
},
|
|
79
|
+
cache: {
|
|
80
|
+
type: "string" as const,
|
|
81
|
+
alias: "c",
|
|
82
|
+
description: "cache directory",
|
|
83
|
+
default: ".cache/ai",
|
|
84
|
+
},
|
|
85
|
+
quiet: {
|
|
86
|
+
type: "boolean" as const,
|
|
87
|
+
alias: "q",
|
|
88
|
+
description: "minimal output",
|
|
89
|
+
default: false,
|
|
90
|
+
},
|
|
91
|
+
"no-cache": {
|
|
92
|
+
type: "boolean" as const,
|
|
93
|
+
description: "disable cache (don't read or write)",
|
|
94
|
+
default: false,
|
|
95
|
+
},
|
|
96
|
+
verbose: {
|
|
97
|
+
type: "boolean" as const,
|
|
98
|
+
alias: "v",
|
|
99
|
+
description: "show ffmpeg commands",
|
|
100
|
+
default: false,
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
async function runRender(
|
|
105
|
+
args: Record<string, unknown>,
|
|
106
|
+
mode: RenderMode,
|
|
107
|
+
commandName: string,
|
|
108
|
+
) {
|
|
109
|
+
const file = args.file as string;
|
|
110
|
+
|
|
111
|
+
if (!file) {
|
|
112
|
+
console.error(`usage: varg ${commandName} <component.tsx> [-o output.mp4]`);
|
|
113
|
+
process.exit(1);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const component = await loadComponent(file);
|
|
117
|
+
|
|
118
|
+
if (!component || component.type !== "render") {
|
|
119
|
+
console.error("error: default export must be a <Render> element");
|
|
120
|
+
process.exit(1);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const basename = file
|
|
124
|
+
.replace(/\.tsx?$/, "")
|
|
125
|
+
.split("/")
|
|
126
|
+
.pop();
|
|
127
|
+
const outputPath = (args.output as string) ?? `output/${basename}.mp4`;
|
|
128
|
+
|
|
129
|
+
if (!args.quiet) {
|
|
130
|
+
const modeLabel =
|
|
131
|
+
mode === "preview" ? " (fast)" : mode === "strict" ? "" : " (preview)";
|
|
132
|
+
console.log(`rendering ${file} → ${outputPath}${modeLabel}`);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const useCache = !args["no-cache"] && mode !== "preview";
|
|
136
|
+
|
|
137
|
+
const defaults = await detectDefaultModels();
|
|
138
|
+
|
|
139
|
+
const buffer = await render(component, {
|
|
140
|
+
output: outputPath,
|
|
141
|
+
cache: useCache ? (args.cache as string) : undefined,
|
|
142
|
+
mode,
|
|
143
|
+
defaults,
|
|
144
|
+
verbose: args.verbose as boolean,
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
if (!args.quiet) {
|
|
148
|
+
console.log(`done! ${buffer.byteLength} bytes → ${outputPath}`);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
68
152
|
export const renderCmd = defineCommand({
|
|
69
153
|
meta: {
|
|
70
154
|
name: "render",
|
|
71
|
-
description: "render
|
|
155
|
+
description: "render to video (strict mode - fails on errors)",
|
|
72
156
|
},
|
|
73
|
-
args:
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
default: false,
|
|
95
|
-
},
|
|
96
|
-
strict: {
|
|
97
|
-
type: "boolean",
|
|
98
|
-
description: "fail on provider errors (no fallback)",
|
|
99
|
-
default: false,
|
|
100
|
-
},
|
|
101
|
-
preview: {
|
|
102
|
-
type: "boolean",
|
|
103
|
-
description: "skip all generation, use placeholders only",
|
|
104
|
-
default: false,
|
|
105
|
-
},
|
|
106
|
-
"no-cache": {
|
|
107
|
-
type: "boolean",
|
|
108
|
-
description: "disable cache (don't read or write)",
|
|
109
|
-
default: false,
|
|
110
|
-
},
|
|
157
|
+
args: sharedArgs,
|
|
158
|
+
async run({ args }) {
|
|
159
|
+
await runRender(args, "strict", "render");
|
|
160
|
+
},
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
export const previewCmd = defineCommand({
|
|
164
|
+
meta: {
|
|
165
|
+
name: "preview",
|
|
166
|
+
description: "render with fallback placeholders on errors",
|
|
167
|
+
},
|
|
168
|
+
args: sharedArgs,
|
|
169
|
+
async run({ args }) {
|
|
170
|
+
await runRender(args, "default", "preview");
|
|
171
|
+
},
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
export const fastCmd = defineCommand({
|
|
175
|
+
meta: {
|
|
176
|
+
name: "fast",
|
|
177
|
+
description: "render with all placeholders (no generation)",
|
|
111
178
|
},
|
|
179
|
+
args: sharedArgs,
|
|
112
180
|
async run({ args }) {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
if (!file) {
|
|
116
|
-
console.error("usage: varg render <component.tsx> [-o output.mp4]");
|
|
117
|
-
process.exit(1);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
const component = await loadComponent(file);
|
|
121
|
-
|
|
122
|
-
if (!component || component.type !== "render") {
|
|
123
|
-
console.error("error: default export must be a <Render> element");
|
|
124
|
-
process.exit(1);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
const basename = file
|
|
128
|
-
.replace(/\.tsx?$/, "")
|
|
129
|
-
.split("/")
|
|
130
|
-
.pop();
|
|
131
|
-
const outputPath = args.output ?? `output/${basename}.mp4`;
|
|
132
|
-
|
|
133
|
-
const mode: RenderMode = args.strict
|
|
134
|
-
? "strict"
|
|
135
|
-
: args.preview
|
|
136
|
-
? "preview"
|
|
137
|
-
: "default";
|
|
138
|
-
|
|
139
|
-
if (!args.quiet) {
|
|
140
|
-
const modeLabel =
|
|
141
|
-
mode === "preview"
|
|
142
|
-
? " (preview)"
|
|
143
|
-
: mode === "strict"
|
|
144
|
-
? " (strict)"
|
|
145
|
-
: "";
|
|
146
|
-
console.log(`rendering ${file} → ${outputPath}${modeLabel}`);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
const useCache = !args["no-cache"] && mode !== "preview";
|
|
150
|
-
|
|
151
|
-
const defaults = await detectDefaultModels();
|
|
152
|
-
|
|
153
|
-
const buffer = await render(component, {
|
|
154
|
-
output: outputPath,
|
|
155
|
-
cache: useCache ? args.cache : undefined,
|
|
156
|
-
mode,
|
|
157
|
-
defaults,
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
if (!args.quiet) {
|
|
161
|
-
console.log(`done! ${buffer.byteLength} bytes → ${outputPath}`);
|
|
162
|
-
}
|
|
181
|
+
await runRender(args, "preview", "fast");
|
|
163
182
|
},
|
|
164
183
|
});
|
package/src/cli/commands/run.tsx
CHANGED
package/src/cli/index.ts
CHANGED
|
@@ -12,9 +12,11 @@ import { defineCommand, runMain } from "citty";
|
|
|
12
12
|
import { registry } from "../core/registry";
|
|
13
13
|
import { allDefinitions } from "../definitions";
|
|
14
14
|
import {
|
|
15
|
+
fastCmd,
|
|
15
16
|
findCmd,
|
|
16
17
|
helpCmd,
|
|
17
18
|
listCmd,
|
|
19
|
+
previewCmd,
|
|
18
20
|
renderCmd,
|
|
19
21
|
runCmd,
|
|
20
22
|
showFindHelp,
|
|
@@ -104,6 +106,8 @@ const main = defineCommand({
|
|
|
104
106
|
subCommands: {
|
|
105
107
|
run: runCmd,
|
|
106
108
|
render: renderCmd,
|
|
109
|
+
preview: previewCmd,
|
|
110
|
+
fast: fastCmd,
|
|
107
111
|
studio: studioCmd,
|
|
108
112
|
list: listCmd,
|
|
109
113
|
ls: listCmd,
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { elevenlabs } from "../../ai-sdk/providers/elevenlabs";
|
|
2
|
+
import { fal } from "../../ai-sdk/providers/fal";
|
|
3
|
+
import { Clip, Music, Render, render, Title, Video } from "..";
|
|
4
|
+
|
|
5
|
+
export default (
|
|
6
|
+
<Render>
|
|
7
|
+
<Clip duration={4}>
|
|
8
|
+
<Video prompt="A sophisticated tabby cat wearing a tailored tiny business suit and small round glasses, standing upright at a McDonald's counter. One paw raised pointing assertively at the illuminated menu board above. The cat has an extremely serious, concentrated expression with furrowed brows. Cinematic lighting with warm McDonald's interior ambiance, shallow depth of field focusing on the cat's determined face, photorealistic fur texture with fine detail. Professional business atmosphere meets fast food chaos." />
|
|
9
|
+
</Clip>
|
|
10
|
+
|
|
11
|
+
<Clip duration={4}>
|
|
12
|
+
<Video prompt="Absolute mayhem - four to five cats in a chaotic pile fight. Orange tabby, black and white tuxedo cat, calico with patches, and fluffy gray cat all scrambling, paws flailing, tumbling over each other in exaggerated cartoon-style motion. They're all desperately reaching for a single perfect golden McDonald's french fry sitting on a red plastic tray in the center. Wide-eyed expressions, mouths open mid-meow, dynamic motion blur, comedic timing. Fast food restaurant background slightly blurred. Playful, over-the-top energy." />
|
|
13
|
+
</Clip>
|
|
14
|
+
|
|
15
|
+
<Clip duration={3}>
|
|
16
|
+
<Video prompt="Proud orange tabby cat wearing an official McDonald's crew member visor and name tag, standing upright behind a restaurant register counter. Front paws crossed confidently across chest, chin lifted with a smug, self-satisfied expression. Perfect posture, professional demeanor. Bright McDonald's interior lighting, red and yellow color scheme in background. The cat radiates 'employee of the month' energy. Crisp, clean, professional fast food aesthetic." />
|
|
17
|
+
<Title position="bottom">McMeow's: NOW HIRING</Title>
|
|
18
|
+
</Clip>
|
|
19
|
+
|
|
20
|
+
<Music
|
|
21
|
+
model={elevenlabs.musicModel()}
|
|
22
|
+
prompt="playful upbeat comedy music with quirky pizzicato strings and light percussion, funny corporate training video vibes"
|
|
23
|
+
duration={11}
|
|
24
|
+
/>
|
|
25
|
+
</Render>
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
async function main() {
|
|
29
|
+
const component = await import("./mcmeows.tsx").then((m) => m.default);
|
|
30
|
+
await render(component, {
|
|
31
|
+
output: "output/mcmeows.mp4",
|
|
32
|
+
cache: ".cache/ai",
|
|
33
|
+
verbose: true,
|
|
34
|
+
defaults: {
|
|
35
|
+
video: fal.videoModel("wan-2.5"),
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
main().catch(console.error);
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { elevenlabs } from "../../ai-sdk/providers/elevenlabs";
|
|
2
|
+
import { Clip, Image, Music, Render, render } from "..";
|
|
3
|
+
|
|
4
|
+
export default (
|
|
5
|
+
<Render width={1920} height={1080}>
|
|
6
|
+
<Clip duration={5}>
|
|
7
|
+
<Image src="media/cyberpunk-street.png" />
|
|
8
|
+
</Clip>
|
|
9
|
+
<Music prompt="calm ambient electronic music" duration={5} />
|
|
10
|
+
</Render>
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
async function main() {
|
|
14
|
+
const component = await import("./music-defaults.tsx").then((m) => m.default);
|
|
15
|
+
await render(component, {
|
|
16
|
+
output: "output/music-defaults.mp4",
|
|
17
|
+
defaults: {
|
|
18
|
+
music: elevenlabs.musicModel(),
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
console.log("done! check output/music-defaults.mp4");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
main().catch(console.error);
|
|
@@ -22,7 +22,7 @@ export async function renderMusic(
|
|
|
22
22
|
duration: props.duration,
|
|
23
23
|
});
|
|
24
24
|
|
|
25
|
-
const modelId = model.modelId;
|
|
25
|
+
const modelId = model.modelId ?? "music";
|
|
26
26
|
const taskId = ctx.progress ? addTask(ctx.progress, "music", modelId) : null;
|
|
27
27
|
|
|
28
28
|
const generateFn = async () => {
|
|
@@ -103,7 +103,7 @@ export function completeTask(tracker: ProgressTracker, id: string): void {
|
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
function getEstimate(task: ProgressTask): number {
|
|
106
|
-
const modelLower = task.model
|
|
106
|
+
const modelLower = task.model?.toLowerCase() ?? "";
|
|
107
107
|
for (const [key, estimate] of Object.entries(MODEL_TIME_ESTIMATES)) {
|
|
108
108
|
if (modelLower.includes(key.toLowerCase())) {
|
|
109
109
|
return estimate;
|
|
@@ -269,11 +269,11 @@ export async function renderRoot(
|
|
|
269
269
|
let path: string;
|
|
270
270
|
if (musicProps.src) {
|
|
271
271
|
path = resolvePath(musicProps.src);
|
|
272
|
-
} else if (musicProps.prompt
|
|
272
|
+
} else if (musicProps.prompt) {
|
|
273
273
|
const result = await renderMusic(musicElement, ctx);
|
|
274
274
|
path = result.path;
|
|
275
275
|
} else {
|
|
276
|
-
throw new Error("Music requires either src or prompt
|
|
276
|
+
throw new Error("Music requires either src or prompt");
|
|
277
277
|
}
|
|
278
278
|
|
|
279
279
|
audioTracks.push({
|