@vibeo/cli 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/create.d.ts +6 -1
- package/dist/commands/create.d.ts.map +1 -1
- package/dist/commands/create.js +18 -107
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/list.d.ts +9 -5
- package/dist/commands/list.d.ts.map +1 -1
- package/dist/commands/list.js +2 -77
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/preview.d.ts +1 -4
- package/dist/commands/preview.d.ts.map +1 -1
- package/dist/commands/preview.js +1 -57
- package/dist/commands/preview.js.map +1 -1
- package/dist/commands/render.d.ts +17 -4
- package/dist/commands/render.d.ts.map +1 -1
- package/dist/commands/render.js +22 -154
- package/dist/commands/render.js.map +1 -1
- package/dist/index.js +103 -57
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
- package/src/commands/create.ts +19 -122
- package/src/commands/list.ts +2 -98
- package/src/commands/preview.ts +1 -66
- package/src/commands/render.ts +26 -149
- package/src/index.ts +104 -57
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/commands/render.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/commands/render.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAerE,SAAS,UAAU,CAAC,EAAU;IAC5B,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;IACtC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;IACzC,MAAM,CAAC,GAAG,OAAO,GAAG,EAAE,CAAC;IACvB,OAAO,GAAG,OAAO,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;AACpD,CAAC;AAED,SAAS,iBAAiB,CAAC,QAAwB;IACjD,MAAM,EAAE,cAAc,EAAE,WAAW,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,QAAQ,CAAC;IACjE,MAAM,QAAQ,GAAG,EAAE,CAAC;IACpB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,OAAO,CAAC,CAAC;IAC9C,MAAM,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IAChC,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC7D,MAAM,GAAG,GAAG,CAAC,OAAO,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IACvC,MAAM,GAAG,GAAG,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,QAAQ,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAE9D,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,QAAQ,GAAG,KAAK,GAAG,MAAM,cAAc,IAAI,WAAW,IAAI,GAAG,IAAI,CAClE,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,IAAmB;IAEnB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;IACpF,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM;QACxB,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC;QACtB,CAAC,CAAC,OAAO,CAAC,OAAO,IAAI,CAAC,WAAW,IAAI,GAAG,EAAE,CAAC,CAAC;IAE9C,OAAO,CAAC,GAAG,CAAC,4BAA4B,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC;IAC7D,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;IACtC,OAAO,CAAC,GAAG,CAAC,aAAa,MAAM,EAAE,CAAC,CAAC;IACnC,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;IACtC,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;IAClD,OAAO,CAAC,GAAG,EAAE,CAAC;IAEd,MAAM,eAAe,GAAG;QACtB,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,IAAI;QACZ,GAAG,EAAE,IAAI,CAAC,GAAG,IAAI,EAAE;QACnB,gBAAgB,EAAE,GAAG;KACtB,CAAC;IAEF,MAAM,UAAU,GAAG,eAAe,CAAC,IAAI,CAAC,MAAM,EAAE,eAAe,CAAC,gBAAgB,CAAC,CAAC;IAClF,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAE7B,MAAM,iBAAiB,CACrB;QACE,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,aAAa,EAAE,IAAI,CAAC,WAAW;QAC/B,UAAU,EAAE,MAAM;QAClB,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,UAAU;QACV,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,WAAW,EAAE,SAAS;QACtB,UAAU,EAAE,iBAAiB;KAC9B,EACD,eAAe,CAChB,CAAC;IAEF,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,CAAC;IACnD,OAAO,CAAC,GAAG,CAAC,eAAe,OAAO,aAAa,MAAM,EAAE,CAAC,CAAC;IACzD,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;AAC7B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,59 +1,105 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
list List registered compositions
|
|
19
|
-
|
|
20
|
-
Options:
|
|
21
|
-
--help Show help for a command
|
|
22
|
-
|
|
23
|
-
Examples:
|
|
24
|
-
vibeo create my-video
|
|
25
|
-
vibeo create music-viz --template audio-reactive
|
|
26
|
-
vibeo render --entry src/index.tsx --composition MyComp --output out.mp4
|
|
27
|
-
vibeo preview --entry src/index.tsx
|
|
28
|
-
vibeo list --entry src/index.tsx
|
|
29
|
-
`);
|
|
30
|
-
}
|
|
31
|
-
async function main() {
|
|
32
|
-
if (!command || command === "--help" || command === "-h") {
|
|
33
|
-
printUsage();
|
|
34
|
-
process.exit(0);
|
|
35
|
-
}
|
|
36
|
-
switch (command) {
|
|
37
|
-
case "create":
|
|
38
|
-
await createCommand(args.slice(1));
|
|
39
|
-
break;
|
|
40
|
-
case "render":
|
|
41
|
-
await renderCommand(args.slice(1));
|
|
42
|
-
break;
|
|
43
|
-
case "preview":
|
|
44
|
-
await previewCommand(args.slice(1));
|
|
45
|
-
break;
|
|
46
|
-
case "list":
|
|
47
|
-
await listCommand(args.slice(1));
|
|
48
|
-
break;
|
|
49
|
-
default:
|
|
50
|
-
console.error(`Unknown command: ${command}`);
|
|
51
|
-
printUsage();
|
|
52
|
-
process.exit(1);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
main().catch((err) => {
|
|
56
|
-
console.error(err);
|
|
57
|
-
process.exit(1);
|
|
1
|
+
import { Cli, z } from "incur";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import { availableParallelism } from "node:os";
|
|
4
|
+
import { createProject } from "./commands/create.js";
|
|
5
|
+
import { startPreview } from "./commands/preview.js";
|
|
6
|
+
import { listCompositions } from "./commands/list.js";
|
|
7
|
+
import { renderVideo } from "./commands/render.js";
|
|
8
|
+
const cli = Cli.create("vibeo", {
|
|
9
|
+
description: "React-based programmatic video framework CLI",
|
|
10
|
+
sync: {
|
|
11
|
+
suggestions: [
|
|
12
|
+
"create a new video project",
|
|
13
|
+
"preview a composition in the browser",
|
|
14
|
+
"render a composition to video",
|
|
15
|
+
"list all registered compositions",
|
|
16
|
+
],
|
|
17
|
+
},
|
|
58
18
|
});
|
|
19
|
+
cli.command("create", {
|
|
20
|
+
description: "Create a new Vibeo project from a template",
|
|
21
|
+
args: z.object({
|
|
22
|
+
name: z.string().describe("Project directory name"),
|
|
23
|
+
}),
|
|
24
|
+
options: z.object({
|
|
25
|
+
template: z
|
|
26
|
+
.enum(["basic", "audio-reactive", "transitions", "subtitles"])
|
|
27
|
+
.default("basic")
|
|
28
|
+
.describe("Template to scaffold from"),
|
|
29
|
+
}),
|
|
30
|
+
examples: [
|
|
31
|
+
{ args: { name: "my-video" }, description: "Create with basic template" },
|
|
32
|
+
{ args: { name: "viz" }, options: { template: "audio-reactive" }, description: "Create with audio-reactive template" },
|
|
33
|
+
],
|
|
34
|
+
async run(c) {
|
|
35
|
+
return await createProject(c.args.name, c.options.template);
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
cli.command("preview", {
|
|
39
|
+
description: "Start a dev server with live preview in the browser",
|
|
40
|
+
options: z.object({
|
|
41
|
+
entry: z.string().describe("Path to the root file with compositions"),
|
|
42
|
+
port: z.number().default(3000).describe("Port for the dev server"),
|
|
43
|
+
}),
|
|
44
|
+
examples: [
|
|
45
|
+
{ options: { entry: "src/index.tsx" }, description: "Preview on default port" },
|
|
46
|
+
],
|
|
47
|
+
async run(c) {
|
|
48
|
+
await startPreview(resolve(c.options.entry), c.options.port);
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
cli.command("render", {
|
|
52
|
+
description: "Render a composition to a video file",
|
|
53
|
+
options: z.object({
|
|
54
|
+
entry: z.string().describe("Path to the root file with compositions"),
|
|
55
|
+
composition: z.string().describe("Composition ID to render"),
|
|
56
|
+
output: z.string().optional().describe("Output file path (default: out/<id>.mp4)"),
|
|
57
|
+
fps: z.number().optional().describe("Override frames per second"),
|
|
58
|
+
frames: z.string().optional().describe('Frame range, e.g. "0-100" or "50"'),
|
|
59
|
+
codec: z
|
|
60
|
+
.enum(["h264", "h265", "vp9", "prores"])
|
|
61
|
+
.default("h264")
|
|
62
|
+
.describe("Video codec"),
|
|
63
|
+
concurrency: z
|
|
64
|
+
.number()
|
|
65
|
+
.default(Math.max(1, Math.floor(availableParallelism() / 2)))
|
|
66
|
+
.describe("Number of parallel browser tabs"),
|
|
67
|
+
imageFormat: z
|
|
68
|
+
.enum(["png", "jpeg"])
|
|
69
|
+
.default("png")
|
|
70
|
+
.describe("Intermediate frame image format"),
|
|
71
|
+
quality: z.number().default(80).describe("JPEG quality / CRF value (0-100)"),
|
|
72
|
+
}),
|
|
73
|
+
examples: [
|
|
74
|
+
{ options: { entry: "src/index.tsx", composition: "MyComp" }, description: "Render with defaults" },
|
|
75
|
+
{ options: { entry: "src/index.tsx", composition: "MyComp", codec: "vp9", frames: "0-100" }, description: "Render a frame range as WebM" },
|
|
76
|
+
],
|
|
77
|
+
async run(c) {
|
|
78
|
+
return await renderVideo({
|
|
79
|
+
entry: resolve(c.options.entry),
|
|
80
|
+
composition: c.options.composition,
|
|
81
|
+
output: c.options.output,
|
|
82
|
+
fps: c.options.fps ?? null,
|
|
83
|
+
frames: c.options.frames ?? null,
|
|
84
|
+
codec: c.options.codec,
|
|
85
|
+
concurrency: c.options.concurrency,
|
|
86
|
+
imageFormat: c.options.imageFormat,
|
|
87
|
+
quality: c.options.quality,
|
|
88
|
+
});
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
cli.command("list", {
|
|
92
|
+
description: "List registered compositions in an entry file",
|
|
93
|
+
options: z.object({
|
|
94
|
+
entry: z.string().describe("Path to the root file with compositions"),
|
|
95
|
+
}),
|
|
96
|
+
examples: [
|
|
97
|
+
{ options: { entry: "src/index.tsx" }, description: "List all compositions" },
|
|
98
|
+
],
|
|
99
|
+
async run(c) {
|
|
100
|
+
const compositions = await listCompositions(resolve(c.options.entry));
|
|
101
|
+
return { compositions };
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
cli.serve();
|
|
59
105
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibeo/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -14,10 +14,11 @@
|
|
|
14
14
|
}
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
+
"@vibeo/audio": "0.1.0",
|
|
17
18
|
"@vibeo/core": "0.1.0",
|
|
18
|
-
"@vibeo/renderer": "0.1.0",
|
|
19
19
|
"@vibeo/player": "0.1.0",
|
|
20
|
-
"@vibeo/
|
|
20
|
+
"@vibeo/renderer": "0.1.0",
|
|
21
|
+
"incur": "^0.3.13"
|
|
21
22
|
},
|
|
22
23
|
"files": [
|
|
23
24
|
"bin",
|
package/src/commands/create.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { mkdir, writeFile } from "node:fs/promises";
|
|
|
3
3
|
import { existsSync } from "node:fs";
|
|
4
4
|
|
|
5
5
|
// ---------------------------------------------------------------------------
|
|
6
|
-
// Embedded templates
|
|
6
|
+
// Embedded templates
|
|
7
7
|
// ---------------------------------------------------------------------------
|
|
8
8
|
|
|
9
9
|
const TEMPLATE_BASIC = `import React from "react";
|
|
@@ -214,112 +214,31 @@ export function Root() {
|
|
|
214
214
|
// ---------------------------------------------------------------------------
|
|
215
215
|
|
|
216
216
|
const TEMPLATES: Record<string, { description: string; source: string }> = {
|
|
217
|
-
basic: {
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
},
|
|
221
|
-
"audio-reactive": {
|
|
222
|
-
description: "Audio visualization with frequency bars and amplitude-driven effects",
|
|
223
|
-
source: TEMPLATE_AUDIO_REACTIVE,
|
|
224
|
-
},
|
|
225
|
-
transitions: {
|
|
226
|
-
description: "Scene transitions (fade, slide) between multiple scenes",
|
|
227
|
-
source: TEMPLATE_TRANSITIONS,
|
|
228
|
-
},
|
|
229
|
-
subtitles: {
|
|
230
|
-
description: "Video with SRT subtitle overlay",
|
|
231
|
-
source: TEMPLATE_SUBTITLES,
|
|
232
|
-
},
|
|
217
|
+
basic: { description: "Minimal composition with text animation and two scenes", source: TEMPLATE_BASIC },
|
|
218
|
+
"audio-reactive": { description: "Audio visualization with frequency bars", source: TEMPLATE_AUDIO_REACTIVE },
|
|
219
|
+
transitions: { description: "Scene transitions (fade, slide)", source: TEMPLATE_TRANSITIONS },
|
|
220
|
+
subtitles: { description: "Video with SRT subtitle overlay", source: TEMPLATE_SUBTITLES },
|
|
233
221
|
};
|
|
234
222
|
|
|
235
|
-
|
|
236
|
-
name: string;
|
|
237
|
-
template: string;
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
function parseArgs(args: string[]): CreateArgs {
|
|
241
|
-
const result: CreateArgs = { name: "", template: "basic" };
|
|
242
|
-
|
|
243
|
-
for (let i = 0; i < args.length; i++) {
|
|
244
|
-
const arg = args[i]!;
|
|
245
|
-
const next = args[i + 1];
|
|
246
|
-
|
|
247
|
-
if (arg === "--template" && next) {
|
|
248
|
-
result.template = next;
|
|
249
|
-
i++;
|
|
250
|
-
} else if (arg.startsWith("--template=")) {
|
|
251
|
-
result.template = arg.slice("--template=".length);
|
|
252
|
-
} else if (arg === "--help" || arg === "-h") {
|
|
253
|
-
printHelp();
|
|
254
|
-
process.exit(0);
|
|
255
|
-
} else if (!arg.startsWith("-") && !result.name) {
|
|
256
|
-
result.name = arg;
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
return result;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
function printHelp(): void {
|
|
264
|
-
console.log(`
|
|
265
|
-
vibeo create - Create a new Vibeo project
|
|
266
|
-
|
|
267
|
-
Usage:
|
|
268
|
-
vibeo create <project-name> [options]
|
|
269
|
-
|
|
270
|
-
Options:
|
|
271
|
-
--template <name> Template to use (default: basic)
|
|
272
|
-
--help Show this help
|
|
273
|
-
|
|
274
|
-
Templates:`);
|
|
223
|
+
export const TEMPLATE_NAMES = Object.keys(TEMPLATES);
|
|
275
224
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
225
|
+
export async function createProject(
|
|
226
|
+
name: string,
|
|
227
|
+
template: string,
|
|
228
|
+
): Promise<{ project: string; template: string; files: string[] }> {
|
|
229
|
+
const tmpl = TEMPLATES[template];
|
|
230
|
+
if (!tmpl) throw new Error(`Unknown template: ${template}`);
|
|
279
231
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
vibeo create my-video
|
|
283
|
-
vibeo create music-viz --template audio-reactive
|
|
284
|
-
vibeo create intro --template transitions
|
|
285
|
-
`);
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
export async function createCommand(args: string[]): Promise<void> {
|
|
289
|
-
const parsed = parseArgs(args);
|
|
290
|
-
|
|
291
|
-
if (!parsed.name) {
|
|
292
|
-
console.error("Error: project name is required\n");
|
|
293
|
-
printHelp();
|
|
294
|
-
process.exit(1);
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
const template = TEMPLATES[parsed.template];
|
|
298
|
-
if (!template) {
|
|
299
|
-
console.error(`Error: unknown template "${parsed.template}"`);
|
|
300
|
-
console.error(`Available: ${Object.keys(TEMPLATES).join(", ")}`);
|
|
301
|
-
process.exit(1);
|
|
302
|
-
}
|
|
232
|
+
const projectDir = resolve(name);
|
|
233
|
+
if (existsSync(projectDir)) throw new Error(`Directory "${name}" already exists`);
|
|
303
234
|
|
|
304
|
-
const projectDir = resolve(parsed.name);
|
|
305
|
-
if (existsSync(projectDir)) {
|
|
306
|
-
console.error(`Error: directory "${parsed.name}" already exists`);
|
|
307
|
-
process.exit(1);
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
console.log(`\nCreating Vibeo project: ${parsed.name}`);
|
|
311
|
-
console.log(`Template: ${parsed.template}\n`);
|
|
312
|
-
|
|
313
|
-
// Create project structure
|
|
314
235
|
await mkdir(join(projectDir, "src"), { recursive: true });
|
|
315
236
|
await mkdir(join(projectDir, "public"), { recursive: true });
|
|
316
237
|
|
|
317
|
-
|
|
318
|
-
await writeFile(join(projectDir, "src", "index.tsx"), template.source);
|
|
238
|
+
await writeFile(join(projectDir, "src", "index.tsx"), tmpl.source);
|
|
319
239
|
|
|
320
|
-
// Write package.json
|
|
321
240
|
const pkg = {
|
|
322
|
-
name
|
|
241
|
+
name,
|
|
323
242
|
version: "0.0.1",
|
|
324
243
|
private: true,
|
|
325
244
|
type: "module",
|
|
@@ -347,7 +266,6 @@ export async function createCommand(args: string[]): Promise<void> {
|
|
|
347
266
|
};
|
|
348
267
|
await writeFile(join(projectDir, "package.json"), JSON.stringify(pkg, null, 2) + "\n");
|
|
349
268
|
|
|
350
|
-
// Write tsconfig.json
|
|
351
269
|
const tsconfig = {
|
|
352
270
|
compilerOptions: {
|
|
353
271
|
target: "ES2022",
|
|
@@ -366,29 +284,8 @@ export async function createCommand(args: string[]): Promise<void> {
|
|
|
366
284
|
};
|
|
367
285
|
await writeFile(join(projectDir, "tsconfig.json"), JSON.stringify(tsconfig, null, 2) + "\n");
|
|
368
286
|
|
|
369
|
-
|
|
370
|
-
await writeFile(
|
|
371
|
-
join(projectDir, ".gitignore"),
|
|
372
|
-
`node_modules/
|
|
373
|
-
dist/
|
|
374
|
-
out/
|
|
375
|
-
*.tmp
|
|
376
|
-
.DS_Store
|
|
377
|
-
`,
|
|
378
|
-
);
|
|
287
|
+
await writeFile(join(projectDir, ".gitignore"), "node_modules/\ndist/\nout/\n*.tmp\n.DS_Store\n");
|
|
379
288
|
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
console.log(` ├── public/`);
|
|
383
|
-
console.log(` ├── package.json`);
|
|
384
|
-
console.log(` ├── tsconfig.json`);
|
|
385
|
-
console.log(` └── .gitignore`);
|
|
386
|
-
|
|
387
|
-
console.log(`
|
|
388
|
-
Next steps:
|
|
389
|
-
cd ${parsed.name}
|
|
390
|
-
bun install
|
|
391
|
-
bun run dev # preview in browser
|
|
392
|
-
bun run build # render to video
|
|
393
|
-
`);
|
|
289
|
+
const files = ["src/index.tsx", "package.json", "tsconfig.json", ".gitignore", "public/"];
|
|
290
|
+
return { project: name, template, files };
|
|
394
291
|
}
|
package/src/commands/list.ts
CHANGED
|
@@ -1,49 +1,6 @@
|
|
|
1
|
-
import { resolve } from "node:path";
|
|
2
1
|
import { bundle } from "@vibeo/renderer";
|
|
3
2
|
import { launchBrowser, createPage, closeBrowser } from "@vibeo/renderer";
|
|
4
3
|
|
|
5
|
-
interface ListArgs {
|
|
6
|
-
entry: string;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
function parseArgs(args: string[]): ListArgs {
|
|
10
|
-
const result: ListArgs = {
|
|
11
|
-
entry: "",
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
for (let i = 0; i < args.length; i++) {
|
|
15
|
-
const arg = args[i]!;
|
|
16
|
-
const next = args[i + 1];
|
|
17
|
-
|
|
18
|
-
if (arg === "--entry" && next) {
|
|
19
|
-
result.entry = next;
|
|
20
|
-
i++;
|
|
21
|
-
} else if (arg.startsWith("--entry=")) {
|
|
22
|
-
result.entry = arg.slice("--entry=".length);
|
|
23
|
-
} else if (arg === "--help" || arg === "-h") {
|
|
24
|
-
printHelp();
|
|
25
|
-
process.exit(0);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
return result;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function printHelp(): void {
|
|
33
|
-
console.log(`
|
|
34
|
-
vibeo list - List registered compositions
|
|
35
|
-
|
|
36
|
-
Usage:
|
|
37
|
-
vibeo list --entry <path>
|
|
38
|
-
|
|
39
|
-
Required:
|
|
40
|
-
--entry <path> Path to the root file with compositions
|
|
41
|
-
|
|
42
|
-
Options:
|
|
43
|
-
--help Show this help
|
|
44
|
-
`);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
4
|
interface CompositionMeta {
|
|
48
5
|
id: string;
|
|
49
6
|
width: number;
|
|
@@ -52,21 +9,7 @@ interface CompositionMeta {
|
|
|
52
9
|
durationInFrames: number;
|
|
53
10
|
}
|
|
54
11
|
|
|
55
|
-
|
|
56
|
-
* Bundle the entry, launch a browser to evaluate it,
|
|
57
|
-
* extract registered compositions, and print a table.
|
|
58
|
-
*/
|
|
59
|
-
export async function listCommand(args: string[]): Promise<void> {
|
|
60
|
-
const parsed = parseArgs(args);
|
|
61
|
-
|
|
62
|
-
if (!parsed.entry) {
|
|
63
|
-
console.error("Error: --entry is required");
|
|
64
|
-
printHelp();
|
|
65
|
-
process.exit(1);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const entry = resolve(parsed.entry);
|
|
69
|
-
|
|
12
|
+
export async function listCompositions(entry: string): Promise<CompositionMeta[]> {
|
|
70
13
|
console.log(`Bundling ${entry}...`);
|
|
71
14
|
const bundleResult = await bundle(entry);
|
|
72
15
|
|
|
@@ -75,11 +18,8 @@ export async function listCommand(args: string[]): Promise<void> {
|
|
|
75
18
|
const page = await createPage(browser, 1920, 1080);
|
|
76
19
|
|
|
77
20
|
await page.goto(bundleResult.url, { waitUntil: "networkidle" });
|
|
78
|
-
|
|
79
|
-
// Wait briefly for React to register compositions
|
|
80
21
|
await page.waitForTimeout(2000);
|
|
81
22
|
|
|
82
|
-
// Extract composition data from the page
|
|
83
23
|
const compositions = await page.evaluate(() => {
|
|
84
24
|
const win = window as typeof window & {
|
|
85
25
|
vibeo_getCompositions?: () => CompositionMeta[];
|
|
@@ -93,44 +33,8 @@ export async function listCommand(args: string[]): Promise<void> {
|
|
|
93
33
|
await page.close();
|
|
94
34
|
await closeBrowser();
|
|
95
35
|
|
|
96
|
-
|
|
97
|
-
console.log("\nNo compositions found.");
|
|
98
|
-
console.log(
|
|
99
|
-
"Make sure your entry file exports compositions via <Composition /> components.",
|
|
100
|
-
);
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// Print table
|
|
105
|
-
console.log("\nRegistered compositions:\n");
|
|
106
|
-
console.log(
|
|
107
|
-
padRight("ID", 25) +
|
|
108
|
-
padRight("Width", 8) +
|
|
109
|
-
padRight("Height", 8) +
|
|
110
|
-
padRight("FPS", 6) +
|
|
111
|
-
padRight("Frames", 8) +
|
|
112
|
-
"Duration",
|
|
113
|
-
);
|
|
114
|
-
console.log("-".repeat(70));
|
|
115
|
-
|
|
116
|
-
for (const comp of compositions) {
|
|
117
|
-
const duration = (comp.durationInFrames / comp.fps).toFixed(1) + "s";
|
|
118
|
-
console.log(
|
|
119
|
-
padRight(comp.id, 25) +
|
|
120
|
-
padRight(String(comp.width), 8) +
|
|
121
|
-
padRight(String(comp.height), 8) +
|
|
122
|
-
padRight(String(comp.fps), 6) +
|
|
123
|
-
padRight(String(comp.durationInFrames), 8) +
|
|
124
|
-
duration,
|
|
125
|
-
);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
console.log();
|
|
36
|
+
return compositions;
|
|
129
37
|
} finally {
|
|
130
38
|
await bundleResult.cleanup();
|
|
131
39
|
}
|
|
132
40
|
}
|
|
133
|
-
|
|
134
|
-
function padRight(str: string, len: number): string {
|
|
135
|
-
return str.length >= len ? str : str + " ".repeat(len - str.length);
|
|
136
|
-
}
|
package/src/commands/preview.ts
CHANGED
|
@@ -1,70 +1,6 @@
|
|
|
1
|
-
import { resolve } from "node:path";
|
|
2
1
|
import { bundle } from "@vibeo/renderer";
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
entry: string;
|
|
6
|
-
port: number;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
function parseArgs(args: string[]): PreviewArgs {
|
|
10
|
-
const result: PreviewArgs = {
|
|
11
|
-
entry: "",
|
|
12
|
-
port: 3000,
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
for (let i = 0; i < args.length; i++) {
|
|
16
|
-
const arg = args[i]!;
|
|
17
|
-
const next = args[i + 1];
|
|
18
|
-
|
|
19
|
-
if (arg === "--entry" && next) {
|
|
20
|
-
result.entry = next;
|
|
21
|
-
i++;
|
|
22
|
-
} else if (arg.startsWith("--entry=")) {
|
|
23
|
-
result.entry = arg.slice("--entry=".length);
|
|
24
|
-
} else if (arg === "--port" && next) {
|
|
25
|
-
result.port = parseInt(next, 10);
|
|
26
|
-
i++;
|
|
27
|
-
} else if (arg.startsWith("--port=")) {
|
|
28
|
-
result.port = parseInt(arg.slice("--port=".length), 10);
|
|
29
|
-
} else if (arg === "--help" || arg === "-h") {
|
|
30
|
-
printHelp();
|
|
31
|
-
process.exit(0);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
return result;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function printHelp(): void {
|
|
39
|
-
console.log(`
|
|
40
|
-
vibeo preview - Start a dev server with live preview
|
|
41
|
-
|
|
42
|
-
Usage:
|
|
43
|
-
vibeo preview --entry <path> [options]
|
|
44
|
-
|
|
45
|
-
Required:
|
|
46
|
-
--entry <path> Path to the root file with compositions
|
|
47
|
-
|
|
48
|
-
Options:
|
|
49
|
-
--port <number> Port for the dev server (default: 3000)
|
|
50
|
-
--help Show this help
|
|
51
|
-
`);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Start a dev server hosting the Player with hot reload.
|
|
56
|
-
*/
|
|
57
|
-
export async function previewCommand(args: string[]): Promise<void> {
|
|
58
|
-
const parsed = parseArgs(args);
|
|
59
|
-
|
|
60
|
-
if (!parsed.entry) {
|
|
61
|
-
console.error("Error: --entry is required");
|
|
62
|
-
printHelp();
|
|
63
|
-
process.exit(1);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const entry = resolve(parsed.entry);
|
|
67
|
-
|
|
3
|
+
export async function startPreview(entry: string, _port: number): Promise<void> {
|
|
68
4
|
console.log(`Starting preview server...`);
|
|
69
5
|
console.log(` Entry: ${entry}`);
|
|
70
6
|
|
|
@@ -73,7 +9,6 @@ export async function previewCommand(args: string[]): Promise<void> {
|
|
|
73
9
|
console.log(`\n Preview running at ${bundleResult.url}`);
|
|
74
10
|
console.log(` Press Ctrl+C to stop\n`);
|
|
75
11
|
|
|
76
|
-
// Keep the process alive until interrupted
|
|
77
12
|
const shutdown = async () => {
|
|
78
13
|
console.log("\nShutting down preview server...");
|
|
79
14
|
await bundleResult.cleanup();
|