zerocut-cli 0.1.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/.eslintrc.js +11 -0
- package/.prettierignore +3 -0
- package/.prettierrc.json +6 -0
- package/README.md +205 -0
- package/dist/bin/zerocut.d.ts +2 -0
- package/dist/bin/zerocut.js +5 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +24 -0
- package/dist/commands/config.d.ts +4 -0
- package/dist/commands/config.js +129 -0
- package/dist/commands/ffmpeg.d.ts +4 -0
- package/dist/commands/ffmpeg.js +32 -0
- package/dist/commands/foo.d.ts +4 -0
- package/dist/commands/foo.js +14 -0
- package/dist/commands/help.d.ts +4 -0
- package/dist/commands/help.js +14 -0
- package/dist/commands/image.d.ts +4 -0
- package/dist/commands/image.js +149 -0
- package/dist/commands/music.d.ts +4 -0
- package/dist/commands/music.js +74 -0
- package/dist/commands/pandoc.d.ts +4 -0
- package/dist/commands/pandoc.js +32 -0
- package/dist/commands/skill.d.ts +4 -0
- package/dist/commands/skill.js +24 -0
- package/dist/commands/tts.d.ts +4 -0
- package/dist/commands/tts.js +74 -0
- package/dist/commands/video.d.ts +4 -0
- package/dist/commands/video.js +166 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +6 -0
- package/dist/services/cerevox.d.ts +34 -0
- package/dist/services/cerevox.js +256 -0
- package/dist/services/commandLoader.d.ts +3 -0
- package/dist/services/commandLoader.js +80 -0
- package/dist/services/config.d.ts +15 -0
- package/dist/services/config.js +235 -0
- package/dist/skill/SKILL.md +133 -0
- package/dist/types/command.d.ts +6 -0
- package/dist/types/command.js +2 -0
- package/dist/utils/progress.d.ts +1 -0
- package/dist/utils/progress.js +13 -0
- package/eslint.config.js +30 -0
- package/package.json +52 -0
- package/scripts/copy-skill-md.cjs +8 -0
- package/src/bin/zerocut.ts +3 -0
- package/src/cli.ts +25 -0
- package/src/commands/config.ts +130 -0
- package/src/commands/ffmpeg.ts +37 -0
- package/src/commands/help.ts +13 -0
- package/src/commands/image.ts +194 -0
- package/src/commands/music.ts +78 -0
- package/src/commands/pandoc.ts +37 -0
- package/src/commands/skill.ts +20 -0
- package/src/commands/tts.ts +80 -0
- package/src/commands/video.ts +202 -0
- package/src/index.ts +1 -0
- package/src/services/cerevox.ts +296 -0
- package/src/services/commandLoader.ts +42 -0
- package/src/services/config.ts +230 -0
- package/src/skill/SKILL.md +209 -0
- package/src/types/command.ts +7 -0
- package/src/utils/progress.ts +10 -0
- package/tsconfig.json +16 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import { getSessionFromCommand, syncToTOS } from "../services/cerevox";
|
|
3
|
+
import { createProgressSpinner } from "../utils/progress";
|
|
4
|
+
import fs from "node:fs";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
|
|
7
|
+
export const name = "music";
|
|
8
|
+
export const description = "Music command: create music";
|
|
9
|
+
|
|
10
|
+
export function register(program: Command): void {
|
|
11
|
+
const parent = program.command("music").description("Create a new music; requires --prompt");
|
|
12
|
+
|
|
13
|
+
async function musicCreateAction(
|
|
14
|
+
this: Command,
|
|
15
|
+
opts: {
|
|
16
|
+
prompt?: string;
|
|
17
|
+
output?: string;
|
|
18
|
+
}
|
|
19
|
+
) {
|
|
20
|
+
const session = getSessionFromCommand(this as unknown as Record<symbol, unknown>);
|
|
21
|
+
if (!session) {
|
|
22
|
+
process.stderr.write("No active session\n");
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const prompt = typeof opts.prompt === "string" ? opts.prompt : undefined;
|
|
26
|
+
if (!prompt || prompt.trim().length === 0) {
|
|
27
|
+
process.stderr.write("Missing required option: --prompt\n");
|
|
28
|
+
process.exitCode = 1;
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const res = await session.ai.generateMusic({
|
|
32
|
+
prompt,
|
|
33
|
+
onProgress: createProgressSpinner("inferencing"),
|
|
34
|
+
});
|
|
35
|
+
process.stdout.write("\n");
|
|
36
|
+
try {
|
|
37
|
+
if (res?.url) {
|
|
38
|
+
const tosUrl = await syncToTOS(res.url as string);
|
|
39
|
+
if (tosUrl) {
|
|
40
|
+
res.url = tosUrl;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
} catch (ex: unknown) {
|
|
44
|
+
console.log((ex as Error).message);
|
|
45
|
+
}
|
|
46
|
+
const output = typeof opts.output === "string" ? opts.output : undefined;
|
|
47
|
+
if (output) {
|
|
48
|
+
const dir = process.cwd();
|
|
49
|
+
const url = res.url;
|
|
50
|
+
const response = await fetch(url);
|
|
51
|
+
const buffer = Buffer.from(await response.arrayBuffer());
|
|
52
|
+
const filePath = path.resolve(dir, output);
|
|
53
|
+
if (!fs.existsSync(path.dirname(filePath))) {
|
|
54
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
55
|
+
}
|
|
56
|
+
fs.writeFileSync(filePath, buffer);
|
|
57
|
+
res.output = filePath;
|
|
58
|
+
}
|
|
59
|
+
console.log({
|
|
60
|
+
url: res.url,
|
|
61
|
+
duration: res.duration,
|
|
62
|
+
usage: res.usage,
|
|
63
|
+
output: res.output,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
parent
|
|
68
|
+
.option("--prompt <prompt>", "Text prompt for music generation (required)")
|
|
69
|
+
.option("--output <file>", "Output file path")
|
|
70
|
+
.action(musicCreateAction);
|
|
71
|
+
|
|
72
|
+
parent
|
|
73
|
+
.command("create")
|
|
74
|
+
.description("Create a new music; requires --prompt")
|
|
75
|
+
.option("--prompt <prompt>", "Text prompt for music generation (required)")
|
|
76
|
+
.option("--output <file>", "Output file path")
|
|
77
|
+
.action(musicCreateAction);
|
|
78
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import { getSessionFromCommand, runPandocCommand } from "../services/cerevox";
|
|
3
|
+
|
|
4
|
+
export const name = "pandoc";
|
|
5
|
+
export const description = "Run pandoc in sandbox";
|
|
6
|
+
|
|
7
|
+
export function register(program: Command): void {
|
|
8
|
+
program
|
|
9
|
+
.command("pandoc")
|
|
10
|
+
.description("Run pandoc command in sandbox")
|
|
11
|
+
.allowUnknownOption(true)
|
|
12
|
+
.option("--args <args...>", "Arguments passed to pandoc")
|
|
13
|
+
.option("--resources <resources...>", "Resource files/urls to sync into sandbox")
|
|
14
|
+
.action(async function (
|
|
15
|
+
this: Command,
|
|
16
|
+
opts: {
|
|
17
|
+
args?: string[];
|
|
18
|
+
resources?: string[];
|
|
19
|
+
}
|
|
20
|
+
) {
|
|
21
|
+
const session = getSessionFromCommand(this as unknown as Record<symbol, unknown>);
|
|
22
|
+
if (!session) {
|
|
23
|
+
process.stderr.write("No active session\n");
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const args = Array.isArray(opts.args) ? opts.args : [];
|
|
27
|
+
if (args.length === 0) {
|
|
28
|
+
process.stderr.write("Missing required option: --args\n");
|
|
29
|
+
process.exitCode = 1;
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const command = `pandoc ${args.join(" ")}`;
|
|
33
|
+
const resources = Array.isArray(opts.resources) ? opts.resources : [];
|
|
34
|
+
const res = await runPandocCommand(session, command, resources);
|
|
35
|
+
console.log(res);
|
|
36
|
+
});
|
|
37
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
|
|
5
|
+
export const name = "skill";
|
|
6
|
+
export const description = "Print built-in SKILL.md content";
|
|
7
|
+
|
|
8
|
+
export function register(program: Command): void {
|
|
9
|
+
program
|
|
10
|
+
.command("skill")
|
|
11
|
+
.description("Print built-in skill markdown")
|
|
12
|
+
.action(() => {
|
|
13
|
+
const filePath = path.resolve(__dirname, "../skill/SKILL.md");
|
|
14
|
+
const content = fs.readFileSync(filePath, "utf8");
|
|
15
|
+
process.stdout.write(content);
|
|
16
|
+
if (!content.endsWith("\n")) {
|
|
17
|
+
process.stdout.write("\n");
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import { getSessionFromCommand, syncToTOS } from "../services/cerevox";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
|
|
6
|
+
export const name = "tts";
|
|
7
|
+
export const description = "TTS command: create speech audio";
|
|
8
|
+
|
|
9
|
+
export function register(program: Command): void {
|
|
10
|
+
const parent = program.command("tts").description("Create speech audio; requires --text");
|
|
11
|
+
|
|
12
|
+
async function ttsCreateAction(
|
|
13
|
+
this: Command,
|
|
14
|
+
opts: {
|
|
15
|
+
prompt?: string;
|
|
16
|
+
text?: string;
|
|
17
|
+
voiceId?: string;
|
|
18
|
+
output?: string;
|
|
19
|
+
}
|
|
20
|
+
) {
|
|
21
|
+
const session = getSessionFromCommand(this as unknown as Record<symbol, unknown>);
|
|
22
|
+
if (!session) {
|
|
23
|
+
process.stderr.write("No active session\n");
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const text = typeof opts.text === "string" ? opts.text : undefined;
|
|
27
|
+
if (!text || text.trim().length === 0) {
|
|
28
|
+
process.stderr.write("Missing required option: --text\n");
|
|
29
|
+
process.exitCode = 1;
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const prompt = typeof opts.prompt === "string" ? opts.prompt : undefined;
|
|
33
|
+
const voiceId = typeof opts.voiceId === "string" ? opts.voiceId : undefined;
|
|
34
|
+
const res = await session.ai.textToSpeech({
|
|
35
|
+
prompt,
|
|
36
|
+
text,
|
|
37
|
+
voiceId,
|
|
38
|
+
});
|
|
39
|
+
try {
|
|
40
|
+
if (res?.url) {
|
|
41
|
+
const tosUrl = await syncToTOS(res.url as string);
|
|
42
|
+
if (tosUrl) {
|
|
43
|
+
res.url = tosUrl;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
} catch (ex: unknown) {
|
|
47
|
+
console.log((ex as Error).message);
|
|
48
|
+
}
|
|
49
|
+
const output = typeof opts.output === "string" ? opts.output : undefined;
|
|
50
|
+
if (output) {
|
|
51
|
+
const dir = process.cwd();
|
|
52
|
+
const url = res.url;
|
|
53
|
+
const response = await fetch(url);
|
|
54
|
+
const buffer = Buffer.from(await response.arrayBuffer());
|
|
55
|
+
const filePath = path.resolve(dir, output);
|
|
56
|
+
if (!fs.existsSync(path.dirname(filePath))) {
|
|
57
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
58
|
+
}
|
|
59
|
+
fs.writeFileSync(filePath, buffer);
|
|
60
|
+
res.output = filePath;
|
|
61
|
+
}
|
|
62
|
+
console.log(res);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
parent
|
|
66
|
+
.option("--prompt <prompt>", "Prompt for speech style/context")
|
|
67
|
+
.option("--text <text>", "Text to synthesize (required)")
|
|
68
|
+
.option("--voiceId <voiceId>", "Voice ID")
|
|
69
|
+
.option("--output <file>", "Output file path")
|
|
70
|
+
.action(ttsCreateAction);
|
|
71
|
+
|
|
72
|
+
parent
|
|
73
|
+
.command("create")
|
|
74
|
+
.description("Create speech audio; requires --text")
|
|
75
|
+
.option("--prompt <prompt>", "Prompt for speech style/context")
|
|
76
|
+
.option("--text <text>", "Text to synthesize (required)")
|
|
77
|
+
.option("--voiceId <voiceId>", "Voice ID")
|
|
78
|
+
.option("--output <file>", "Output file path")
|
|
79
|
+
.action(ttsCreateAction);
|
|
80
|
+
}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import { getMaterialUri, getSessionFromCommand, syncToTOS } from "../services/cerevox";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { createProgressSpinner } from "../utils/progress";
|
|
6
|
+
|
|
7
|
+
export const name = "video";
|
|
8
|
+
export const description = "Video command: create video";
|
|
9
|
+
|
|
10
|
+
export function register(program: Command): void {
|
|
11
|
+
const parent = program.command("video").description("Create a new video; requires --prompt");
|
|
12
|
+
|
|
13
|
+
const allowedTypes = [
|
|
14
|
+
"zerocut3.0",
|
|
15
|
+
"seedance-1.5-pro",
|
|
16
|
+
"vidu",
|
|
17
|
+
"vidu-pro",
|
|
18
|
+
"viduq3",
|
|
19
|
+
"viduq3-turbo",
|
|
20
|
+
"kling",
|
|
21
|
+
"kling-v3",
|
|
22
|
+
"wan",
|
|
23
|
+
"wan-flash",
|
|
24
|
+
"sora2",
|
|
25
|
+
"sora2-pro",
|
|
26
|
+
"veo3.1",
|
|
27
|
+
"veo3.1-pro",
|
|
28
|
+
] as const;
|
|
29
|
+
|
|
30
|
+
async function videoCreateAction(
|
|
31
|
+
this: Command,
|
|
32
|
+
opts: {
|
|
33
|
+
prompt?: string;
|
|
34
|
+
duration?: string;
|
|
35
|
+
model?: string;
|
|
36
|
+
sourceVideo?: string;
|
|
37
|
+
seed?: string;
|
|
38
|
+
firstFrame?: string;
|
|
39
|
+
lastFrame?: string;
|
|
40
|
+
refs?: string;
|
|
41
|
+
resolution?: "720p" | "1080p";
|
|
42
|
+
aspectRatio?: "9:16" | "16:9" | "1:1";
|
|
43
|
+
withAudio?: boolean;
|
|
44
|
+
optimizeCameraMotion?: boolean;
|
|
45
|
+
output?: string;
|
|
46
|
+
}
|
|
47
|
+
) {
|
|
48
|
+
const session = getSessionFromCommand(this as unknown as Record<symbol, unknown>);
|
|
49
|
+
if (!session) {
|
|
50
|
+
process.stderr.write("No active session\n");
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const prompt = typeof opts.prompt === "string" ? opts.prompt : undefined;
|
|
54
|
+
if (!prompt || prompt.trim().length === 0) {
|
|
55
|
+
process.stderr.write("Missing required option: --prompt\n");
|
|
56
|
+
process.exitCode = 1;
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
let model = typeof opts.model === "string" ? opts.model.trim() : undefined;
|
|
60
|
+
if (model && !(allowedTypes as readonly string[]).includes(model)) {
|
|
61
|
+
process.stderr.write(
|
|
62
|
+
`Invalid value for --model: ${model}. Allowed: ${allowedTypes.join("|")}\n`
|
|
63
|
+
);
|
|
64
|
+
process.exitCode = 1;
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
if (!model) model = "vidu";
|
|
68
|
+
const durationStr = typeof opts.duration === "string" ? opts.duration.trim() : undefined;
|
|
69
|
+
const sourceVideo = typeof opts.sourceVideo === "string" ? opts.sourceVideo.trim() : undefined;
|
|
70
|
+
let duration: number = 0;
|
|
71
|
+
if (durationStr) {
|
|
72
|
+
const n = Number.parseInt(durationStr, 10);
|
|
73
|
+
if (!Number.isFinite(n) || n < 1 || n > 16) {
|
|
74
|
+
process.stderr.write("Invalid value for --duration: must be integer 1-16\n");
|
|
75
|
+
process.exitCode = 1;
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
duration = n;
|
|
79
|
+
}
|
|
80
|
+
const allowedAspectRatios = ["9:16", "16:9", "1:1"] as const;
|
|
81
|
+
const ar = typeof opts.aspectRatio === "string" ? opts.aspectRatio : undefined;
|
|
82
|
+
if (ar && !(allowedAspectRatios as readonly string[]).includes(ar)) {
|
|
83
|
+
process.stderr.write(
|
|
84
|
+
`Invalid value for --aspectRatio: ${ar}. Allowed: ${allowedAspectRatios.join("|")}\n`
|
|
85
|
+
);
|
|
86
|
+
process.exitCode = 1;
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const aspectRatio = ar as (typeof allowedAspectRatios)[number] | undefined;
|
|
90
|
+
const images: {
|
|
91
|
+
type: "first_frame" | "last_frame" | "reference" | "storyboard";
|
|
92
|
+
url: string;
|
|
93
|
+
name?: string;
|
|
94
|
+
}[] = [];
|
|
95
|
+
if (opts.firstFrame) {
|
|
96
|
+
images.push({
|
|
97
|
+
type: "first_frame",
|
|
98
|
+
url: await getMaterialUri(session, opts.firstFrame),
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
if (opts.lastFrame) {
|
|
102
|
+
images.push({
|
|
103
|
+
type: "last_frame",
|
|
104
|
+
url: await getMaterialUri(session, opts.lastFrame),
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
const refsList =
|
|
108
|
+
typeof opts.refs === "string" && opts.refs.length > 0
|
|
109
|
+
? opts.refs
|
|
110
|
+
.split(",")
|
|
111
|
+
.map((s) => s.trim())
|
|
112
|
+
.filter((s) => s.length > 0)
|
|
113
|
+
: [];
|
|
114
|
+
for (const ref of refsList) {
|
|
115
|
+
images.push({
|
|
116
|
+
type: "reference",
|
|
117
|
+
url: await getMaterialUri(session, ref),
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
const res = await session.ai.generateVideo({
|
|
121
|
+
prompt,
|
|
122
|
+
model: model as (typeof allowedTypes)[number],
|
|
123
|
+
duration: duration || undefined,
|
|
124
|
+
resolution: opts.resolution,
|
|
125
|
+
aspect_ratio: aspectRatio,
|
|
126
|
+
mute: !(opts.withAudio ?? true),
|
|
127
|
+
optimize_camera: opts.optimizeCameraMotion,
|
|
128
|
+
seed: opts.seed ? Number.parseInt(opts.seed, 10) : undefined,
|
|
129
|
+
images: images.length > 0 ? images : undefined,
|
|
130
|
+
videos: sourceVideo
|
|
131
|
+
? [
|
|
132
|
+
{
|
|
133
|
+
type: "base",
|
|
134
|
+
url: await getMaterialUri(session, sourceVideo),
|
|
135
|
+
},
|
|
136
|
+
]
|
|
137
|
+
: undefined,
|
|
138
|
+
onProgress: createProgressSpinner("inferencing"),
|
|
139
|
+
});
|
|
140
|
+
try {
|
|
141
|
+
if (res?.url) {
|
|
142
|
+
const tosUrl = await syncToTOS(res.url as string);
|
|
143
|
+
if (tosUrl) {
|
|
144
|
+
res.url = tosUrl;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
} catch {}
|
|
148
|
+
process.stdout.write("\n");
|
|
149
|
+
const output = typeof opts.output === "string" ? opts.output : undefined;
|
|
150
|
+
if (output) {
|
|
151
|
+
const dir = process.cwd();
|
|
152
|
+
const url = res.url;
|
|
153
|
+
const response = await fetch(url);
|
|
154
|
+
const buffer = Buffer.from(await response.arrayBuffer());
|
|
155
|
+
const filePath = path.resolve(dir, output);
|
|
156
|
+
if (!fs.existsSync(path.dirname(filePath))) {
|
|
157
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
158
|
+
}
|
|
159
|
+
fs.writeFileSync(filePath, buffer);
|
|
160
|
+
res.output = filePath;
|
|
161
|
+
}
|
|
162
|
+
console.log(res);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// default action on `zerocut video`
|
|
166
|
+
parent
|
|
167
|
+
.option("--prompt <prompt>", "Text prompt for video generation (required)")
|
|
168
|
+
.option("--duration <duration>", "Video duration in seconds (1-16)")
|
|
169
|
+
.option("--model <model>", `Video model: ${allowedTypes.join("|")} (default: vidu)`)
|
|
170
|
+
.option("--sourceVideo <video>", "Base video path/url for edit mode (requires --duration 3-10)")
|
|
171
|
+
.option("--seed <seed>", "Random seed")
|
|
172
|
+
.option("--firstFrame <image>", "First frame image path/url")
|
|
173
|
+
.option("--lastFrame <image>", "Last frame image path/url")
|
|
174
|
+
.option("--refs <refs>", "Comma-separated reference image/video paths/urls")
|
|
175
|
+
.option("--resolution <resolution>", "Resolution, e.g., 720p")
|
|
176
|
+
.option("--aspectRatio <ratio>", "Aspect ratio: 9:16|16:9|1:1")
|
|
177
|
+
.option("--withAudio", "Include audio track")
|
|
178
|
+
.option("--optimizeCameraMotion", "Optimize camera motion")
|
|
179
|
+
.option("--output <file>", "Output file path")
|
|
180
|
+
.action(videoCreateAction);
|
|
181
|
+
|
|
182
|
+
// keep `video create` for compatibility
|
|
183
|
+
parent
|
|
184
|
+
.command("create")
|
|
185
|
+
.description("Create a new video; requires --prompt")
|
|
186
|
+
.option("--prompt <prompt>", "Text prompt for video generation (required)")
|
|
187
|
+
.option("--duration <duration>", "Video duration in seconds (1-16)")
|
|
188
|
+
.option("--model <model>", `Video model: ${allowedTypes.join("|")} (default: vidu)`)
|
|
189
|
+
.option("--sourceVideo <video>", "Base video path/url for edit mode (requires --duration 3-10)")
|
|
190
|
+
.option("--seed <seed>", "Random seed")
|
|
191
|
+
.option("--firstFrame <image>", "First frame image path/url")
|
|
192
|
+
.option("--lastFrame <image>", "Last frame image path/url")
|
|
193
|
+
.option("--refs <refs>", "Comma-separated reference image/video paths/urls")
|
|
194
|
+
.option("--resolution <resolution>", "Resolution, e.g., 720p")
|
|
195
|
+
.option("--aspectRatio <ratio>", "Aspect ratio: 9:16|16:9|1:1")
|
|
196
|
+
.option("--withAudio", "Include audio track")
|
|
197
|
+
.option("--optimizeCameraMotion", "Optimize camera motion")
|
|
198
|
+
.option("--output <file>", "Output file path")
|
|
199
|
+
.action(videoCreateAction);
|
|
200
|
+
|
|
201
|
+
// removed `video edit`
|
|
202
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { run, createProgram } from "./cli";
|