@editframe/cli 0.7.0-beta.11 → 0.7.0-beta.12
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 -0
- package/dist/VERSION.js +1 -1
- package/dist/commands/auth.d.ts +9 -0
- package/dist/commands/check.d.ts +1 -0
- package/dist/commands/preview.d.ts +1 -0
- package/dist/commands/process-file.d.ts +1 -0
- package/dist/commands/process-file.js +27 -0
- package/dist/commands/process.d.ts +1 -0
- package/dist/commands/render.d.ts +1 -0
- package/dist/commands/render.js +3 -3
- package/dist/commands/sync.d.ts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/operations/getRenderInfo.d.ts +15 -0
- package/dist/operations/processRenderInfo.d.ts +3 -0
- package/dist/operations/syncAssetsDirectory.d.ts +1 -0
- package/dist/utils/attachWorkbench.d.ts +3 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/launchBrowserAndWaitForSDK.d.ts +10 -0
- package/dist/utils/startDevServer.d.ts +8 -0
- package/dist/utils/startPreviewServer.d.ts +8 -0
- package/dist/utils/validateVideoResolution.d.ts +9 -0
- package/dist/utils/validateVideoResolution.js +6 -4
- package/dist/utils/withSpinner.d.ts +1 -0
- package/package.json +7 -7
- package/src/commands/auth.ts +1 -1
- package/src/commands/process-file.ts +43 -0
- package/src/commands/process.ts +5 -5
- package/src/commands/render.ts +10 -10
- package/src/commands/sync.ts +1 -1
- package/src/operations/processRenderInfo.ts +1 -1
- package/src/operations/syncAssetsDirectory.ts +1 -1
- package/src/utils/launchBrowserAndWaitForSDK.ts +1 -1
- package/src/utils/startDevServer.ts +1 -1
- package/src/utils/startPreviewServer.ts +1 -1
- package/src/utils/validateVideoResolution.ts +7 -4
- package/dist/VERSION.cjs +0 -4
- package/dist/commands/auth.cjs +0 -33
- package/dist/commands/check.cjs +0 -115
- package/dist/commands/preview.cjs +0 -6
- package/dist/commands/process.cjs +0 -36
- package/dist/commands/render.cjs +0 -169
- package/dist/commands/sync.cjs +0 -6
- package/dist/index.cjs +0 -17
- package/dist/operations/getRenderInfo.cjs +0 -59
- package/dist/operations/processRenderInfo.cjs +0 -30
- package/dist/operations/syncAssetsDirectory.cjs +0 -250
- package/dist/utils/index.cjs +0 -14
- package/dist/utils/launchBrowserAndWaitForSDK.cjs +0 -49
- package/dist/utils/startPreviewServer.cjs +0 -38
- package/dist/utils/validateVideoResolution.cjs +0 -27
- package/dist/utils/withSpinner.cjs +0 -15
package/dist/commands/render.cjs
DELETED
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
const path = require("node:path");
|
|
3
|
-
const fs = require("node:fs/promises");
|
|
4
|
-
const tar = require("tar");
|
|
5
|
-
const commander = require("commander");
|
|
6
|
-
const nodeHtmlParser = require("node-html-parser");
|
|
7
|
-
const vite = require("vite");
|
|
8
|
-
const assets = require("@editframe/assets");
|
|
9
|
-
const withSpinner = require("../utils/withSpinner.cjs");
|
|
10
|
-
const api = require("@editframe/api");
|
|
11
|
-
const launchBrowserAndWaitForSDK = require("../utils/launchBrowserAndWaitForSDK.cjs");
|
|
12
|
-
const startPreviewServer = require("../utils/startPreviewServer.cjs");
|
|
13
|
-
const node_stream = require("node:stream");
|
|
14
|
-
const syncAssetsDirectory = require("../operations/syncAssetsDirectory.cjs");
|
|
15
|
-
const index = require("../utils/index.cjs");
|
|
16
|
-
const getRenderInfo = require("../operations/getRenderInfo.cjs");
|
|
17
|
-
const processRenderInfo = require("../operations/processRenderInfo.cjs");
|
|
18
|
-
const node_util = require("node:util");
|
|
19
|
-
const validateVideoResolution = require("../utils/validateVideoResolution.cjs");
|
|
20
|
-
function _interopNamespaceDefault(e) {
|
|
21
|
-
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
22
|
-
if (e) {
|
|
23
|
-
for (const k in e) {
|
|
24
|
-
if (k !== "default") {
|
|
25
|
-
const d = Object.getOwnPropertyDescriptor(e, k);
|
|
26
|
-
Object.defineProperty(n, k, d.get ? d : {
|
|
27
|
-
enumerable: true,
|
|
28
|
-
get: () => e[k]
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
n.default = e;
|
|
34
|
-
return Object.freeze(n);
|
|
35
|
-
}
|
|
36
|
-
const tar__namespace = /* @__PURE__ */ _interopNamespaceDefault(tar);
|
|
37
|
-
const buildProductionUrl = async (origin, tagName, assetPath) => {
|
|
38
|
-
const md5Sum = await assets.md5FilePath(assetPath);
|
|
39
|
-
const basename = path.basename(assetPath);
|
|
40
|
-
switch (tagName) {
|
|
41
|
-
case "ef-audio":
|
|
42
|
-
case "ef-video": {
|
|
43
|
-
return `${origin}/api/video2/isobmff_files/${md5Sum}/${basename}`;
|
|
44
|
-
}
|
|
45
|
-
case "ef-captions": {
|
|
46
|
-
return `${origin}/api/video2/caption_files/${md5Sum}/${basename}`;
|
|
47
|
-
}
|
|
48
|
-
case "ef-image": {
|
|
49
|
-
return `${origin}/api/video2/image_files/${md5Sum}/${basename}`;
|
|
50
|
-
}
|
|
51
|
-
default: {
|
|
52
|
-
return assetPath;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
class V1Builder {
|
|
57
|
-
async buildProductionUrl(tagName, assetPath) {
|
|
58
|
-
return buildProductionUrl("editframe://", tagName, assetPath);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
class V2Builder {
|
|
62
|
-
async buildProductionUrl(tagName, assetPath) {
|
|
63
|
-
const efRenderHost = commander.program.opts().efRenderHost;
|
|
64
|
-
return buildProductionUrl(efRenderHost, tagName, assetPath);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
const strategyBuilders = {
|
|
68
|
-
v1: new V1Builder(),
|
|
69
|
-
v2: new V2Builder()
|
|
70
|
-
};
|
|
71
|
-
commander.program.command("render [directory]").description(
|
|
72
|
-
"Render a directory's index.html file as a video in the editframe cloud"
|
|
73
|
-
).addOption(
|
|
74
|
-
new commander.Option("-s, --strategy <strategy>", "Render strategy").choices(["v1", "v2"]).default("v1")
|
|
75
|
-
).action(async (directory, options) => {
|
|
76
|
-
directory ??= ".";
|
|
77
|
-
await syncAssetsDirectory.syncAssetDirectory(directory);
|
|
78
|
-
const srcDir = path.join(directory, "src");
|
|
79
|
-
const distDir = path.join(directory, "dist");
|
|
80
|
-
const builder = strategyBuilders[options.strategy];
|
|
81
|
-
if (!builder) {
|
|
82
|
-
console.error("Invalid strategy", options.strategy);
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
await withSpinner.withSpinner("Building\n", async () => {
|
|
86
|
-
try {
|
|
87
|
-
await vite.build({
|
|
88
|
-
root: directory,
|
|
89
|
-
logLevel: "info",
|
|
90
|
-
// Optional: adjust log level as needed
|
|
91
|
-
clearScreen: false
|
|
92
|
-
// Optional: keep console output clean
|
|
93
|
-
});
|
|
94
|
-
} catch (error) {
|
|
95
|
-
console.error("Build failed:", error);
|
|
96
|
-
}
|
|
97
|
-
});
|
|
98
|
-
const previewServer = await startPreviewServer.PreviewServer.start(distDir);
|
|
99
|
-
process.stderr.write("Preview server started at:");
|
|
100
|
-
process.stderr.write(previewServer.url);
|
|
101
|
-
process.stderr.write("\n");
|
|
102
|
-
await launchBrowserAndWaitForSDK.launchBrowserAndWaitForSDK(
|
|
103
|
-
{
|
|
104
|
-
url: previewServer.url,
|
|
105
|
-
efInteractive: false,
|
|
106
|
-
interactive: false,
|
|
107
|
-
headless: true
|
|
108
|
-
},
|
|
109
|
-
async (page) => {
|
|
110
|
-
const renderInfo = await page.evaluate(getRenderInfo.getRenderInfo);
|
|
111
|
-
validateVideoResolution.validateVideoResolution({
|
|
112
|
-
width: renderInfo.width,
|
|
113
|
-
height: renderInfo.height
|
|
114
|
-
});
|
|
115
|
-
await processRenderInfo.processRenderInfo(renderInfo);
|
|
116
|
-
const doc = nodeHtmlParser.parse(
|
|
117
|
-
await fs.readFile(path.join(distDir, "index.html"), "utf-8")
|
|
118
|
-
);
|
|
119
|
-
const elements = doc.querySelectorAll(
|
|
120
|
-
"ef-audio, ef-video, ef-image, ef-captions"
|
|
121
|
-
);
|
|
122
|
-
for (const element of elements) {
|
|
123
|
-
const src = element.getAttribute("src");
|
|
124
|
-
if (!src) {
|
|
125
|
-
continue;
|
|
126
|
-
}
|
|
127
|
-
const assetPath = path.join(srcDir, src);
|
|
128
|
-
element.setAttribute(
|
|
129
|
-
"src",
|
|
130
|
-
await builder.buildProductionUrl(
|
|
131
|
-
element.tagName.toLowerCase(),
|
|
132
|
-
assetPath
|
|
133
|
-
)
|
|
134
|
-
);
|
|
135
|
-
}
|
|
136
|
-
await fs.writeFile(path.join(distDir, "index.html"), doc.toString());
|
|
137
|
-
const md5 = await assets.md5Directory(distDir);
|
|
138
|
-
const render = await api.createRender(index.getClient(), {
|
|
139
|
-
id: md5,
|
|
140
|
-
width: renderInfo.width,
|
|
141
|
-
height: renderInfo.height,
|
|
142
|
-
fps: renderInfo.fps,
|
|
143
|
-
duration_ms: renderInfo.durationMs,
|
|
144
|
-
work_slice_ms: 4e3,
|
|
145
|
-
strategy: options.strategy
|
|
146
|
-
});
|
|
147
|
-
if (render?.status !== "created") {
|
|
148
|
-
process.stderr.write(
|
|
149
|
-
`Render is in '${render?.status}' status. It cannot be recreated while in this status.
|
|
150
|
-
`
|
|
151
|
-
);
|
|
152
|
-
return;
|
|
153
|
-
}
|
|
154
|
-
const tarStream = tar__namespace.create(
|
|
155
|
-
{
|
|
156
|
-
gzip: true,
|
|
157
|
-
cwd: distDir
|
|
158
|
-
},
|
|
159
|
-
["."]
|
|
160
|
-
);
|
|
161
|
-
const readable = new node_stream.PassThrough();
|
|
162
|
-
tarStream.pipe(readable);
|
|
163
|
-
await api.uploadRender(index.getClient(), md5, readable);
|
|
164
|
-
process.stderr.write("Render assets uploaded\n");
|
|
165
|
-
process.stderr.write(node_util.inspect(render));
|
|
166
|
-
process.stderr.write("\n");
|
|
167
|
-
}
|
|
168
|
-
);
|
|
169
|
-
});
|
package/dist/commands/sync.cjs
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
const commander = require("commander");
|
|
3
|
-
const syncAssetsDirectory = require("../operations/syncAssetsDirectory.cjs");
|
|
4
|
-
commander.program.command("sync").description("Sync assets to Editframe servers for rendering").argument("[directory]", "Path to project directory to sync.").action(async (projectDirectory = ".") => {
|
|
5
|
-
await syncAssetsDirectory.syncAssetDirectory(projectDirectory);
|
|
6
|
-
});
|
package/dist/index.cjs
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
"use strict";
|
|
3
|
-
require("dotenv/config");
|
|
4
|
-
const commander = require("commander");
|
|
5
|
-
const VERSION = require("./VERSION.cjs");
|
|
6
|
-
require("./commands/auth.cjs");
|
|
7
|
-
require("./commands/sync.cjs");
|
|
8
|
-
require("./commands/render.cjs");
|
|
9
|
-
require("./commands/preview.cjs");
|
|
10
|
-
require("./commands/process.cjs");
|
|
11
|
-
require("./commands/check.cjs");
|
|
12
|
-
commander.program.name("editframe").addOption(new commander.Option("-t, --token <token>", "API Token").env("EF_TOKEN")).addOption(
|
|
13
|
-
new commander.Option("--ef-host <host>", "Editframe Host").env("EF_HOST").default("https://editframe.dev")
|
|
14
|
-
).addOption(
|
|
15
|
-
new commander.Option("--ef-render-host <host>", "Editframe Render Host").env("EF_RENDER_HOST").default("https://editframe.dev")
|
|
16
|
-
).version(VERSION.VERSION);
|
|
17
|
-
commander.program.parse(process.argv);
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const getRenderInfo = async () => {
|
|
4
|
-
const rootTimeGroup = document.querySelector("ef-timegroup");
|
|
5
|
-
if (!rootTimeGroup) {
|
|
6
|
-
throw new Error("No ef-timegroup found");
|
|
7
|
-
}
|
|
8
|
-
console.error("Waiting for media durations", rootTimeGroup);
|
|
9
|
-
await rootTimeGroup.waitForMediaDurations();
|
|
10
|
-
const width = rootTimeGroup.clientWidth;
|
|
11
|
-
const height = rootTimeGroup.clientHeight;
|
|
12
|
-
const fps = 30;
|
|
13
|
-
const durationMs = Math.round(rootTimeGroup.durationMs);
|
|
14
|
-
const elements = document.querySelectorAll(
|
|
15
|
-
"ef-audio, ef-video, ef-image, ef-captions"
|
|
16
|
-
);
|
|
17
|
-
const assets = {
|
|
18
|
-
efMedia: {},
|
|
19
|
-
efCaptions: /* @__PURE__ */ new Set(),
|
|
20
|
-
efImage: /* @__PURE__ */ new Set()
|
|
21
|
-
};
|
|
22
|
-
for (const element of elements) {
|
|
23
|
-
switch (element.tagName) {
|
|
24
|
-
case "EF-AUDIO":
|
|
25
|
-
case "EF-VIDEO": {
|
|
26
|
-
const src = element.src;
|
|
27
|
-
console.error("Processing element", element.tagName, src);
|
|
28
|
-
assets.efMedia[src] = element.trackFragmentIndexLoader.value;
|
|
29
|
-
break;
|
|
30
|
-
}
|
|
31
|
-
case "EF-IMAGE": {
|
|
32
|
-
const src = element.src;
|
|
33
|
-
console.error("Processing element", element.tagName, src);
|
|
34
|
-
assets.efImage.add(src);
|
|
35
|
-
break;
|
|
36
|
-
}
|
|
37
|
-
case "EF-CAPTIONS": {
|
|
38
|
-
const src = element.targetElement?.src;
|
|
39
|
-
console.error("Processing element", element.tagName, src);
|
|
40
|
-
assets.efCaptions.add(src);
|
|
41
|
-
break;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
const renderInfo = {
|
|
46
|
-
width,
|
|
47
|
-
height,
|
|
48
|
-
fps,
|
|
49
|
-
durationMs,
|
|
50
|
-
assets: {
|
|
51
|
-
efMedia: assets.efMedia,
|
|
52
|
-
efCaptions: Array.from(assets.efCaptions),
|
|
53
|
-
efImage: Array.from(assets.efImage)
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
console.error("Render info", renderInfo);
|
|
57
|
-
return renderInfo;
|
|
58
|
-
};
|
|
59
|
-
exports.getRenderInfo = getRenderInfo;
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const assets = require("@editframe/assets");
|
|
4
|
-
const processRenderInfo = async (renderInfo) => {
|
|
5
|
-
for (const [src, tracks] of Object.entries(renderInfo.assets.efMedia)) {
|
|
6
|
-
process.stderr.write("Processing media asset: ");
|
|
7
|
-
process.stderr.write(src);
|
|
8
|
-
process.stderr.write("\n");
|
|
9
|
-
for (const trackId in tracks) {
|
|
10
|
-
await assets.generateTrack(
|
|
11
|
-
"./src/assets",
|
|
12
|
-
`./src${src}`,
|
|
13
|
-
`src?trackId=${trackId}`
|
|
14
|
-
);
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
for (const imageAsset of renderInfo.assets.efImage) {
|
|
18
|
-
process.stderr.write("Processing image asset: ");
|
|
19
|
-
process.stderr.write(imageAsset);
|
|
20
|
-
process.stderr.write("\n");
|
|
21
|
-
await assets.cacheImage("./src/assets", `./src${imageAsset}`);
|
|
22
|
-
}
|
|
23
|
-
for (const captionsAsset of renderInfo.assets.efCaptions) {
|
|
24
|
-
process.stderr.write("Processing captions asset: ");
|
|
25
|
-
process.stderr.write(captionsAsset);
|
|
26
|
-
process.stderr.write("\n");
|
|
27
|
-
await assets.findOrCreateCaptions("./src/assets", `./src${captionsAsset}`);
|
|
28
|
-
}
|
|
29
|
-
};
|
|
30
|
-
exports.processRenderInfo = processRenderInfo;
|
|
@@ -1,250 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const assets = require("@editframe/assets");
|
|
4
|
-
const fs = require("node:fs/promises");
|
|
5
|
-
const path = require("node:path");
|
|
6
|
-
const api = require("@editframe/api");
|
|
7
|
-
const node_fs = require("node:fs");
|
|
8
|
-
const index = require("../utils/index.cjs");
|
|
9
|
-
const imageMatch = /\.(png|jpe?g|gif|webp)$/i;
|
|
10
|
-
const trackMatch = /\.track-[\d]+.mp4$/i;
|
|
11
|
-
const fragmentIndexMatch = /\.tracks.json$/i;
|
|
12
|
-
const captionsMatch = /\.captions.json$/i;
|
|
13
|
-
class SyncStatus {
|
|
14
|
-
constructor(assetPath) {
|
|
15
|
-
this.assetPath = assetPath;
|
|
16
|
-
this.infoPath = `${this.assetPath}.info`;
|
|
17
|
-
}
|
|
18
|
-
async isSynced() {
|
|
19
|
-
const result = await fs.stat(this.infoPath).catch((error) => {
|
|
20
|
-
if (error.code === "ENOENT") {
|
|
21
|
-
return false;
|
|
22
|
-
}
|
|
23
|
-
throw error;
|
|
24
|
-
});
|
|
25
|
-
return !!result;
|
|
26
|
-
}
|
|
27
|
-
async markSynced() {
|
|
28
|
-
process.stderr.write(`✏️ Marking asset as synced: ${this.assetPath}
|
|
29
|
-
`);
|
|
30
|
-
await fs.writeFile(this.infoPath, "{}", "utf-8");
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
const syncAssetDirectory = async (projectDirectory) => {
|
|
34
|
-
const fullPath = path.join(
|
|
35
|
-
process.cwd(),
|
|
36
|
-
projectDirectory,
|
|
37
|
-
"src",
|
|
38
|
-
"assets",
|
|
39
|
-
".cache"
|
|
40
|
-
);
|
|
41
|
-
const stat = await fs.stat(fullPath).catch((error) => {
|
|
42
|
-
if (error.code === "ENOENT") {
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
throw error;
|
|
46
|
-
});
|
|
47
|
-
if (!stat?.isDirectory()) {
|
|
48
|
-
console.error(`No assets cache directory found at ${fullPath}`);
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
const assets$1 = await fs.readdir(fullPath);
|
|
52
|
-
process.stderr.write(`Syncing asset dir: ${fullPath}
|
|
53
|
-
`);
|
|
54
|
-
for (const asset of assets$1) {
|
|
55
|
-
process.stderr.write(`Syncing asset: ${asset}
|
|
56
|
-
`);
|
|
57
|
-
const assetDir = path.join(fullPath, asset);
|
|
58
|
-
const stat2 = await fs.stat(assetDir);
|
|
59
|
-
if (!stat2.isDirectory()) {
|
|
60
|
-
process.stderr.write("Invalid asset. Did not find asset directory.\n");
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
const subAssets = await fs.readdir(assetDir);
|
|
64
|
-
for (const subAsset of subAssets) {
|
|
65
|
-
if (subAsset.endsWith(".info")) {
|
|
66
|
-
continue;
|
|
67
|
-
}
|
|
68
|
-
const subAssetPath = path.join(assetDir, subAsset);
|
|
69
|
-
const syncStatus = new SyncStatus(subAssetPath);
|
|
70
|
-
if (await syncStatus.isSynced()) {
|
|
71
|
-
process.stderr.write(
|
|
72
|
-
` ✔ Sub-asset has already been synced: ${subAsset}
|
|
73
|
-
`
|
|
74
|
-
);
|
|
75
|
-
continue;
|
|
76
|
-
}
|
|
77
|
-
switch (true) {
|
|
78
|
-
case imageMatch.test(subAsset): {
|
|
79
|
-
const probeResult = await assets.Probe.probePath(subAssetPath);
|
|
80
|
-
const [videoProbe] = probeResult.videoStreams;
|
|
81
|
-
if (!videoProbe) {
|
|
82
|
-
process.stderr.write(
|
|
83
|
-
`🚫 No video stream found in image: ${subAsset}
|
|
84
|
-
`
|
|
85
|
-
);
|
|
86
|
-
break;
|
|
87
|
-
}
|
|
88
|
-
const ext = path.extname(subAsset).slice(1);
|
|
89
|
-
if (!(ext === "jpg" || ext === "jpeg" || ext === "png" || ext === "webp")) {
|
|
90
|
-
process.stderr.write(`🚫 Invalid image format: ${subAsset}
|
|
91
|
-
`);
|
|
92
|
-
break;
|
|
93
|
-
}
|
|
94
|
-
process.stderr.write(`🖼️ Syncing image: ${subAsset}
|
|
95
|
-
`);
|
|
96
|
-
const created = await api.createImageFile(index.getClient(), {
|
|
97
|
-
id: asset,
|
|
98
|
-
filename: subAsset,
|
|
99
|
-
width: videoProbe.width,
|
|
100
|
-
height: videoProbe.height,
|
|
101
|
-
mime_type: `image/${ext}`
|
|
102
|
-
});
|
|
103
|
-
if (created) {
|
|
104
|
-
if (created.complete) {
|
|
105
|
-
process.stderr.write(" ✔ Image has already been synced.\n");
|
|
106
|
-
} else {
|
|
107
|
-
await api.uploadImageFile(
|
|
108
|
-
index.getClient(),
|
|
109
|
-
created.id,
|
|
110
|
-
node_fs.createReadStream(subAssetPath)
|
|
111
|
-
);
|
|
112
|
-
process.stderr.write(" ✅ Image has been synced.\n");
|
|
113
|
-
}
|
|
114
|
-
await syncStatus.markSynced();
|
|
115
|
-
}
|
|
116
|
-
break;
|
|
117
|
-
}
|
|
118
|
-
case trackMatch.test(subAsset): {
|
|
119
|
-
process.stderr.write(`📼 Syncing a/v track: ${subAsset}
|
|
120
|
-
`);
|
|
121
|
-
const createdFile = await api.createISOBMFFFile(index.getClient(), {
|
|
122
|
-
id: asset,
|
|
123
|
-
filename: subAsset.replace(/\.track-[\d]+.mp4$/, "")
|
|
124
|
-
});
|
|
125
|
-
if (createdFile) {
|
|
126
|
-
const probe = await assets.Probe.probePath(subAssetPath);
|
|
127
|
-
const trackId = subAsset.match(/track-([\d]+).mp4/)?.[1];
|
|
128
|
-
if (!trackId) {
|
|
129
|
-
process.stderr.write(
|
|
130
|
-
`🚫 No track ID found for track: ${subAsset}
|
|
131
|
-
`
|
|
132
|
-
);
|
|
133
|
-
break;
|
|
134
|
-
}
|
|
135
|
-
const [track] = probe.streams;
|
|
136
|
-
if (!track) {
|
|
137
|
-
process.stderr.write(
|
|
138
|
-
`🚫 No track stream found in track: ${subAsset}
|
|
139
|
-
`
|
|
140
|
-
);
|
|
141
|
-
break;
|
|
142
|
-
}
|
|
143
|
-
if (track.duration === void 0) {
|
|
144
|
-
process.stderr.write(
|
|
145
|
-
`🚫 No duration found in track: ${subAsset}
|
|
146
|
-
`
|
|
147
|
-
);
|
|
148
|
-
break;
|
|
149
|
-
}
|
|
150
|
-
const stat3 = await fs.stat(subAssetPath);
|
|
151
|
-
const createPayload = track.codec_type === "audio" ? {
|
|
152
|
-
type: track.codec_type,
|
|
153
|
-
file_id: asset,
|
|
154
|
-
track_id: Number(trackId),
|
|
155
|
-
probe_info: track,
|
|
156
|
-
duration_ms: Math.round(track.duration * 1e3),
|
|
157
|
-
codec_name: track.codec_name,
|
|
158
|
-
byte_size: stat3.size
|
|
159
|
-
} : {
|
|
160
|
-
type: track.codec_type,
|
|
161
|
-
file_id: asset,
|
|
162
|
-
track_id: Number(trackId),
|
|
163
|
-
probe_info: track,
|
|
164
|
-
duration_ms: Math.round(track.duration * 1e3),
|
|
165
|
-
codec_name: track.codec_name,
|
|
166
|
-
byte_size: stat3.size
|
|
167
|
-
};
|
|
168
|
-
const createdTrack = await api.createISOBMFFTrack(
|
|
169
|
-
index.getClient(),
|
|
170
|
-
createPayload
|
|
171
|
-
);
|
|
172
|
-
if (createdTrack) {
|
|
173
|
-
if (createdTrack.last_received_byte === createdTrack.byte_size - 1) {
|
|
174
|
-
process.stderr.write(" ✔ Track has already been synced.\n");
|
|
175
|
-
} else {
|
|
176
|
-
await api.uploadISOBMFFTrack(
|
|
177
|
-
index.getClient(),
|
|
178
|
-
createdFile.id,
|
|
179
|
-
Number(trackId),
|
|
180
|
-
node_fs.createReadStream(subAssetPath)
|
|
181
|
-
);
|
|
182
|
-
process.stderr.write(" ✅ Track has been synced.\n");
|
|
183
|
-
}
|
|
184
|
-
await syncStatus.markSynced();
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
break;
|
|
188
|
-
}
|
|
189
|
-
case fragmentIndexMatch.test(subAsset): {
|
|
190
|
-
process.stderr.write(`📋 Syncing fragment index: ${subAsset}
|
|
191
|
-
`);
|
|
192
|
-
const createdFile = await api.createISOBMFFFile(index.getClient(), {
|
|
193
|
-
id: asset,
|
|
194
|
-
filename: subAsset.replace(/\.tracks.json$/, "")
|
|
195
|
-
});
|
|
196
|
-
if (createdFile) {
|
|
197
|
-
if (createdFile.fragment_index_complete) {
|
|
198
|
-
process.stderr.write(
|
|
199
|
-
" ✔ Fragment index has already been synced.\n"
|
|
200
|
-
);
|
|
201
|
-
} else {
|
|
202
|
-
const readStream = node_fs.createReadStream(subAssetPath);
|
|
203
|
-
await api.uploadFragmentIndex(index.getClient(), asset, readStream);
|
|
204
|
-
process.stderr.write(" ✅ Fragment index has been synced.\n");
|
|
205
|
-
}
|
|
206
|
-
await syncStatus.markSynced();
|
|
207
|
-
} else {
|
|
208
|
-
process.stderr.write(
|
|
209
|
-
`🚫 No file found for fragment index: ${subAsset}
|
|
210
|
-
`
|
|
211
|
-
);
|
|
212
|
-
break;
|
|
213
|
-
}
|
|
214
|
-
break;
|
|
215
|
-
}
|
|
216
|
-
case captionsMatch.test(subAsset): {
|
|
217
|
-
process.stderr.write(`📝 Syncing captions: ${subAsset}
|
|
218
|
-
`);
|
|
219
|
-
const createdFile = await api.createCaptionFile(index.getClient(), {
|
|
220
|
-
id: asset,
|
|
221
|
-
filename: subAsset.replace(/\.captions.json$/, "")
|
|
222
|
-
});
|
|
223
|
-
if (createdFile) {
|
|
224
|
-
if (createdFile.complete) {
|
|
225
|
-
process.stderr.write(" ✔ Captions have already been synced.\n");
|
|
226
|
-
} else {
|
|
227
|
-
const readStream = node_fs.createReadStream(subAssetPath);
|
|
228
|
-
await api.uploadCaptionFile(index.getClient(), asset, readStream);
|
|
229
|
-
process.stderr.write(" ✅ Captions have been synced.\n");
|
|
230
|
-
}
|
|
231
|
-
await syncStatus.markSynced();
|
|
232
|
-
} else {
|
|
233
|
-
process.stderr.write(
|
|
234
|
-
`🚫 No file found for captions: ${subAsset}
|
|
235
|
-
`
|
|
236
|
-
);
|
|
237
|
-
break;
|
|
238
|
-
}
|
|
239
|
-
break;
|
|
240
|
-
}
|
|
241
|
-
default: {
|
|
242
|
-
process.stderr.write(`🚫 Unknown sub-asset: ${subAsset}
|
|
243
|
-
`);
|
|
244
|
-
break;
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
};
|
|
250
|
-
exports.syncAssetDirectory = syncAssetDirectory;
|
package/dist/utils/index.cjs
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const commander = require("commander");
|
|
4
|
-
require("dotenv/config");
|
|
5
|
-
const api = require("@editframe/api");
|
|
6
|
-
let client;
|
|
7
|
-
const getClient = () => {
|
|
8
|
-
if (!client) {
|
|
9
|
-
const programOpts = commander.program.opts();
|
|
10
|
-
client = new api.Client(programOpts.token, programOpts.efHost);
|
|
11
|
-
}
|
|
12
|
-
return client;
|
|
13
|
-
};
|
|
14
|
-
exports.getClient = getClient;
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const chalk = require("chalk");
|
|
4
|
-
const playwright = require("playwright");
|
|
5
|
-
const debug = require("debug");
|
|
6
|
-
const withSpinner = require("./withSpinner.cjs");
|
|
7
|
-
const browserLog = debug("ef:cli::browser");
|
|
8
|
-
async function launchBrowserAndWaitForSDK(options, fn) {
|
|
9
|
-
const browser = await withSpinner.withSpinner("Launching chrome", async () => {
|
|
10
|
-
return playwright.chromium.launch({
|
|
11
|
-
channel: "chrome",
|
|
12
|
-
headless: options.headless ?? true,
|
|
13
|
-
// headless: false,
|
|
14
|
-
devtools: options.interactive === true
|
|
15
|
-
});
|
|
16
|
-
});
|
|
17
|
-
const page = await withSpinner.withSpinner("Loading EditFrame SDK", async () => {
|
|
18
|
-
const pageOptions = {};
|
|
19
|
-
if (options.interactive === true) {
|
|
20
|
-
pageOptions.viewport = null;
|
|
21
|
-
}
|
|
22
|
-
const page2 = await browser.newPage(pageOptions);
|
|
23
|
-
page2.on("console", (msg) => {
|
|
24
|
-
browserLog(chalk.blue(`browser (${msg.type()}) |`), msg.text());
|
|
25
|
-
});
|
|
26
|
-
const url = options.url + (options.efInteractive ? "" : "?EF_NONINTERACTIVE=1");
|
|
27
|
-
process.stderr.write("\nLoading url: ");
|
|
28
|
-
process.stderr.write(url);
|
|
29
|
-
process.stderr.write("\n");
|
|
30
|
-
await page2.goto(url);
|
|
31
|
-
await page2.waitForFunction(
|
|
32
|
-
() => {
|
|
33
|
-
return (
|
|
34
|
-
// @ts-expect-error
|
|
35
|
-
window.EF_REGISTERED
|
|
36
|
-
);
|
|
37
|
-
},
|
|
38
|
-
[],
|
|
39
|
-
{ timeout: 1e4 }
|
|
40
|
-
);
|
|
41
|
-
return page2;
|
|
42
|
-
});
|
|
43
|
-
await fn(page);
|
|
44
|
-
if (options.interactive !== true) {
|
|
45
|
-
await browser.close();
|
|
46
|
-
process.exit(0);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
exports.launchBrowserAndWaitForSDK = launchBrowserAndWaitForSDK;
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const vite = require("vite");
|
|
4
|
-
const path = require("node:path");
|
|
5
|
-
const vitePlugin = require("@editframe/vite-plugin");
|
|
6
|
-
const withSpinner = require("./withSpinner.cjs");
|
|
7
|
-
class PreviewServer {
|
|
8
|
-
constructor(previewServer) {
|
|
9
|
-
this.previewServer = previewServer;
|
|
10
|
-
}
|
|
11
|
-
static async start(directory) {
|
|
12
|
-
return new PreviewServer(await startPreviewServer(directory));
|
|
13
|
-
}
|
|
14
|
-
get url() {
|
|
15
|
-
return `http://localhost:${this.previewServer.config.server.port}`;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
const startPreviewServer = async (directory) => {
|
|
19
|
-
return await withSpinner.withSpinner("Starting vite...", async () => {
|
|
20
|
-
const resolvedDirectory = path.resolve(process.cwd(), directory);
|
|
21
|
-
const cacheRoot = path.join(resolvedDirectory, "assets");
|
|
22
|
-
const devServer = await vite.createServer({
|
|
23
|
-
server: {
|
|
24
|
-
watch: null
|
|
25
|
-
},
|
|
26
|
-
root: resolvedDirectory,
|
|
27
|
-
plugins: [
|
|
28
|
-
vitePlugin.vitePluginEditframe({
|
|
29
|
-
root: resolvedDirectory,
|
|
30
|
-
cacheRoot
|
|
31
|
-
})
|
|
32
|
-
]
|
|
33
|
-
});
|
|
34
|
-
await devServer.listen();
|
|
35
|
-
return devServer;
|
|
36
|
-
});
|
|
37
|
-
};
|
|
38
|
-
exports.PreviewServer = PreviewServer;
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const zod = require("zod");
|
|
4
|
-
const ora = require("ora");
|
|
5
|
-
const debug = require("debug");
|
|
6
|
-
const log = debug("ef:cli:auth");
|
|
7
|
-
const schema = zod.z.object({
|
|
8
|
-
width: zod.z.number().int(),
|
|
9
|
-
height: zod.z.number().int()
|
|
10
|
-
}).refine((data) => data.width % 2 === 0 && data.height % 2 === 0, {
|
|
11
|
-
message: "Both width and height must be divisible by 2.",
|
|
12
|
-
path: ["width", "height"]
|
|
13
|
-
});
|
|
14
|
-
const validateVideoResolution = async (rawPayload) => {
|
|
15
|
-
const spinner = ora("Validating video resolution").start();
|
|
16
|
-
const result = schema.safeParse(rawPayload);
|
|
17
|
-
if (result.success) {
|
|
18
|
-
spinner.succeed("Video resolution is valid");
|
|
19
|
-
return result.data;
|
|
20
|
-
}
|
|
21
|
-
spinner.fail("Invalid video resolution");
|
|
22
|
-
process.stderr.write(result.error?.errors.map((e) => e.message).join("\n"));
|
|
23
|
-
process.stderr.write("\n");
|
|
24
|
-
log("Error:", result.error?.errors.map((e) => e.message).join("\n"));
|
|
25
|
-
process.exit(1);
|
|
26
|
-
};
|
|
27
|
-
exports.validateVideoResolution = validateVideoResolution;
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const ora = require("ora");
|
|
4
|
-
const withSpinner = async (label, fn) => {
|
|
5
|
-
const spinner = ora(label).start();
|
|
6
|
-
try {
|
|
7
|
-
const result = await fn();
|
|
8
|
-
spinner.succeed();
|
|
9
|
-
return result;
|
|
10
|
-
} catch (error) {
|
|
11
|
-
spinner.fail();
|
|
12
|
-
throw error;
|
|
13
|
-
}
|
|
14
|
-
};
|
|
15
|
-
exports.withSpinner = withSpinner;
|