video-maker-mcp 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.
Files changed (41) hide show
  1. package/README.md +143 -0
  2. package/dist/cli/index.d.ts +2 -0
  3. package/dist/cli/index.js +74 -0
  4. package/dist/cli/index.js.map +1 -0
  5. package/dist/cli/install.d.ts +15 -0
  6. package/dist/cli/install.js +59 -0
  7. package/dist/cli/install.js.map +1 -0
  8. package/dist/cli/load-env.d.ts +1 -0
  9. package/dist/cli/load-env.js +11 -0
  10. package/dist/cli/load-env.js.map +1 -0
  11. package/dist/core/assets.d.ts +28 -0
  12. package/dist/core/assets.js +50 -0
  13. package/dist/core/assets.js.map +1 -0
  14. package/dist/core/env.d.ts +27 -0
  15. package/dist/core/env.js +89 -0
  16. package/dist/core/env.js.map +1 -0
  17. package/dist/core/export.d.ts +11 -0
  18. package/dist/core/export.js +39 -0
  19. package/dist/core/export.js.map +1 -0
  20. package/dist/core/paths.d.ts +12 -0
  21. package/dist/core/paths.js +57 -0
  22. package/dist/core/paths.js.map +1 -0
  23. package/dist/core/plan-schema.d.ts +90 -0
  24. package/dist/core/plan-schema.js +91 -0
  25. package/dist/core/plan-schema.js.map +1 -0
  26. package/dist/core/project.d.ts +41 -0
  27. package/dist/core/project.js +72 -0
  28. package/dist/core/project.js.map +1 -0
  29. package/dist/core/render.d.ts +12 -0
  30. package/dist/core/render.js +100 -0
  31. package/dist/core/render.js.map +1 -0
  32. package/dist/core/subtitles.d.ts +4 -0
  33. package/dist/core/subtitles.js +30 -0
  34. package/dist/core/subtitles.js.map +1 -0
  35. package/dist/mcp/server.d.ts +3 -0
  36. package/dist/mcp/server.js +120 -0
  37. package/dist/mcp/server.js.map +1 -0
  38. package/dist/providers/tts/volcengine.d.ts +19 -0
  39. package/dist/providers/tts/volcengine.js +209 -0
  40. package/dist/providers/tts/volcengine.js.map +1 -0
  41. package/package.json +39 -0
