@editframe/cli 0.10.0-beta.3 → 0.10.0-beta.5
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/VERSION.d.ts +1 -1
- package/dist/VERSION.js +1 -1
- package/dist/commands/process-file.js +14 -8
- package/dist/commands/render.js +24 -10
- package/dist/operations/getRenderInfo.d.ts +40 -4
- package/dist/operations/getRenderInfo.js +13 -0
- package/dist/operations/processRenderInfo.js +3 -0
- package/dist/operations/syncAssetsDirectory.js +2 -2
- package/package.json +5 -5
- package/src/commands/process-file.ts +19 -12
- package/src/commands/process.ts +0 -1
- package/src/commands/render.ts +20 -8
- package/src/operations/getRenderInfo.ts +14 -0
- package/src/operations/processRenderInfo.ts +3 -0
- package/src/operations/syncAssetsDirectory.ts +2 -2
package/dist/VERSION.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const VERSION = "0.10.0-beta.
|
|
1
|
+
export declare const VERSION = "0.10.0-beta.5";
|
package/dist/VERSION.js
CHANGED
|
@@ -10,26 +10,32 @@ program.command("process-file <file>").description("Upload a audio/video to Edit
|
|
|
10
10
|
const client = getClient();
|
|
11
11
|
const md5 = await md5FilePath(path);
|
|
12
12
|
const byte_size = (await stat(path)).size;
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
const unprocessedFile = await withSpinner(
|
|
14
|
+
"Creating unprocessed file record",
|
|
15
|
+
async () => await createUnprocessedFile(client, {
|
|
15
16
|
md5,
|
|
16
17
|
processes: [],
|
|
17
18
|
filename: basename(path),
|
|
18
19
|
byte_size
|
|
19
|
-
})
|
|
20
|
-
|
|
20
|
+
})
|
|
21
|
+
);
|
|
21
22
|
const readStream = createReadStream(path);
|
|
22
23
|
await withSpinner("Uploading file", async () => {
|
|
23
|
-
await uploadUnprocessedFile(
|
|
24
|
+
await uploadUnprocessedFile(
|
|
25
|
+
client,
|
|
26
|
+
unprocessedFile.id,
|
|
27
|
+
readStream,
|
|
28
|
+
byte_size
|
|
29
|
+
);
|
|
24
30
|
});
|
|
25
|
-
const
|
|
31
|
+
const updatedUnprocessedFile = await withSpinner(
|
|
26
32
|
"Marking for processing",
|
|
27
33
|
async () => {
|
|
28
|
-
return await updateUnprocessedFile(client,
|
|
34
|
+
return await updateUnprocessedFile(client, unprocessedFile.id, {
|
|
29
35
|
processes: ["isobmff"]
|
|
30
36
|
});
|
|
31
37
|
}
|
|
32
38
|
);
|
|
33
39
|
process.stderr.write("File uploaded and marked for processing.\n");
|
|
34
|
-
console.log(JSON.stringify(
|
|
40
|
+
console.log(JSON.stringify(updatedUnprocessedFile, null, 2));
|
|
35
41
|
});
|
package/dist/commands/render.js
CHANGED
|
@@ -5,7 +5,6 @@ import { PassThrough } from "node:stream";
|
|
|
5
5
|
import * as tar from "tar";
|
|
6
6
|
import { program, Option } from "commander";
|
|
7
7
|
import { parse } from "node-html-parser";
|
|
8
|
-
import { build } from "vite";
|
|
9
8
|
import { md5Directory, md5FilePath } from "@editframe/assets";
|
|
10
9
|
import { withSpinner } from "../utils/withSpinner.js";
|
|
11
10
|
import { syncAssetDirectory } from "../operations/syncAssetsDirectory.js";
|
|
@@ -13,10 +12,11 @@ import { createRender, uploadRender } from "@editframe/api";
|
|
|
13
12
|
import { launchBrowserAndWaitForSDK } from "../utils/launchBrowserAndWaitForSDK.js";
|
|
14
13
|
import { PreviewServer } from "../utils/startPreviewServer.js";
|
|
15
14
|
import { getClient } from "../utils/index.js";
|
|
16
|
-
import { getRenderInfo } from "../operations/getRenderInfo.js";
|
|
15
|
+
import { RenderInfo, getRenderInfo } from "../operations/getRenderInfo.js";
|
|
17
16
|
import { processRenderInfo } from "../operations/processRenderInfo.js";
|
|
18
17
|
import { validateVideoResolution } from "../utils/validateVideoResolution.js";
|
|
19
18
|
import { getFolderSize } from "../utils/getFolderSize.js";
|
|
19
|
+
import { spawnSync } from "node:child_process";
|
|
20
20
|
const buildAssetId = async (assetPath) => {
|
|
21
21
|
const md5Sum = await md5FilePath(assetPath);
|
|
22
22
|
const basename = path.basename(assetPath);
|
|
@@ -52,12 +52,23 @@ program.command("render [directory]").description(
|
|
|
52
52
|
}
|
|
53
53
|
await withSpinner("Building\n", async () => {
|
|
54
54
|
try {
|
|
55
|
-
await
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
55
|
+
await withSpinner("Building\n", async () => {
|
|
56
|
+
spawnSync(
|
|
57
|
+
"npx",
|
|
58
|
+
// biome-ignore format: Grouping CLI arguments
|
|
59
|
+
[
|
|
60
|
+
"vite",
|
|
61
|
+
"build",
|
|
62
|
+
directory,
|
|
63
|
+
"--clearScreen",
|
|
64
|
+
"false",
|
|
65
|
+
"--logLevel",
|
|
66
|
+
"debug"
|
|
67
|
+
],
|
|
68
|
+
{
|
|
69
|
+
stdio: "inherit"
|
|
70
|
+
}
|
|
71
|
+
);
|
|
61
72
|
});
|
|
62
73
|
} catch (error) {
|
|
63
74
|
console.error("Build failed:", error);
|
|
@@ -75,7 +86,7 @@ program.command("render [directory]").description(
|
|
|
75
86
|
headless: true
|
|
76
87
|
},
|
|
77
88
|
async (page) => {
|
|
78
|
-
const renderInfo = await page.evaluate(getRenderInfo);
|
|
89
|
+
const renderInfo = RenderInfo.parse(await page.evaluate(getRenderInfo));
|
|
79
90
|
validateVideoResolution({
|
|
80
91
|
width: renderInfo.width,
|
|
81
92
|
height: renderInfo.height
|
|
@@ -88,6 +99,9 @@ program.command("render [directory]").description(
|
|
|
88
99
|
"ef-audio, ef-video, ef-image, ef-captions"
|
|
89
100
|
);
|
|
90
101
|
for (const element of elements) {
|
|
102
|
+
if (element.hasAttribute("asset-id")) {
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
91
105
|
const src = element.getAttribute("src");
|
|
92
106
|
if (!src) {
|
|
93
107
|
continue;
|
|
@@ -126,7 +140,7 @@ program.command("render [directory]").description(
|
|
|
126
140
|
const readable = new PassThrough();
|
|
127
141
|
tarStream.pipe(readable);
|
|
128
142
|
const folderSize = await getFolderSize(distDir);
|
|
129
|
-
await uploadRender(getClient(),
|
|
143
|
+
await uploadRender(getClient(), render.id, readable, folderSize);
|
|
130
144
|
process.stderr.write("Render assets uploaded\n");
|
|
131
145
|
process.stderr.write(inspect(render));
|
|
132
146
|
process.stderr.write("\n");
|
|
@@ -1,7 +1,43 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const RenderInfo: z.ZodObject<{
|
|
3
|
+
width: z.ZodNumber;
|
|
4
|
+
height: z.ZodNumber;
|
|
5
|
+
fps: z.ZodNumber;
|
|
6
|
+
durationMs: z.ZodNumber;
|
|
7
|
+
assets: z.ZodObject<{
|
|
8
|
+
efMedia: z.ZodRecord<z.ZodString, z.ZodAny>;
|
|
9
|
+
efCaptions: z.ZodArray<z.ZodString, "many">;
|
|
10
|
+
efImage: z.ZodArray<z.ZodString, "many">;
|
|
11
|
+
}, "strip", z.ZodTypeAny, {
|
|
12
|
+
efMedia: Record<string, any>;
|
|
13
|
+
efCaptions: string[];
|
|
14
|
+
efImage: string[];
|
|
15
|
+
}, {
|
|
16
|
+
efMedia: Record<string, any>;
|
|
17
|
+
efCaptions: string[];
|
|
18
|
+
efImage: string[];
|
|
19
|
+
}>;
|
|
20
|
+
}, "strip", z.ZodTypeAny, {
|
|
21
|
+
height: number;
|
|
22
|
+
width: number;
|
|
23
|
+
fps: number;
|
|
24
|
+
assets: {
|
|
25
|
+
efMedia: Record<string, any>;
|
|
26
|
+
efCaptions: string[];
|
|
27
|
+
efImage: string[];
|
|
28
|
+
};
|
|
29
|
+
durationMs: number;
|
|
30
|
+
}, {
|
|
31
|
+
height: number;
|
|
32
|
+
width: number;
|
|
33
|
+
fps: number;
|
|
34
|
+
assets: {
|
|
35
|
+
efMedia: Record<string, any>;
|
|
36
|
+
efCaptions: string[];
|
|
37
|
+
efImage: string[];
|
|
38
|
+
};
|
|
39
|
+
durationMs: number;
|
|
40
|
+
}>;
|
|
5
41
|
export declare const getRenderInfo: () => Promise<{
|
|
6
42
|
width: number;
|
|
7
43
|
height: number;
|
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
const RenderInfo = z.object({
|
|
3
|
+
width: z.number().positive(),
|
|
4
|
+
height: z.number().positive(),
|
|
5
|
+
fps: z.number().positive(),
|
|
6
|
+
durationMs: z.number().positive(),
|
|
7
|
+
assets: z.object({
|
|
8
|
+
efMedia: z.record(z.any()),
|
|
9
|
+
efCaptions: z.array(z.string()),
|
|
10
|
+
efImage: z.array(z.string())
|
|
11
|
+
})
|
|
12
|
+
});
|
|
1
13
|
const getRenderInfo = async () => {
|
|
2
14
|
const rootTimeGroup = document.querySelector("ef-timegroup");
|
|
3
15
|
if (!rootTimeGroup) {
|
|
@@ -55,5 +67,6 @@ const getRenderInfo = async () => {
|
|
|
55
67
|
return renderInfo;
|
|
56
68
|
};
|
|
57
69
|
export {
|
|
70
|
+
RenderInfo,
|
|
58
71
|
getRenderInfo
|
|
59
72
|
};
|
|
@@ -5,6 +5,9 @@ const processRenderInfo = async (renderInfo) => {
|
|
|
5
5
|
process.stderr.write(src);
|
|
6
6
|
process.stderr.write("\n");
|
|
7
7
|
for (const trackId in tracks) {
|
|
8
|
+
process.stderr.write("Generating track: ");
|
|
9
|
+
process.stderr.write(trackId);
|
|
10
|
+
process.stderr.write("\n");
|
|
8
11
|
await generateTrack(
|
|
9
12
|
"./src/assets",
|
|
10
13
|
`./src${src}`,
|
|
@@ -219,7 +219,7 @@ const syncAssetDirectory = async (projectDirectory) => {
|
|
|
219
219
|
const readStream = createReadStream(subAssetPath);
|
|
220
220
|
await uploadFragmentIndex(
|
|
221
221
|
getClient(),
|
|
222
|
-
|
|
222
|
+
createdFile.id,
|
|
223
223
|
readStream,
|
|
224
224
|
stats.size
|
|
225
225
|
).then(() => {
|
|
@@ -257,7 +257,7 @@ const syncAssetDirectory = async (projectDirectory) => {
|
|
|
257
257
|
const stats = statSync(subAssetPath);
|
|
258
258
|
await uploadCaptionFile(
|
|
259
259
|
getClient(),
|
|
260
|
-
|
|
260
|
+
createdFile.id,
|
|
261
261
|
readStream,
|
|
262
262
|
stats.size
|
|
263
263
|
).then(() => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@editframe/cli",
|
|
3
|
-
"version": "0.10.0-beta.
|
|
3
|
+
"version": "0.10.0-beta.5",
|
|
4
4
|
"description": "Command line interface for EditFrame",
|
|
5
5
|
"bin": {
|
|
6
6
|
"editframe": "./dist/index.js"
|
|
@@ -23,10 +23,10 @@
|
|
|
23
23
|
"vite-tsconfig-paths": "^4.3.2"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@editframe/api": "0.10.0-beta.
|
|
27
|
-
"@editframe/assets": "0.10.0-beta.
|
|
28
|
-
"@editframe/elements": "0.10.0-beta.
|
|
29
|
-
"@editframe/vite-plugin": "0.10.0-beta.
|
|
26
|
+
"@editframe/api": "0.10.0-beta.5",
|
|
27
|
+
"@editframe/assets": "0.10.0-beta.5",
|
|
28
|
+
"@editframe/elements": "0.10.0-beta.5",
|
|
29
|
+
"@editframe/vite-plugin": "0.10.0-beta.5",
|
|
30
30
|
"@inquirer/prompts": "^5.3.8",
|
|
31
31
|
"axios": "^1.6.8",
|
|
32
32
|
"chalk": "^5.3.0",
|
|
@@ -24,25 +24,32 @@ program
|
|
|
24
24
|
|
|
25
25
|
const byte_size = (await stat(path)).size;
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
27
|
+
const unprocessedFile = await withSpinner(
|
|
28
|
+
"Creating unprocessed file record",
|
|
29
|
+
async () =>
|
|
30
|
+
await createUnprocessedFile(client, {
|
|
31
|
+
md5,
|
|
32
|
+
processes: [],
|
|
33
|
+
filename: basename(path),
|
|
34
|
+
byte_size,
|
|
35
|
+
}),
|
|
36
|
+
);
|
|
35
37
|
|
|
36
38
|
const readStream = createReadStream(path);
|
|
37
39
|
|
|
38
40
|
await withSpinner("Uploading file", async () => {
|
|
39
|
-
await uploadUnprocessedFile(
|
|
41
|
+
await uploadUnprocessedFile(
|
|
42
|
+
client,
|
|
43
|
+
unprocessedFile.id,
|
|
44
|
+
readStream,
|
|
45
|
+
byte_size,
|
|
46
|
+
);
|
|
40
47
|
});
|
|
41
48
|
|
|
42
|
-
const
|
|
49
|
+
const updatedUnprocessedFile = await withSpinner(
|
|
43
50
|
"Marking for processing",
|
|
44
51
|
async () => {
|
|
45
|
-
return await updateUnprocessedFile(client,
|
|
52
|
+
return await updateUnprocessedFile(client, unprocessedFile.id, {
|
|
46
53
|
processes: ["isobmff"],
|
|
47
54
|
});
|
|
48
55
|
},
|
|
@@ -50,5 +57,5 @@ program
|
|
|
50
57
|
|
|
51
58
|
process.stderr.write("File uploaded and marked for processing.\n");
|
|
52
59
|
|
|
53
|
-
console.log(JSON.stringify(
|
|
60
|
+
console.log(JSON.stringify(updatedUnprocessedFile, null, 2));
|
|
54
61
|
});
|
package/src/commands/process.ts
CHANGED
|
@@ -17,7 +17,6 @@ program
|
|
|
17
17
|
.action(async (directory) => {
|
|
18
18
|
directory ??= ".";
|
|
19
19
|
|
|
20
|
-
// const srcDir = path.join(directory, "src");
|
|
21
20
|
const distDir = path.join(directory, "dist");
|
|
22
21
|
await withSpinner("Building\n", async () => {
|
|
23
22
|
spawnSync("npx", ["vite", "build", directory], {
|
package/src/commands/render.ts
CHANGED
|
@@ -6,7 +6,6 @@ import { PassThrough } from "node:stream";
|
|
|
6
6
|
import * as tar from "tar";
|
|
7
7
|
import { program, Option } from "commander";
|
|
8
8
|
import { parse as parseHTML } from "node-html-parser";
|
|
9
|
-
import { build } from "vite";
|
|
10
9
|
|
|
11
10
|
import { md5Directory, md5FilePath } from "@editframe/assets";
|
|
12
11
|
|
|
@@ -16,10 +15,11 @@ import { createRender, uploadRender } from "@editframe/api";
|
|
|
16
15
|
import { launchBrowserAndWaitForSDK } from "../utils/launchBrowserAndWaitForSDK.ts";
|
|
17
16
|
import { PreviewServer } from "../utils/startPreviewServer.ts";
|
|
18
17
|
import { getClient } from "../utils/index.ts";
|
|
19
|
-
import { getRenderInfo } from "../operations/getRenderInfo.ts";
|
|
18
|
+
import { RenderInfo, getRenderInfo } from "../operations/getRenderInfo.ts";
|
|
20
19
|
import { processRenderInfo } from "../operations/processRenderInfo.ts";
|
|
21
20
|
import { validateVideoResolution } from "../utils/validateVideoResolution.ts";
|
|
22
21
|
import { getFolderSize } from "../utils/getFolderSize.ts";
|
|
22
|
+
import { spawnSync } from "node:child_process";
|
|
23
23
|
|
|
24
24
|
interface StrategyBuilder {
|
|
25
25
|
buildAssetId: (assetPath: string) => Promise<string>;
|
|
@@ -74,10 +74,19 @@ program
|
|
|
74
74
|
}
|
|
75
75
|
await withSpinner("Building\n", async () => {
|
|
76
76
|
try {
|
|
77
|
-
await
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
77
|
+
await withSpinner("Building\n", async () => {
|
|
78
|
+
spawnSync(
|
|
79
|
+
"npx",
|
|
80
|
+
// biome-ignore format: Grouping CLI arguments
|
|
81
|
+
[
|
|
82
|
+
"vite", "build", directory,
|
|
83
|
+
"--clearScreen", "false",
|
|
84
|
+
"--logLevel", "debug",
|
|
85
|
+
],
|
|
86
|
+
{
|
|
87
|
+
stdio: "inherit",
|
|
88
|
+
},
|
|
89
|
+
);
|
|
81
90
|
});
|
|
82
91
|
} catch (error) {
|
|
83
92
|
console.error("Build failed:", error);
|
|
@@ -96,7 +105,7 @@ program
|
|
|
96
105
|
headless: true,
|
|
97
106
|
},
|
|
98
107
|
async (page) => {
|
|
99
|
-
const renderInfo = await page.evaluate(getRenderInfo);
|
|
108
|
+
const renderInfo = RenderInfo.parse(await page.evaluate(getRenderInfo));
|
|
100
109
|
|
|
101
110
|
validateVideoResolution({
|
|
102
111
|
width: renderInfo.width,
|
|
@@ -112,6 +121,9 @@ program
|
|
|
112
121
|
"ef-audio, ef-video, ef-image, ef-captions",
|
|
113
122
|
);
|
|
114
123
|
for (const element of elements) {
|
|
124
|
+
if (element.hasAttribute("asset-id")) {
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
115
127
|
const src = element.getAttribute("src");
|
|
116
128
|
if (!src) {
|
|
117
129
|
continue;
|
|
@@ -159,7 +171,7 @@ program
|
|
|
159
171
|
const readable = new PassThrough();
|
|
160
172
|
tarStream.pipe(readable);
|
|
161
173
|
const folderSize = await getFolderSize(distDir);
|
|
162
|
-
await uploadRender(getClient(),
|
|
174
|
+
await uploadRender(getClient(), render.id, readable, folderSize);
|
|
163
175
|
process.stderr.write("Render assets uploaded\n");
|
|
164
176
|
process.stderr.write(inspect(render));
|
|
165
177
|
process.stderr.write("\n");
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
* RUN IN A WEB BROWSER. LOGS ARE CAPTURED AND RE-LOGGED.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
|
|
6
8
|
import type {
|
|
7
9
|
EFCaptions,
|
|
8
10
|
EFImage,
|
|
@@ -10,6 +12,18 @@ import type {
|
|
|
10
12
|
EFTimegroup,
|
|
11
13
|
} from "@editframe/elements";
|
|
12
14
|
|
|
15
|
+
export const RenderInfo = z.object({
|
|
16
|
+
width: z.number().positive(),
|
|
17
|
+
height: z.number().positive(),
|
|
18
|
+
fps: z.number().positive(),
|
|
19
|
+
durationMs: z.number().positive(),
|
|
20
|
+
assets: z.object({
|
|
21
|
+
efMedia: z.record(z.any()),
|
|
22
|
+
efCaptions: z.array(z.string()),
|
|
23
|
+
efImage: z.array(z.string()),
|
|
24
|
+
}),
|
|
25
|
+
});
|
|
26
|
+
|
|
13
27
|
export const getRenderInfo = async () => {
|
|
14
28
|
const rootTimeGroup = document.querySelector("ef-timegroup") as
|
|
15
29
|
| EFTimegroup
|
|
@@ -13,6 +13,9 @@ export const processRenderInfo = async (
|
|
|
13
13
|
process.stderr.write(src);
|
|
14
14
|
process.stderr.write("\n");
|
|
15
15
|
for (const trackId in tracks) {
|
|
16
|
+
process.stderr.write("Generating track: ");
|
|
17
|
+
process.stderr.write(trackId);
|
|
18
|
+
process.stderr.write("\n");
|
|
16
19
|
await generateTrack(
|
|
17
20
|
"./src/assets",
|
|
18
21
|
`./src${src}`,
|
|
@@ -269,7 +269,7 @@ export const syncAssetDirectory = async (
|
|
|
269
269
|
const readStream = createReadStream(subAssetPath);
|
|
270
270
|
await uploadFragmentIndex(
|
|
271
271
|
getClient(),
|
|
272
|
-
|
|
272
|
+
createdFile.id,
|
|
273
273
|
readStream,
|
|
274
274
|
stats.size,
|
|
275
275
|
)
|
|
@@ -309,7 +309,7 @@ export const syncAssetDirectory = async (
|
|
|
309
309
|
const stats = statSync(subAssetPath);
|
|
310
310
|
await uploadCaptionFile(
|
|
311
311
|
getClient(),
|
|
312
|
-
|
|
312
|
+
createdFile.id,
|
|
313
313
|
readStream,
|
|
314
314
|
stats.size,
|
|
315
315
|
)
|