@editframe/cli 0.7.0-beta.1 → 0.7.0-beta.11
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.cjs +1 -1
- package/dist/VERSION.js +1 -1
- package/dist/commands/auth.cjs +14 -11
- package/dist/commands/auth.js +15 -12
- package/dist/commands/check.cjs +2 -2
- package/dist/commands/check.js +2 -2
- package/dist/commands/process.cjs +36 -0
- package/dist/commands/process.js +35 -0
- package/dist/commands/render.cjs +34 -25
- package/dist/commands/render.js +34 -25
- package/dist/index.cjs +1 -11
- package/dist/index.js +1 -12
- package/dist/operations/getRenderInfo.cjs +59 -0
- package/dist/operations/getRenderInfo.js +59 -0
- package/dist/operations/processRenderInfo.cjs +30 -0
- package/dist/operations/processRenderInfo.js +30 -0
- package/dist/operations/syncAssetsDirectory.cjs +83 -40
- package/dist/operations/syncAssetsDirectory.js +82 -39
- package/dist/utils/index.cjs +8 -15
- package/dist/utils/index.js +8 -15
- package/dist/utils/launchBrowserAndWaitForSDK.cjs +7 -3
- package/dist/utils/launchBrowserAndWaitForSDK.js +7 -3
- package/dist/utils/validateVideoResolution.cjs +27 -0
- package/dist/utils/validateVideoResolution.js +27 -0
- package/package.json +6 -12
- package/src/commands/auth.ts +14 -12
- package/src/commands/check.ts +2 -2
- package/src/commands/process.ts +43 -37
- package/src/commands/render.ts +32 -30
- package/src/operations/getRenderInfo.ts +80 -0
- package/src/operations/processRenderInfo.ts +37 -0
- package/src/operations/syncAssetsDirectory.ts +77 -40
- package/src/utils/index.ts +7 -16
- package/src/utils/launchBrowserAndWaitForSDK.ts +9 -3
- package/src/utils/validateVideoResolution.ts +33 -0
- package/dist/api/caption-file.cjs +0 -48
- package/dist/api/caption-file.js +0 -48
- package/dist/api/image-file.cjs +0 -49
- package/dist/api/image-file.js +0 -49
- package/dist/api/index.cjs +0 -12
- package/dist/api/index.js +0 -12
- package/dist/api/isobmff-file.cjs +0 -48
- package/dist/api/isobmff-file.js +0 -48
- package/dist/api/isobmff-track.cjs +0 -63
- package/dist/api/isobmff-track.js +0 -63
- package/dist/api/renders.cjs +0 -51
- package/dist/api/renders.js +0 -51
- package/src/api/caption-file.ts +0 -60
- package/src/api/image-file.ts +0 -58
- package/src/api/index.ts +0 -17
- package/src/api/isobmff-file.ts +0 -59
- package/src/api/isobmff-track.ts +0 -77
- package/src/api/renders.ts +0 -59
|
@@ -3,11 +3,9 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
3
3
|
const assets = require("@editframe/assets");
|
|
4
4
|
const fs = require("node:fs/promises");
|
|
5
5
|
const path = require("node:path");
|
|
6
|
-
const
|
|
7
|
-
const imageFile = require("../api/image-file.cjs");
|
|
8
|
-
const isobmffFile = require("../api/isobmff-file.cjs");
|
|
9
|
-
const isobmffTrack = require("../api/isobmff-track.cjs");
|
|
6
|
+
const api = require("@editframe/api");
|
|
10
7
|
const node_fs = require("node:fs");
|
|
8
|
+
const index = require("../utils/index.cjs");
|
|
11
9
|
const imageMatch = /\.(png|jpe?g|gif|webp)$/i;
|
|
12
10
|
const trackMatch = /\.track-[\d]+.mp4$/i;
|
|
13
11
|
const fragmentIndexMatch = /\.tracks.json$/i;
|
|
@@ -27,7 +25,8 @@ class SyncStatus {
|
|
|
27
25
|
return !!result;
|
|
28
26
|
}
|
|
29
27
|
async markSynced() {
|
|
30
|
-
|
|
28
|
+
process.stderr.write(`✏️ Marking asset as synced: ${this.assetPath}
|
|
29
|
+
`);
|
|
31
30
|
await fs.writeFile(this.infoPath, "{}", "utf-8");
|
|
32
31
|
}
|
|
33
32
|
}
|
|
@@ -39,19 +38,26 @@ const syncAssetDirectory = async (projectDirectory) => {
|
|
|
39
38
|
"assets",
|
|
40
39
|
".cache"
|
|
41
40
|
);
|
|
42
|
-
const stat = await fs.stat(fullPath)
|
|
43
|
-
|
|
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()) {
|
|
44
48
|
console.error(`No assets cache directory found at ${fullPath}`);
|
|
45
49
|
return;
|
|
46
50
|
}
|
|
47
51
|
const assets$1 = await fs.readdir(fullPath);
|
|
48
|
-
|
|
52
|
+
process.stderr.write(`Syncing asset dir: ${fullPath}
|
|
53
|
+
`);
|
|
49
54
|
for (const asset of assets$1) {
|
|
50
|
-
|
|
55
|
+
process.stderr.write(`Syncing asset: ${asset}
|
|
56
|
+
`);
|
|
51
57
|
const assetDir = path.join(fullPath, asset);
|
|
52
58
|
const stat2 = await fs.stat(assetDir);
|
|
53
59
|
if (!stat2.isDirectory()) {
|
|
54
|
-
|
|
60
|
+
process.stderr.write("Invalid asset. Did not find asset directory.\n");
|
|
55
61
|
return;
|
|
56
62
|
}
|
|
57
63
|
const subAssets = await fs.readdir(assetDir);
|
|
@@ -62,7 +68,10 @@ const syncAssetDirectory = async (projectDirectory) => {
|
|
|
62
68
|
const subAssetPath = path.join(assetDir, subAsset);
|
|
63
69
|
const syncStatus = new SyncStatus(subAssetPath);
|
|
64
70
|
if (await syncStatus.isSynced()) {
|
|
65
|
-
|
|
71
|
+
process.stderr.write(
|
|
72
|
+
` ✔ Sub-asset has already been synced: ${subAsset}
|
|
73
|
+
`
|
|
74
|
+
);
|
|
66
75
|
continue;
|
|
67
76
|
}
|
|
68
77
|
switch (true) {
|
|
@@ -70,16 +79,21 @@ const syncAssetDirectory = async (projectDirectory) => {
|
|
|
70
79
|
const probeResult = await assets.Probe.probePath(subAssetPath);
|
|
71
80
|
const [videoProbe] = probeResult.videoStreams;
|
|
72
81
|
if (!videoProbe) {
|
|
73
|
-
|
|
82
|
+
process.stderr.write(
|
|
83
|
+
`🚫 No video stream found in image: ${subAsset}
|
|
84
|
+
`
|
|
85
|
+
);
|
|
74
86
|
break;
|
|
75
87
|
}
|
|
76
88
|
const ext = path.extname(subAsset).slice(1);
|
|
77
89
|
if (!(ext === "jpg" || ext === "jpeg" || ext === "png" || ext === "webp")) {
|
|
78
|
-
|
|
90
|
+
process.stderr.write(`🚫 Invalid image format: ${subAsset}
|
|
91
|
+
`);
|
|
79
92
|
break;
|
|
80
93
|
}
|
|
81
|
-
|
|
82
|
-
|
|
94
|
+
process.stderr.write(`🖼️ Syncing image: ${subAsset}
|
|
95
|
+
`);
|
|
96
|
+
const created = await api.createImageFile(index.getClient(), {
|
|
83
97
|
id: asset,
|
|
84
98
|
filename: subAsset,
|
|
85
99
|
width: videoProbe.width,
|
|
@@ -88,18 +102,23 @@ const syncAssetDirectory = async (projectDirectory) => {
|
|
|
88
102
|
});
|
|
89
103
|
if (created) {
|
|
90
104
|
if (created.complete) {
|
|
91
|
-
|
|
105
|
+
process.stderr.write(" ✔ Image has already been synced.\n");
|
|
92
106
|
} else {
|
|
93
|
-
await
|
|
94
|
-
|
|
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");
|
|
95
113
|
}
|
|
96
114
|
await syncStatus.markSynced();
|
|
97
115
|
}
|
|
98
116
|
break;
|
|
99
117
|
}
|
|
100
118
|
case trackMatch.test(subAsset): {
|
|
101
|
-
|
|
102
|
-
|
|
119
|
+
process.stderr.write(`📼 Syncing a/v track: ${subAsset}
|
|
120
|
+
`);
|
|
121
|
+
const createdFile = await api.createISOBMFFFile(index.getClient(), {
|
|
103
122
|
id: asset,
|
|
104
123
|
filename: subAsset.replace(/\.track-[\d]+.mp4$/, "")
|
|
105
124
|
});
|
|
@@ -107,16 +126,25 @@ const syncAssetDirectory = async (projectDirectory) => {
|
|
|
107
126
|
const probe = await assets.Probe.probePath(subAssetPath);
|
|
108
127
|
const trackId = subAsset.match(/track-([\d]+).mp4/)?.[1];
|
|
109
128
|
if (!trackId) {
|
|
110
|
-
|
|
129
|
+
process.stderr.write(
|
|
130
|
+
`🚫 No track ID found for track: ${subAsset}
|
|
131
|
+
`
|
|
132
|
+
);
|
|
111
133
|
break;
|
|
112
134
|
}
|
|
113
135
|
const [track] = probe.streams;
|
|
114
136
|
if (!track) {
|
|
115
|
-
|
|
137
|
+
process.stderr.write(
|
|
138
|
+
`🚫 No track stream found in track: ${subAsset}
|
|
139
|
+
`
|
|
140
|
+
);
|
|
116
141
|
break;
|
|
117
142
|
}
|
|
118
143
|
if (track.duration === void 0) {
|
|
119
|
-
|
|
144
|
+
process.stderr.write(
|
|
145
|
+
`🚫 No duration found in track: ${subAsset}
|
|
146
|
+
`
|
|
147
|
+
);
|
|
120
148
|
break;
|
|
121
149
|
}
|
|
122
150
|
const stat3 = await fs.stat(subAssetPath);
|
|
@@ -137,17 +165,21 @@ const syncAssetDirectory = async (projectDirectory) => {
|
|
|
137
165
|
codec_name: track.codec_name,
|
|
138
166
|
byte_size: stat3.size
|
|
139
167
|
};
|
|
140
|
-
const createdTrack = await
|
|
168
|
+
const createdTrack = await api.createISOBMFFTrack(
|
|
169
|
+
index.getClient(),
|
|
170
|
+
createPayload
|
|
171
|
+
);
|
|
141
172
|
if (createdTrack) {
|
|
142
173
|
if (createdTrack.last_received_byte === createdTrack.byte_size - 1) {
|
|
143
|
-
|
|
174
|
+
process.stderr.write(" ✔ Track has already been synced.\n");
|
|
144
175
|
} else {
|
|
145
|
-
await
|
|
176
|
+
await api.uploadISOBMFFTrack(
|
|
177
|
+
index.getClient(),
|
|
146
178
|
createdFile.id,
|
|
147
179
|
Number(trackId),
|
|
148
180
|
node_fs.createReadStream(subAssetPath)
|
|
149
181
|
);
|
|
150
|
-
|
|
182
|
+
process.stderr.write(" ✅ Track has been synced.\n");
|
|
151
183
|
}
|
|
152
184
|
await syncStatus.markSynced();
|
|
153
185
|
}
|
|
@@ -155,49 +187,60 @@ const syncAssetDirectory = async (projectDirectory) => {
|
|
|
155
187
|
break;
|
|
156
188
|
}
|
|
157
189
|
case fragmentIndexMatch.test(subAsset): {
|
|
158
|
-
|
|
159
|
-
|
|
190
|
+
process.stderr.write(`📋 Syncing fragment index: ${subAsset}
|
|
191
|
+
`);
|
|
192
|
+
const createdFile = await api.createISOBMFFFile(index.getClient(), {
|
|
160
193
|
id: asset,
|
|
161
194
|
filename: subAsset.replace(/\.tracks.json$/, "")
|
|
162
195
|
});
|
|
163
196
|
if (createdFile) {
|
|
164
197
|
if (createdFile.fragment_index_complete) {
|
|
165
|
-
|
|
198
|
+
process.stderr.write(
|
|
199
|
+
" ✔ Fragment index has already been synced.\n"
|
|
200
|
+
);
|
|
166
201
|
} else {
|
|
167
202
|
const readStream = node_fs.createReadStream(subAssetPath);
|
|
168
|
-
await
|
|
169
|
-
|
|
203
|
+
await api.uploadFragmentIndex(index.getClient(), asset, readStream);
|
|
204
|
+
process.stderr.write(" ✅ Fragment index has been synced.\n");
|
|
170
205
|
}
|
|
171
206
|
await syncStatus.markSynced();
|
|
172
207
|
} else {
|
|
173
|
-
|
|
208
|
+
process.stderr.write(
|
|
209
|
+
`🚫 No file found for fragment index: ${subAsset}
|
|
210
|
+
`
|
|
211
|
+
);
|
|
174
212
|
break;
|
|
175
213
|
}
|
|
176
214
|
break;
|
|
177
215
|
}
|
|
178
216
|
case captionsMatch.test(subAsset): {
|
|
179
|
-
|
|
180
|
-
|
|
217
|
+
process.stderr.write(`📝 Syncing captions: ${subAsset}
|
|
218
|
+
`);
|
|
219
|
+
const createdFile = await api.createCaptionFile(index.getClient(), {
|
|
181
220
|
id: asset,
|
|
182
221
|
filename: subAsset.replace(/\.captions.json$/, "")
|
|
183
222
|
});
|
|
184
223
|
if (createdFile) {
|
|
185
224
|
if (createdFile.complete) {
|
|
186
|
-
|
|
225
|
+
process.stderr.write(" ✔ Captions have already been synced.\n");
|
|
187
226
|
} else {
|
|
188
227
|
const readStream = node_fs.createReadStream(subAssetPath);
|
|
189
|
-
await
|
|
190
|
-
|
|
228
|
+
await api.uploadCaptionFile(index.getClient(), asset, readStream);
|
|
229
|
+
process.stderr.write(" ✅ Captions have been synced.\n");
|
|
191
230
|
}
|
|
192
231
|
await syncStatus.markSynced();
|
|
193
232
|
} else {
|
|
194
|
-
|
|
233
|
+
process.stderr.write(
|
|
234
|
+
`🚫 No file found for captions: ${subAsset}
|
|
235
|
+
`
|
|
236
|
+
);
|
|
195
237
|
break;
|
|
196
238
|
}
|
|
197
239
|
break;
|
|
198
240
|
}
|
|
199
241
|
default: {
|
|
200
|
-
|
|
242
|
+
process.stderr.write(`🚫 Unknown sub-asset: ${subAsset}
|
|
243
|
+
`);
|
|
201
244
|
break;
|
|
202
245
|
}
|
|
203
246
|
}
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { Probe } from "@editframe/assets";
|
|
2
2
|
import fs from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
|
-
import { createCaptionFile, uploadCaptionFile } from "
|
|
5
|
-
import { createImageFile, uploadImageFile } from "../api/image-file.js";
|
|
6
|
-
import { createISOBMFFFile, uploadFragmentIndex } from "../api/isobmff-file.js";
|
|
7
|
-
import { createISOBMFFTrack, uploadISOBMFFTrack } from "../api/isobmff-track.js";
|
|
4
|
+
import { createCaptionFile, uploadCaptionFile, createISOBMFFFile, uploadFragmentIndex, createISOBMFFTrack, uploadISOBMFFTrack, createImageFile, uploadImageFile } from "@editframe/api";
|
|
8
5
|
import { createReadStream } from "node:fs";
|
|
6
|
+
import { getClient } from "../utils/index.js";
|
|
9
7
|
const imageMatch = /\.(png|jpe?g|gif|webp)$/i;
|
|
10
8
|
const trackMatch = /\.track-[\d]+.mp4$/i;
|
|
11
9
|
const fragmentIndexMatch = /\.tracks.json$/i;
|
|
@@ -25,7 +23,8 @@ class SyncStatus {
|
|
|
25
23
|
return !!result;
|
|
26
24
|
}
|
|
27
25
|
async markSynced() {
|
|
28
|
-
|
|
26
|
+
process.stderr.write(`✏️ Marking asset as synced: ${this.assetPath}
|
|
27
|
+
`);
|
|
29
28
|
await fs.writeFile(this.infoPath, "{}", "utf-8");
|
|
30
29
|
}
|
|
31
30
|
}
|
|
@@ -37,19 +36,26 @@ const syncAssetDirectory = async (projectDirectory) => {
|
|
|
37
36
|
"assets",
|
|
38
37
|
".cache"
|
|
39
38
|
);
|
|
40
|
-
const stat = await fs.stat(fullPath)
|
|
41
|
-
|
|
39
|
+
const stat = await fs.stat(fullPath).catch((error) => {
|
|
40
|
+
if (error.code === "ENOENT") {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
throw error;
|
|
44
|
+
});
|
|
45
|
+
if (!stat?.isDirectory()) {
|
|
42
46
|
console.error(`No assets cache directory found at ${fullPath}`);
|
|
43
47
|
return;
|
|
44
48
|
}
|
|
45
49
|
const assets = await fs.readdir(fullPath);
|
|
46
|
-
|
|
50
|
+
process.stderr.write(`Syncing asset dir: ${fullPath}
|
|
51
|
+
`);
|
|
47
52
|
for (const asset of assets) {
|
|
48
|
-
|
|
53
|
+
process.stderr.write(`Syncing asset: ${asset}
|
|
54
|
+
`);
|
|
49
55
|
const assetDir = path.join(fullPath, asset);
|
|
50
56
|
const stat2 = await fs.stat(assetDir);
|
|
51
57
|
if (!stat2.isDirectory()) {
|
|
52
|
-
|
|
58
|
+
process.stderr.write("Invalid asset. Did not find asset directory.\n");
|
|
53
59
|
return;
|
|
54
60
|
}
|
|
55
61
|
const subAssets = await fs.readdir(assetDir);
|
|
@@ -60,7 +66,10 @@ const syncAssetDirectory = async (projectDirectory) => {
|
|
|
60
66
|
const subAssetPath = path.join(assetDir, subAsset);
|
|
61
67
|
const syncStatus = new SyncStatus(subAssetPath);
|
|
62
68
|
if (await syncStatus.isSynced()) {
|
|
63
|
-
|
|
69
|
+
process.stderr.write(
|
|
70
|
+
` ✔ Sub-asset has already been synced: ${subAsset}
|
|
71
|
+
`
|
|
72
|
+
);
|
|
64
73
|
continue;
|
|
65
74
|
}
|
|
66
75
|
switch (true) {
|
|
@@ -68,16 +77,21 @@ const syncAssetDirectory = async (projectDirectory) => {
|
|
|
68
77
|
const probeResult = await Probe.probePath(subAssetPath);
|
|
69
78
|
const [videoProbe] = probeResult.videoStreams;
|
|
70
79
|
if (!videoProbe) {
|
|
71
|
-
|
|
80
|
+
process.stderr.write(
|
|
81
|
+
`🚫 No video stream found in image: ${subAsset}
|
|
82
|
+
`
|
|
83
|
+
);
|
|
72
84
|
break;
|
|
73
85
|
}
|
|
74
86
|
const ext = path.extname(subAsset).slice(1);
|
|
75
87
|
if (!(ext === "jpg" || ext === "jpeg" || ext === "png" || ext === "webp")) {
|
|
76
|
-
|
|
88
|
+
process.stderr.write(`🚫 Invalid image format: ${subAsset}
|
|
89
|
+
`);
|
|
77
90
|
break;
|
|
78
91
|
}
|
|
79
|
-
|
|
80
|
-
|
|
92
|
+
process.stderr.write(`🖼️ Syncing image: ${subAsset}
|
|
93
|
+
`);
|
|
94
|
+
const created = await createImageFile(getClient(), {
|
|
81
95
|
id: asset,
|
|
82
96
|
filename: subAsset,
|
|
83
97
|
width: videoProbe.width,
|
|
@@ -86,18 +100,23 @@ const syncAssetDirectory = async (projectDirectory) => {
|
|
|
86
100
|
});
|
|
87
101
|
if (created) {
|
|
88
102
|
if (created.complete) {
|
|
89
|
-
|
|
103
|
+
process.stderr.write(" ✔ Image has already been synced.\n");
|
|
90
104
|
} else {
|
|
91
|
-
await uploadImageFile(
|
|
92
|
-
|
|
105
|
+
await uploadImageFile(
|
|
106
|
+
getClient(),
|
|
107
|
+
created.id,
|
|
108
|
+
createReadStream(subAssetPath)
|
|
109
|
+
);
|
|
110
|
+
process.stderr.write(" ✅ Image has been synced.\n");
|
|
93
111
|
}
|
|
94
112
|
await syncStatus.markSynced();
|
|
95
113
|
}
|
|
96
114
|
break;
|
|
97
115
|
}
|
|
98
116
|
case trackMatch.test(subAsset): {
|
|
99
|
-
|
|
100
|
-
|
|
117
|
+
process.stderr.write(`📼 Syncing a/v track: ${subAsset}
|
|
118
|
+
`);
|
|
119
|
+
const createdFile = await createISOBMFFFile(getClient(), {
|
|
101
120
|
id: asset,
|
|
102
121
|
filename: subAsset.replace(/\.track-[\d]+.mp4$/, "")
|
|
103
122
|
});
|
|
@@ -105,16 +124,25 @@ const syncAssetDirectory = async (projectDirectory) => {
|
|
|
105
124
|
const probe = await Probe.probePath(subAssetPath);
|
|
106
125
|
const trackId = subAsset.match(/track-([\d]+).mp4/)?.[1];
|
|
107
126
|
if (!trackId) {
|
|
108
|
-
|
|
127
|
+
process.stderr.write(
|
|
128
|
+
`🚫 No track ID found for track: ${subAsset}
|
|
129
|
+
`
|
|
130
|
+
);
|
|
109
131
|
break;
|
|
110
132
|
}
|
|
111
133
|
const [track] = probe.streams;
|
|
112
134
|
if (!track) {
|
|
113
|
-
|
|
135
|
+
process.stderr.write(
|
|
136
|
+
`🚫 No track stream found in track: ${subAsset}
|
|
137
|
+
`
|
|
138
|
+
);
|
|
114
139
|
break;
|
|
115
140
|
}
|
|
116
141
|
if (track.duration === void 0) {
|
|
117
|
-
|
|
142
|
+
process.stderr.write(
|
|
143
|
+
`🚫 No duration found in track: ${subAsset}
|
|
144
|
+
`
|
|
145
|
+
);
|
|
118
146
|
break;
|
|
119
147
|
}
|
|
120
148
|
const stat3 = await fs.stat(subAssetPath);
|
|
@@ -135,17 +163,21 @@ const syncAssetDirectory = async (projectDirectory) => {
|
|
|
135
163
|
codec_name: track.codec_name,
|
|
136
164
|
byte_size: stat3.size
|
|
137
165
|
};
|
|
138
|
-
const createdTrack = await createISOBMFFTrack(
|
|
166
|
+
const createdTrack = await createISOBMFFTrack(
|
|
167
|
+
getClient(),
|
|
168
|
+
createPayload
|
|
169
|
+
);
|
|
139
170
|
if (createdTrack) {
|
|
140
171
|
if (createdTrack.last_received_byte === createdTrack.byte_size - 1) {
|
|
141
|
-
|
|
172
|
+
process.stderr.write(" ✔ Track has already been synced.\n");
|
|
142
173
|
} else {
|
|
143
174
|
await uploadISOBMFFTrack(
|
|
175
|
+
getClient(),
|
|
144
176
|
createdFile.id,
|
|
145
177
|
Number(trackId),
|
|
146
178
|
createReadStream(subAssetPath)
|
|
147
179
|
);
|
|
148
|
-
|
|
180
|
+
process.stderr.write(" ✅ Track has been synced.\n");
|
|
149
181
|
}
|
|
150
182
|
await syncStatus.markSynced();
|
|
151
183
|
}
|
|
@@ -153,49 +185,60 @@ const syncAssetDirectory = async (projectDirectory) => {
|
|
|
153
185
|
break;
|
|
154
186
|
}
|
|
155
187
|
case fragmentIndexMatch.test(subAsset): {
|
|
156
|
-
|
|
157
|
-
|
|
188
|
+
process.stderr.write(`📋 Syncing fragment index: ${subAsset}
|
|
189
|
+
`);
|
|
190
|
+
const createdFile = await createISOBMFFFile(getClient(), {
|
|
158
191
|
id: asset,
|
|
159
192
|
filename: subAsset.replace(/\.tracks.json$/, "")
|
|
160
193
|
});
|
|
161
194
|
if (createdFile) {
|
|
162
195
|
if (createdFile.fragment_index_complete) {
|
|
163
|
-
|
|
196
|
+
process.stderr.write(
|
|
197
|
+
" ✔ Fragment index has already been synced.\n"
|
|
198
|
+
);
|
|
164
199
|
} else {
|
|
165
200
|
const readStream = createReadStream(subAssetPath);
|
|
166
|
-
await uploadFragmentIndex(asset, readStream);
|
|
167
|
-
|
|
201
|
+
await uploadFragmentIndex(getClient(), asset, readStream);
|
|
202
|
+
process.stderr.write(" ✅ Fragment index has been synced.\n");
|
|
168
203
|
}
|
|
169
204
|
await syncStatus.markSynced();
|
|
170
205
|
} else {
|
|
171
|
-
|
|
206
|
+
process.stderr.write(
|
|
207
|
+
`🚫 No file found for fragment index: ${subAsset}
|
|
208
|
+
`
|
|
209
|
+
);
|
|
172
210
|
break;
|
|
173
211
|
}
|
|
174
212
|
break;
|
|
175
213
|
}
|
|
176
214
|
case captionsMatch.test(subAsset): {
|
|
177
|
-
|
|
178
|
-
|
|
215
|
+
process.stderr.write(`📝 Syncing captions: ${subAsset}
|
|
216
|
+
`);
|
|
217
|
+
const createdFile = await createCaptionFile(getClient(), {
|
|
179
218
|
id: asset,
|
|
180
219
|
filename: subAsset.replace(/\.captions.json$/, "")
|
|
181
220
|
});
|
|
182
221
|
if (createdFile) {
|
|
183
222
|
if (createdFile.complete) {
|
|
184
|
-
|
|
223
|
+
process.stderr.write(" ✔ Captions have already been synced.\n");
|
|
185
224
|
} else {
|
|
186
225
|
const readStream = createReadStream(subAssetPath);
|
|
187
|
-
await uploadCaptionFile(asset, readStream);
|
|
188
|
-
|
|
226
|
+
await uploadCaptionFile(getClient(), asset, readStream);
|
|
227
|
+
process.stderr.write(" ✅ Captions have been synced.\n");
|
|
189
228
|
}
|
|
190
229
|
await syncStatus.markSynced();
|
|
191
230
|
} else {
|
|
192
|
-
|
|
231
|
+
process.stderr.write(
|
|
232
|
+
`🚫 No file found for captions: ${subAsset}
|
|
233
|
+
`
|
|
234
|
+
);
|
|
193
235
|
break;
|
|
194
236
|
}
|
|
195
237
|
break;
|
|
196
238
|
}
|
|
197
239
|
default: {
|
|
198
|
-
|
|
240
|
+
process.stderr.write(`🚫 Unknown sub-asset: ${subAsset}
|
|
241
|
+
`);
|
|
199
242
|
break;
|
|
200
243
|
}
|
|
201
244
|
}
|
package/dist/utils/index.cjs
CHANGED
|
@@ -2,20 +2,13 @@
|
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const commander = require("commander");
|
|
4
4
|
require("dotenv/config");
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
if (!
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
);
|
|
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);
|
|
12
11
|
}
|
|
13
|
-
|
|
14
|
-
Object.assign(init.headers, {
|
|
15
|
-
Authorization: `Bearer ${programOpts.token}`,
|
|
16
|
-
"Content-Type": "application/json"
|
|
17
|
-
});
|
|
18
|
-
const url = new URL(path, programOpts.efHost);
|
|
19
|
-
return fetch(url, init);
|
|
12
|
+
return client;
|
|
20
13
|
};
|
|
21
|
-
exports.
|
|
14
|
+
exports.getClient = getClient;
|
package/dist/utils/index.js
CHANGED
|
@@ -1,21 +1,14 @@
|
|
|
1
1
|
import { program } from "commander";
|
|
2
2
|
import "dotenv/config";
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
if (!
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
);
|
|
3
|
+
import { Client } from "@editframe/api";
|
|
4
|
+
let client;
|
|
5
|
+
const getClient = () => {
|
|
6
|
+
if (!client) {
|
|
7
|
+
const programOpts = program.opts();
|
|
8
|
+
client = new Client(programOpts.token, programOpts.efHost);
|
|
10
9
|
}
|
|
11
|
-
|
|
12
|
-
Object.assign(init.headers, {
|
|
13
|
-
Authorization: `Bearer ${programOpts.token}`,
|
|
14
|
-
"Content-Type": "application/json"
|
|
15
|
-
});
|
|
16
|
-
const url = new URL(path, programOpts.efHost);
|
|
17
|
-
return fetch(url, init);
|
|
10
|
+
return client;
|
|
18
11
|
};
|
|
19
12
|
export {
|
|
20
|
-
|
|
13
|
+
getClient
|
|
21
14
|
};
|
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const chalk = require("chalk");
|
|
4
4
|
const playwright = require("playwright");
|
|
5
|
+
const debug = require("debug");
|
|
5
6
|
const withSpinner = require("./withSpinner.cjs");
|
|
7
|
+
const browserLog = debug("ef:cli::browser");
|
|
6
8
|
async function launchBrowserAndWaitForSDK(options, fn) {
|
|
7
9
|
const browser = await withSpinner.withSpinner("Launching chrome", async () => {
|
|
8
10
|
return playwright.chromium.launch({
|
|
@@ -19,10 +21,12 @@ async function launchBrowserAndWaitForSDK(options, fn) {
|
|
|
19
21
|
}
|
|
20
22
|
const page2 = await browser.newPage(pageOptions);
|
|
21
23
|
page2.on("console", (msg) => {
|
|
22
|
-
|
|
24
|
+
browserLog(chalk.blue(`browser (${msg.type()}) |`), msg.text());
|
|
23
25
|
});
|
|
24
26
|
const url = options.url + (options.efInteractive ? "" : "?EF_NONINTERACTIVE=1");
|
|
25
|
-
|
|
27
|
+
process.stderr.write("\nLoading url: ");
|
|
28
|
+
process.stderr.write(url);
|
|
29
|
+
process.stderr.write("\n");
|
|
26
30
|
await page2.goto(url);
|
|
27
31
|
await page2.waitForFunction(
|
|
28
32
|
() => {
|
|
@@ -32,7 +36,7 @@ async function launchBrowserAndWaitForSDK(options, fn) {
|
|
|
32
36
|
);
|
|
33
37
|
},
|
|
34
38
|
[],
|
|
35
|
-
{ timeout:
|
|
39
|
+
{ timeout: 1e4 }
|
|
36
40
|
);
|
|
37
41
|
return page2;
|
|
38
42
|
});
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
2
|
import { chromium } from "playwright";
|
|
3
|
+
import debug from "debug";
|
|
3
4
|
import { withSpinner } from "./withSpinner.js";
|
|
5
|
+
const browserLog = debug("ef:cli::browser");
|
|
4
6
|
async function launchBrowserAndWaitForSDK(options, fn) {
|
|
5
7
|
const browser = await withSpinner("Launching chrome", async () => {
|
|
6
8
|
return chromium.launch({
|
|
@@ -17,10 +19,12 @@ async function launchBrowserAndWaitForSDK(options, fn) {
|
|
|
17
19
|
}
|
|
18
20
|
const page2 = await browser.newPage(pageOptions);
|
|
19
21
|
page2.on("console", (msg) => {
|
|
20
|
-
|
|
22
|
+
browserLog(chalk.blue(`browser (${msg.type()}) |`), msg.text());
|
|
21
23
|
});
|
|
22
24
|
const url = options.url + (options.efInteractive ? "" : "?EF_NONINTERACTIVE=1");
|
|
23
|
-
|
|
25
|
+
process.stderr.write("\nLoading url: ");
|
|
26
|
+
process.stderr.write(url);
|
|
27
|
+
process.stderr.write("\n");
|
|
24
28
|
await page2.goto(url);
|
|
25
29
|
await page2.waitForFunction(
|
|
26
30
|
() => {
|
|
@@ -30,7 +34,7 @@ async function launchBrowserAndWaitForSDK(options, fn) {
|
|
|
30
34
|
);
|
|
31
35
|
},
|
|
32
36
|
[],
|
|
33
|
-
{ timeout:
|
|
37
|
+
{ timeout: 1e4 }
|
|
34
38
|
);
|
|
35
39
|
return page2;
|
|
36
40
|
});
|
|
@@ -0,0 +1,27 @@
|
|
|
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;
|