package/README.md ADDED
@@ -0,0 +1,143 @@
1
+ # video-maker-mcp
2
+
3
+ Local MCP storyboard video renderer for Codex-driven short video generation.
4
+
5
+ `video-maker-mcp` does not run its own LLM and does not generate images itself. Codex writes the script and storyboard, uses its host image generation capability to create scene images, then this MCP server validates assets, generates Doubao/Volcengine narration, and renders a 9:16 MP4 with ffmpeg.
6
+
7
+ ## Install With Codex
8
+
9
+ Paste this into Codex:
10
+
11
+ ```text
12
+ 请帮我安装 video-maker-mcp。执行:
13
+ npx -y video-maker-mcp@latest install --host codex
14
+
15
+ 如果提示缺少 ffmpeg,请按提示安装 ffmpeg,然后重新运行:
16
+ npx -y video-maker-mcp@latest doctor
17
+
18
+ 最后确认 Codex 能看到 video-maker MCP server。
19
+ ```
20
+
21
+ Manual command:
22
+
23
+ ```bash
24
+ npx -y video-maker-mcp@latest install --host codex
25
+ ```
26
+
27
+ The installer configures Codex with:
28
+
29
+ ```bash
30
+ codex mcp add video-maker -- npx -y video-maker-mcp@latest serve
31
+ ```
32
+
33
+ It does not silently install system packages and does not bundle `ffmpeg-static`.
34
+
35
+ ## Requirements
36
+
37
+ - Node.js 20+
38
+ - Codex CLI
39
+ - ffmpeg on PATH
40
+ - Doubao/Volcengine TTS credentials
41
+
42
+ ffmpeg install hints:
43
+
44
+ ```bash
45
+ # macOS
46
+ brew install ffmpeg
47
+
48
+ # Ubuntu/Debian
49
+ sudo apt update && sudo apt install -y ffmpeg
50
+
51
+ # Windows
52
+ winget install Gyan.FFmpeg
53
+ ```
54
+
55
+ ## TTS Environment
56
+
57
+ Set:
58
+
59
+ ```env
60
+ VIDEO_MAKER_TTS_API_KEY=your-api-key
61
+ VIDEO_MAKER_TTS_VOICE_ID=zh_female_vv_uranus_bigtts
62
+ VIDEO_MAKER_TTS_RESOURCE_ID=seed-tts-2.0
63
+ ```
64
+
65
+ For local development, put these values in a project-root `.env` file. The CLI loads `.env` automatically. To load another env file, set `VIDEO_MAKER_ENV_FILE=/path/to/file`.
66
+
67
+ The default TTS integration uses the current Doubao/Volcengine V3 HTTP unidirectional API with `X-Api-Key`. This matches the new console API Key page.
68
+
69
+ Legacy V1 `AppID + Access Token` is still accepted as a fallback when `VIDEO_MAKER_TTS_API_KEY` is not set, but new accounts should use `VIDEO_MAKER_TTS_API_KEY`.
70
+
71
+ Optional:
72
+
73
+ ```env
74
+ VIDEO_MAKER_TTS_ENDPOINT=https://openspeech.bytedance.com/api/v3/tts/unidirectional
75
+ VIDEO_MAKER_WORKSPACE=$HOME/.video-maker
76
+ VIDEO_MAKER_EXPORT_DIR=$HOME/Downloads/video-maker
77
+ ```
78
+
79
+ Quick TTS smoke test:
80
+
81
+ ```bash
82
+ npm run build
83
+ node dist/cli/index.js tts-test --text "你好,这是一段豆包语音测试。"
84
+ open ~/Downloads/video-maker/doubao-tts-test.mp3
85
+ ```
86
+
87
+ `tts-test --out` accepts either a directory or an `.mp3` file:
88
+
89
+ ```bash
90
+ node dist/cli/index.js tts-test --out ~/Downloads/video-maker
91
+ node dist/cli/index.js tts-test --out ~/Downloads/my-voice-test.mp3
92
+ ```
93
+
94
+ ## Codex Workflow
95
+
96
+ Once installed, ask Codex:
97
+
98
+ ```text
99
+ 用 video-maker 把下面文稿生成一个 60 秒竖屏中文解说视频。请先检查环境,然后创建项目,生成分镜计划,生成每个分镜图片,验证素材,生成语音,最后渲染 mp4,并把最终文件导出到 ~/Downloads/video-maker。
100
+ ```
101
+
102
+ The MCP workflow is:
103
+
104
+ 1. `check_environment`
105
+ 2. `create_video_project`
106
+ 3. `get_video_plan_schema`
107
+ 4. `save_video_plan`
108
+ 5. `list_required_assets`
109
+ 6. Codex generates images into the exact returned paths
110
+ 7. `verify_assets`
111
+ 8. `generate_audio`
112
+ 9. `render_video`
113
+ 10. Optional: `export_video`
114
+
115
+ ## Output
116
+
117
+ Projects are stored under:
118
+
119
+ ```text
120
+ ~/.video-maker/projects/<projectId>
121
+ ```
122
+
123
+ Final files:
124
+
125
+ - `output/final.mp4`
126
+ - `output/subtitles.srt`
127
+ - `manifest.json`
128
+ - `video_plan.json`
129
+
130
+ For user-facing delivery, ask Codex to pass `outputDir` to `render_video` or call `export_video` after rendering. If no export directory is provided, `export_video` copies files to:
131
+
132
+ ```text
133
+ ~/Downloads/video-maker/<projectId>
134
+ ```
135
+
136
+ ## Local Development
137
+
138
+ ```bash
139
+ npm install
140
+ npm run typecheck
141
+ npm run build
142
+ node dist/cli/index.js doctor
143
+ ```
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from "commander";
3
+ import fs from "node:fs/promises";
4
+ import path from "node:path";
5
+ import { serveMcp } from "../mcp/server.js";
6
+ import { installCodex, runDoctor } from "./install.js";
7
+ import { synthesizeVolcengineSpeech } from "../providers/tts/volcengine.js";
8
+ import { loadCliEnv } from "./load-env.js";
9
+ import { DEFAULT_EXPORT_DIR, resolveUserPath } from "../core/paths.js";
10
+ loadCliEnv();
11
+ const program = new Command();
12
+ function defaultTtsTestPath() {
13
+ return path.join(DEFAULT_EXPORT_DIR, "doubao-tts-test.mp3");
14
+ }
15
+ async function resolveOutputPath(output) {
16
+ const resolved = resolveUserPath(output);
17
+ if (path.extname(resolved).toLowerCase() === ".mp3") {
18
+ await fs.mkdir(path.dirname(resolved), { recursive: true });
19
+ return resolved;
20
+ }
21
+ await fs.mkdir(resolved, { recursive: true });
22
+ return path.join(resolved, "doubao-tts-test.mp3");
23
+ }
24
+ program
25
+ .name("video-maker-mcp")
26
+ .description("Local MCP storyboard video renderer for Codex.")
27
+ .version("0.1.0");
28
+ program
29
+ .command("serve")
30
+ .description("Start the stdio MCP server.")
31
+ .action(async () => {
32
+ await serveMcp();
33
+ });
34
+ program
35
+ .command("doctor")
36
+ .description("Check local dependencies and configuration.")
37
+ .action(async () => {
38
+ const result = await runDoctor();
39
+ console.log(JSON.stringify(result, null, 2));
40
+ if (!result.ok)
41
+ process.exitCode = 1;
42
+ });
43
+ program
44
+ .command("install")
45
+ .description("Configure video-maker-mcp for a supported host.")
46
+ .option("--host <host>", "Host to configure; v1 supports codex", "codex")
47
+ .option("--package-spec <spec>", "npm package spec used in Codex MCP config", "video-maker-mcp@latest")
48
+ .action(async (opts) => {
49
+ if (opts.host !== "codex") {
50
+ console.error("v1 only supports --host codex");
51
+ process.exitCode = 1;
52
+ return;
53
+ }
54
+ const result = await installCodex({ host: "codex", packageSpec: opts.packageSpec });
55
+ console.log(JSON.stringify(result, null, 2));
56
+ if (!result.ok)
57
+ process.exitCode = 1;
58
+ });
59
+ program
60
+ .command("tts-test")
61
+ .description("Generate a short MP3 with the configured Doubao/Volcengine TTS credentials.")
62
+ .option("--text <text>", "Text to synthesize", "你好,这是一段 video-maker-mcp 的豆包语音合成本地测试。")
63
+ .option("--out <path>", "Output MP3 path or directory", defaultTtsTestPath())
64
+ .action(async (opts) => {
65
+ const outputPath = await resolveOutputPath(opts.out);
66
+ const audio = await synthesizeVolcengineSpeech(opts.text);
67
+ await fs.writeFile(outputPath, audio);
68
+ console.log(JSON.stringify({ ok: true, outputPath, bytes: audio.length }, null, 2));
69
+ });
70
+ program.parseAsync(process.argv).catch((error) => {
71
+ console.error(error instanceof Error ? error.message : String(error));
72
+ process.exitCode = 1;
73
+ });
74
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import { checkEnvironment } from "../core/env.js";
2
+ export interface InstallOptions {
3
+ host: "codex";
4
+ packageSpec?: string;
5
+ }
6
+ export declare function runDoctor(): Promise<{
7
+ ok: boolean;
8
+ environment: Awaited<ReturnType<typeof checkEnvironment>>;
9
+ }>;
10
+ export declare function installCodex(options: InstallOptions): Promise<{
11
+ ok: boolean;
12
+ configured: boolean;
13
+ message: string;
14
+ environment: Awaited<ReturnType<typeof checkEnvironment>>;
15
+ }>;
@@ -0,0 +1,59 @@
1
+ import { execa } from "execa";
2
+ import { checkEnvironment, ffmpegInstallCommand } from "../core/env.js";
3
+ import { ensureWorkspace } from "../core/project.js";
4
+ export async function runDoctor() {
5
+ await ensureWorkspace();
6
+ const environment = await checkEnvironment();
7
+ return { ok: environment.ok, environment };
8
+ }
9
+ export async function installCodex(options) {
10
+ if (options.host !== "codex") {
11
+ throw new Error("v1 only supports --host codex");
12
+ }
13
+ await ensureWorkspace();
14
+ const environment = await checkEnvironment();
15
+ if (!environment.ffmpeg.installed) {
16
+ return {
17
+ ok: false,
18
+ configured: false,
19
+ environment,
20
+ message: `ffmpeg is required before configuring video-maker-mcp. Install it with: ${environment.ffmpeg.installCommand ?? ffmpegInstallCommand()}`
21
+ };
22
+ }
23
+ if (!environment.codex.installed) {
24
+ return {
25
+ ok: false,
26
+ configured: false,
27
+ environment,
28
+ message: "Codex CLI was not found on PATH. Install Codex first, then rerun this installer."
29
+ };
30
+ }
31
+ const already = await execa("codex", ["mcp", "get", "video-maker"], { reject: false });
32
+ if (already.exitCode === 0) {
33
+ return {
34
+ ok: true,
35
+ configured: false,
36
+ environment,
37
+ message: "Codex MCP server 'video-maker' is already configured."
38
+ };
39
+ }
40
+ const packageSpec = options.packageSpec ?? "video-maker-mcp@latest";
41
+ const add = await execa("codex", [
42
+ "mcp", "add", "video-maker", "--",
43
+ "npx", "-y", packageSpec, "serve"
44
+ ], { reject: false });
45
+ if (add.exitCode !== 0) {
46
+ throw new Error(`codex mcp add failed:\n${add.stdout}\n${add.stderr}`);
47
+ }
48
+ const smoke = await execa("codex", ["mcp", "get", "video-maker"], { reject: false });
49
+ if (smoke.exitCode !== 0) {
50
+ throw new Error(`codex mcp get video-maker failed after install:\n${smoke.stdout}\n${smoke.stderr}`);
51
+ }
52
+ return {
53
+ ok: true,
54
+ configured: true,
55
+ environment,
56
+ message: "Configured Codex MCP server 'video-maker'. Restart active Codex sessions to load it."
57
+ };
58
+ }
59
+ //# sourceMappingURL=install.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/cli/install.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAC9B,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACxE,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAOrD,MAAM,CAAC,KAAK,UAAU,SAAS;IAI7B,MAAM,eAAe,EAAE,CAAC;IACxB,MAAM,WAAW,GAAG,MAAM,gBAAgB,EAAE,CAAC;IAC7C,OAAO,EAAE,EAAE,EAAE,WAAW,CAAC,EAAE,EAAE,WAAW,EAAE,CAAC;AAC7C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAAuB;IAMxD,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACnD,CAAC;IACD,MAAM,eAAe,EAAE,CAAC;IACxB,MAAM,WAAW,GAAG,MAAM,gBAAgB,EAAE,CAAC;IAC7C,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;QAClC,OAAO;YACL,EAAE,EAAE,KAAK;YACT,UAAU,EAAE,KAAK;YACjB,WAAW;YACX,OAAO,EAAE,2EAA2E,WAAW,CAAC,MAAM,CAAC,cAAc,IAAI,oBAAoB,EAAE,EAAE;SAClJ,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC;QACjC,OAAO;YACL,EAAE,EAAE,KAAK;YACT,UAAU,EAAE,KAAK;YACjB,WAAW;YACX,OAAO,EAAE,kFAAkF;SAC5F,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IACvF,IAAI,OAAO,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO;YACL,EAAE,EAAE,IAAI;YACR,UAAU,EAAE,KAAK;YACjB,WAAW;YACX,OAAO,EAAE,uDAAuD;SACjE,CAAC;IACJ,CAAC;IAED,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,wBAAwB,CAAC;IACpE,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,OAAO,EAAE;QAC/B,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,IAAI;QACjC,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO;KAClC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IACtB,IAAI,GAAG,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,0BAA0B,GAAG,CAAC,MAAM,KAAK,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;IACzE,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IACrF,IAAI,KAAK,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,oDAAoD,KAAK,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IACvG,CAAC;IACD,OAAO;QACL,EAAE,EAAE,IAAI;QACR,UAAU,EAAE,IAAI;QAChB,WAAW;QACX,OAAO,EAAE,sFAAsF;KAChG,CAAC;AACJ,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function loadCliEnv(): string | undefined;
@@ -0,0 +1,11 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import dotenv from "dotenv";
4
+ export function loadCliEnv() {
5
+ const envFile = process.env.VIDEO_MAKER_ENV_FILE ?? path.join(process.cwd(), ".env");
6
+ if (!fs.existsSync(envFile))
7
+ return undefined;
8
+ dotenv.config({ path: envFile, quiet: true });
9
+ return envFile;
10
+ }
11
+ //# sourceMappingURL=load-env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-env.js","sourceRoot":"","sources":["../../src/cli/load-env.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,MAAM,UAAU,UAAU;IACxB,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,CAAC,CAAC;IACrF,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,SAAS,CAAC;IAC9C,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9C,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,28 @@
1
+ export interface RequiredAsset {
2
+ sceneId: string;
3
+ assetPath: string;
4
+ absolutePath: string;
5
+ prompt: string;
6
+ durationSec: number;
7
+ }
8
+ export interface AssetIssue {
9
+ sceneId: string;
10
+ assetPath: string;
11
+ absolutePath: string;
12
+ ok: false;
13
+ error: string;
14
+ }
15
+ export interface VerifiedAsset {
16
+ sceneId: string;
17
+ assetPath: string;
18
+ absolutePath: string;
19
+ ok: true;
20
+ width: number;
21
+ height: number;
22
+ format?: string;
23
+ }
24
+ export declare function listRequiredAssets(projectId: string): Promise<RequiredAsset[]>;
25
+ export declare function verifyAssets(projectId: string): Promise<{
26
+ ok: boolean;
27
+ assets: Array<VerifiedAsset | AssetIssue>;
28
+ }>;
@@ -0,0 +1,50 @@
1
+ import fs from "node:fs/promises";
2
+ import sharp from "sharp";
3
+ import { readVideoPlan, markStatus } from "./project.js";
4
+ import { toProjectPath } from "./paths.js";
5
+ export async function listRequiredAssets(projectId) {
6
+ const plan = await readVideoPlan(projectId);
7
+ return plan.scenes.map((scene) => ({
8
+ sceneId: scene.id,
9
+ assetPath: scene.assetPath,
10
+ absolutePath: toProjectPath(projectId, scene.assetPath),
11
+ prompt: scene.visualPrompt,
12
+ durationSec: scene.durationSec
13
+ }));
14
+ }
15
+ export async function verifyAssets(projectId) {
16
+ const required = await listRequiredAssets(projectId);
17
+ const assets = await Promise.all(required.map(async (asset) => {
18
+ try {
19
+ await fs.access(asset.absolutePath);
20
+ const metadata = await sharp(asset.absolutePath).metadata();
21
+ if (!metadata.width || !metadata.height) {
22
+ throw new Error("Image dimensions could not be read");
23
+ }
24
+ return {
25
+ sceneId: asset.sceneId,
26
+ assetPath: asset.assetPath,
27
+ absolutePath: asset.absolutePath,
28
+ ok: true,
29
+ width: metadata.width,
30
+ height: metadata.height,
31
+ format: metadata.format
32
+ };
33
+ }
34
+ catch (error) {
35
+ return {
36
+ sceneId: asset.sceneId,
37
+ assetPath: asset.assetPath,
38
+ absolutePath: asset.absolutePath,
39
+ ok: false,
40
+ error: error instanceof Error ? error.message : String(error)
41
+ };
42
+ }
43
+ }));
44
+ const ok = assets.every((asset) => asset.ok);
45
+ if (ok) {
46
+ await markStatus(projectId, "assets_ready");
47
+ }
48
+ return { ok, assets };
49
+ }
50
+ //# sourceMappingURL=assets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assets.js","sourceRoot":"","sources":["../../src/core/assets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AA4B3C,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,SAAiB;IACxD,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,SAAS,CAAC,CAAC;IAC5C,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACjC,OAAO,EAAE,KAAK,CAAC,EAAE;QACjB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,YAAY,EAAE,aAAa,CAAC,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC;QACvD,MAAM,EAAE,KAAK,CAAC,YAAY;QAC1B,WAAW,EAAE,KAAK,CAAC,WAAW;KAC/B,CAAC,CAAC,CAAC;AACN,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,SAAiB;IAIlD,MAAM,QAAQ,GAAG,MAAM,kBAAkB,CAAC,SAAS,CAAC,CAAC;IACrD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,EAAuC,EAAE;QACjG,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;YACpC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,QAAQ,EAAE,CAAC;YAC5D,IAAI,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;gBACxC,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;YACxD,CAAC;YACD,OAAO;gBACL,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,YAAY,EAAE,KAAK,CAAC,YAAY;gBAChC,EAAE,EAAE,IAAI;gBACR,KAAK,EAAE,QAAQ,CAAC,KAAK;gBACrB,MAAM,EAAE,QAAQ,CAAC,MAAM;gBACvB,MAAM,EAAE,QAAQ,CAAC,MAAM;aACxB,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO;gBACL,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,YAAY,EAAE,KAAK,CAAC,YAAY;gBAChC,EAAE,EAAE,KAAK;gBACT,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;aAC9D,CAAC;QACJ,CAAC;IACH,CAAC,CAAC,CAAC,CAAC;IACJ,MAAM,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC7C,IAAI,EAAE,EAAE,CAAC;QACP,MAAM,UAAU,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC;AACxB,CAAC"}
@@ -0,0 +1,27 @@
1
+ export interface BinaryCheck {
2
+ installed: boolean;
3
+ path?: string;
4
+ version?: string;
5
+ installCommand?: string;
6
+ error?: string;
7
+ }
8
+ export interface TtsCheck {
9
+ configured: boolean;
10
+ missingEnv: string[];
11
+ }
12
+ export interface EnvironmentCheck {
13
+ ok: boolean;
14
+ node: {
15
+ version: string;
16
+ ok: boolean;
17
+ };
18
+ ffmpeg: BinaryCheck;
19
+ codex: BinaryCheck;
20
+ tts: TtsCheck;
21
+ workspaceDir: string;
22
+ defaultExportDir: string;
23
+ nextActions: string[];
24
+ }
25
+ export declare function ffmpegInstallCommand(platform?: NodeJS.Platform): string;
26
+ export declare function resolveBinary(name: string, args?: string[]): Promise<BinaryCheck>;
27
+ export declare function checkEnvironment(): Promise<EnvironmentCheck>;
@@ -0,0 +1,89 @@
1
+ import os from "node:os";
2
+ import { execa } from "execa";
3
+ import which from "which";
4
+ import { exportDir, workspaceDir } from "./paths.js";
5
+ function missingTtsEnv(env = process.env) {
6
+ const missing = [];
7
+ if (!env.VIDEO_MAKER_TTS_VOICE_ID)
8
+ missing.push("VIDEO_MAKER_TTS_VOICE_ID");
9
+ if (env.VIDEO_MAKER_TTS_API_KEY)
10
+ return missing;
11
+ if (env.VIDEO_MAKER_TTS_APP_ID && (env.VIDEO_MAKER_TTS_TOKEN || env.VIDEO_MAKER_TTS_ACCESS_TOKEN || env.VOLCENGINE_SECRET_ACCESS_KEY)) {
12
+ return missing;
13
+ }
14
+ missing.push("VIDEO_MAKER_TTS_API_KEY");
15
+ return missing;
16
+ }
17
+ export function ffmpegInstallCommand(platform = process.platform) {
18
+ if (platform === "darwin")
19
+ return "brew install ffmpeg";
20
+ if (platform === "win32")
21
+ return "winget install Gyan.FFmpeg";
22
+ if (platform === "linux") {
23
+ const distro = os.release().toLowerCase();
24
+ if (distro.includes("arch"))
25
+ return "sudo pacman -S ffmpeg";
26
+ if (distro.includes("fedora"))
27
+ return "sudo dnf install -y ffmpeg";
28
+ return "sudo apt update && sudo apt install -y ffmpeg";
29
+ }
30
+ return "Install ffmpeg from https://ffmpeg.org/download.html and ensure ffmpeg is on PATH";
31
+ }
32
+ export async function resolveBinary(name, args = ["--version"]) {
33
+ try {
34
+ const binaryPath = await which(name);
35
+ const result = await execa(binaryPath, args, { reject: false });
36
+ const version = `${result.stdout}\n${result.stderr}`.trim().split("\n")[0];
37
+ return {
38
+ installed: result.exitCode === 0,
39
+ path: binaryPath,
40
+ version,
41
+ error: result.exitCode === 0 ? undefined : `${name} exited with ${result.exitCode}`
42
+ };
43
+ }
44
+ catch (error) {
45
+ return {
46
+ installed: false,
47
+ installCommand: name === "ffmpeg" ? ffmpegInstallCommand() : undefined,
48
+ error: error instanceof Error ? error.message : String(error)
49
+ };
50
+ }
51
+ }
52
+ export async function checkEnvironment() {
53
+ const nodeMajor = Number(process.versions.node.split(".")[0]);
54
+ const [ffmpeg, codex] = await Promise.all([
55
+ resolveBinary("ffmpeg", ["-version"]),
56
+ resolveBinary("codex", ["--version"])
57
+ ]);
58
+ const missingEnv = missingTtsEnv();
59
+ const nextActions = [];
60
+ if (!ffmpeg.installed) {
61
+ nextActions.push(`Install ffmpeg: ${ffmpeg.installCommand ?? ffmpegInstallCommand()}`);
62
+ }
63
+ if (!codex.installed) {
64
+ nextActions.push("Install Codex CLI before using the Codex installer integration.");
65
+ }
66
+ if (missingEnv.length > 0) {
67
+ nextActions.push(`Set TTS environment variables: ${missingEnv.join(", ")}`);
68
+ }
69
+ if (nodeMajor < 20) {
70
+ nextActions.push("Install Node.js 20 or newer.");
71
+ }
72
+ return {
73
+ ok: nodeMajor >= 20 && ffmpeg.installed && missingEnv.length === 0,
74
+ node: {
75
+ version: process.versions.node,
76
+ ok: nodeMajor >= 20
77
+ },
78
+ ffmpeg,
79
+ codex,
80
+ tts: {
81
+ configured: missingEnv.length === 0,
82
+ missingEnv
83
+ },
84
+ workspaceDir: workspaceDir(),
85
+ defaultExportDir: exportDir(),
86
+ nextActions
87
+ };
88
+ }
89
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/core/env.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export interface ExportVideoResult {
2
+ projectId: string;
3
+ exportDir: string;
4
+ files: {
5
+ video: string;
6
+ subtitles?: string;
7
+ manifest: string;
8
+ plan?: string;
9
+ };
10
+ }
11
+ export declare function exportProjectVideo(projectId: string, outputDir?: string): Promise<ExportVideoResult>;
@@ -0,0 +1,39 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { exportDir, resolveUserPath, toProjectPath } from "./paths.js";
4
+ import { markStatus, readManifest } from "./project.js";
5
+ export async function exportProjectVideo(projectId, outputDir) {
6
+ const manifest = await readManifest(projectId);
7
+ if (!manifest.outputPath) {
8
+ throw new Error("Project video is missing. Run render_video before export_video.");
9
+ }
10
+ const destinationDir = outputDir ? resolveUserPath(outputDir) : path.join(exportDir(), projectId);
11
+ await fs.mkdir(destinationDir, { recursive: true });
12
+ const videoPath = path.join(destinationDir, "final.mp4");
13
+ const manifestPath = path.join(destinationDir, "manifest.json");
14
+ const subtitlePath = manifest.subtitlePath ? path.join(destinationDir, "subtitles.srt") : undefined;
15
+ const planPath = manifest.planPath ? path.join(destinationDir, "video_plan.json") : undefined;
16
+ await markStatus(projectId, "rendered", {
17
+ exportedPath: videoPath,
18
+ exportedAt: new Date().toISOString()
19
+ });
20
+ await fs.copyFile(toProjectPath(projectId, manifest.outputPath), videoPath);
21
+ await fs.copyFile(toProjectPath(projectId, "manifest.json"), manifestPath);
22
+ if (manifest.subtitlePath && subtitlePath) {
23
+ await fs.copyFile(toProjectPath(projectId, manifest.subtitlePath), subtitlePath);
24
+ }
25
+ if (manifest.planPath && planPath) {
26
+ await fs.copyFile(toProjectPath(projectId, manifest.planPath), planPath);
27
+ }
28
+ return {
29
+ projectId,
30
+ exportDir: destinationDir,
31
+ files: {
32
+ video: videoPath,
33
+ subtitles: subtitlePath,
34
+ manifest: manifestPath,
35
+ plan: planPath
36
+ }
37
+ };
38
+ }
39
+ //# sourceMappingURL=export.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export.js","sourceRoot":"","sources":["../../src/core/export.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAaxD,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,SAAiB,EAAE,SAAkB;IAC5E,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,SAAS,CAAC,CAAC;IAC/C,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,iEAAiE,CAAC,CAAC;IACrF,CAAC;IAED,MAAM,cAAc,GAAG,SAAS,CAAC,CAAC,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,SAAS,CAAC,CAAC;IAClG,MAAM,EAAE,CAAC,KAAK,CAAC,cAAc,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEpD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;IACzD,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,eAAe,CAAC,CAAC;IAChE,MAAM,YAAY,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACpG,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAE9F,MAAM,UAAU,CAAC,SAAS,EAAE,UAAU,EAAE;QACtC,YAAY,EAAE,SAAS;QACvB,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACrC,CAAC,CAAC;IAEH,MAAM,EAAE,CAAC,QAAQ,CAAC,aAAa,CAAC,SAAS,EAAE,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,CAAC,CAAC;IAC5E,MAAM,EAAE,CAAC,QAAQ,CAAC,aAAa,CAAC,SAAS,EAAE,eAAe,CAAC,EAAE,YAAY,CAAC,CAAC;IAC3E,IAAI,QAAQ,CAAC,YAAY,IAAI,YAAY,EAAE,CAAC;QAC1C,MAAM,EAAE,CAAC,QAAQ,CAAC,aAAa,CAAC,SAAS,EAAE,QAAQ,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC,CAAC;IACnF,CAAC;IACD,IAAI,QAAQ,CAAC,QAAQ,IAAI,QAAQ,EAAE,CAAC;QAClC,MAAM,EAAE,CAAC,QAAQ,CAAC,aAAa,CAAC,SAAS,EAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAC;IAC3E,CAAC;IAED,OAAO;QACL,SAAS;QACT,SAAS,EAAE,cAAc;QACzB,KAAK,EAAE;YACL,KAAK,EAAE,SAAS;YAChB,SAAS,EAAE,YAAY;YACvB,QAAQ,EAAE,YAAY;YACtB,IAAI,EAAE,QAAQ;SACf;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,12 @@
1
+ export declare const DEFAULT_WORKSPACE_DIR: string;
2
+ export declare const DEFAULT_EXPORT_DIR: string;
3
+ export declare const PROJECTS_DIR = "projects";
4
+ export declare function workspaceDir(): string;
5
+ export declare function exportDir(): string;
6
+ export declare function resolveUserPath(input: string): string;
7
+ export declare function projectsDir(): string;
8
+ export declare function projectDir(projectId: string): string;
9
+ export declare function toProjectPath(projectId: string, relativePath: string): string;
10
+ export declare function assertSafeProjectId(projectId: string): void;
11
+ export declare function assertProjectRelativePath(relativePath: string): void;
12
+ export declare function makeProjectId(date?: Date): string;