@memberjunction/video-studio-render-worker 0.0.1-seed.1 → 6.2.0-edge.7
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/LICENSE +183 -0
- package/README.md +139 -4
- package/assets/fonts/Inter-OFL.txt +93 -0
- package/assets/fonts/Inter-Regular.ttf +0 -0
- package/assets/fonts/JetBrainsMono-OFL.txt +93 -0
- package/assets/fonts/JetBrainsMono-Regular.ttf +0 -0
- package/dist/backend.d.ts +201 -0
- package/dist/backend.d.ts.map +1 -0
- package/dist/backend.js +205 -0
- package/dist/backend.js.map +1 -0
- package/dist/bundle.d.ts +112 -0
- package/dist/bundle.d.ts.map +1 -0
- package/dist/bundle.js +433 -0
- package/dist/bundle.js.map +1 -0
- package/dist/checks/dom-rules.d.ts +57 -0
- package/dist/checks/dom-rules.d.ts.map +1 -0
- package/dist/checks/dom-rules.js +205 -0
- package/dist/checks/dom-rules.js.map +1 -0
- package/dist/checks/hyperframes-check.d.ts +37 -0
- package/dist/checks/hyperframes-check.d.ts.map +1 -0
- package/dist/checks/hyperframes-check.js +161 -0
- package/dist/checks/hyperframes-check.js.map +1 -0
- package/dist/checks/static-checks.d.ts +46 -0
- package/dist/checks/static-checks.d.ts.map +1 -0
- package/dist/checks/static-checks.js +681 -0
- package/dist/checks/static-checks.js.map +1 -0
- package/dist/hyperframes-backend.d.ts +53 -0
- package/dist/hyperframes-backend.d.ts.map +1 -0
- package/dist/hyperframes-backend.js +733 -0
- package/dist/hyperframes-backend.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/jobs.d.ts +88 -0
- package/dist/jobs.d.ts.map +1 -0
- package/dist/jobs.js +650 -0
- package/dist/jobs.js.map +1 -0
- package/dist/lint-gate.d.ts +21 -0
- package/dist/lint-gate.d.ts.map +1 -0
- package/dist/lint-gate.js +528 -0
- package/dist/lint-gate.js.map +1 -0
- package/dist/main.d.ts +47 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +195 -0
- package/dist/main.js.map +1 -0
- package/dist/one-shot.d.ts +37 -0
- package/dist/one-shot.d.ts.map +1 -0
- package/dist/one-shot.js +228 -0
- package/dist/one-shot.js.map +1 -0
- package/dist/preamble.d.ts +69 -0
- package/dist/preamble.d.ts.map +1 -0
- package/dist/preamble.js +331 -0
- package/dist/preamble.js.map +1 -0
- package/dist/server.d.ts +75 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +526 -0
- package/dist/server.js.map +1 -0
- package/package.json +43 -5
package/dist/bundle.js
ADDED
|
@@ -0,0 +1,433 @@
|
|
|
1
|
+
import * as fs from 'node:fs/promises';
|
|
2
|
+
import * as os from 'node:os';
|
|
3
|
+
import * as path from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import { VIDEO_FORMATS, } from '@memberjunction/video-studio-core';
|
|
6
|
+
import { RenderWorkerError } from './backend.js';
|
|
7
|
+
import { BuildPreambleOptionsFromBundle, InjectPreambleIntoHtml, } from './preamble.js';
|
|
8
|
+
const PACKAGE_FONTS_DIR = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', 'assets', 'fonts');
|
|
9
|
+
const BUNDLED_FONT_FILES = ['Inter-Regular.ttf', 'JetBrainsMono-Regular.ttf'];
|
|
10
|
+
/** Maximum number of `Files` + `Assets` entries allowed in a single bundle. */
|
|
11
|
+
export const MAX_BUNDLE_ENTRIES = 2000;
|
|
12
|
+
/** Minimum allowed output frame dimension in pixels. */
|
|
13
|
+
export const MIN_FRAME_DIMENSION = 16;
|
|
14
|
+
/** Maximum allowed output frame dimension in pixels. */
|
|
15
|
+
export const MAX_FRAME_DIMENSION = 4096;
|
|
16
|
+
/** Maximum allowed relative deviation (1%) from the format's target aspect ratio. */
|
|
17
|
+
export const MAX_ASPECT_RATIO_TOLERANCE = 0.01;
|
|
18
|
+
/** Minimum allowed frame rate in frames per second. */
|
|
19
|
+
export const MIN_FPS = 1;
|
|
20
|
+
/** Maximum allowed frame rate in frames per second. */
|
|
21
|
+
export const MAX_FPS = 60;
|
|
22
|
+
/** Maximum allowed composition duration in seconds. */
|
|
23
|
+
export const MAX_DURATION_SECONDS = 600;
|
|
24
|
+
/**
|
|
25
|
+
* Validates a `RenderProjectBundle`, throwing `RenderWorkerError('InvalidBundle', ...)` on any violation.
|
|
26
|
+
*/
|
|
27
|
+
export function ValidateRenderBundle(bundle) {
|
|
28
|
+
if (!bundle || typeof bundle !== 'object') {
|
|
29
|
+
throw new RenderWorkerError('InvalidBundle', 'Bundle must be a non-null object.');
|
|
30
|
+
}
|
|
31
|
+
if (!Array.isArray(bundle.Files) || !Array.isArray(bundle.Assets)) {
|
|
32
|
+
throw new RenderWorkerError('InvalidBundle', 'Bundle.Files and Bundle.Assets must be arrays.');
|
|
33
|
+
}
|
|
34
|
+
if (!VIDEO_FORMATS.includes(bundle.Format)) {
|
|
35
|
+
throw new RenderWorkerError('InvalidBundle', `Bundle.Format must be one of ${VIDEO_FORMATS.join(', ')}, got "${String(bundle.Format)}".`);
|
|
36
|
+
}
|
|
37
|
+
if (typeof bundle.Seed !== 'number' || !Number.isInteger(bundle.Seed)) {
|
|
38
|
+
throw new RenderWorkerError('InvalidBundle', 'Bundle.Seed must be an integer.');
|
|
39
|
+
}
|
|
40
|
+
if (bundle.DataSnapshot !== undefined &&
|
|
41
|
+
(bundle.DataSnapshot === null ||
|
|
42
|
+
typeof bundle.DataSnapshot !== 'object' ||
|
|
43
|
+
Array.isArray(bundle.DataSnapshot))) {
|
|
44
|
+
throw new RenderWorkerError('InvalidBundle', 'Bundle.DataSnapshot must be a plain object.');
|
|
45
|
+
}
|
|
46
|
+
const totalEntries = bundle.Files.length + bundle.Assets.length;
|
|
47
|
+
if (totalEntries > MAX_BUNDLE_ENTRIES) {
|
|
48
|
+
throw new RenderWorkerError('InvalidBundle', `Bundle entry count (${totalEntries}) exceeds maximum allowed (${MAX_BUNDLE_ENTRIES}).`);
|
|
49
|
+
}
|
|
50
|
+
ValidateBundleRelativePath(bundle.EntryFile, 'EntryFile');
|
|
51
|
+
if (!/\.html?$/i.test(bundle.EntryFile)) {
|
|
52
|
+
throw new RenderWorkerError('InvalidBundle', `EntryFile "${bundle.EntryFile}" must be an .html or .htm file.`);
|
|
53
|
+
}
|
|
54
|
+
validateFilesAndAssets(bundle);
|
|
55
|
+
}
|
|
56
|
+
function validateFilesAndAssets(bundle) {
|
|
57
|
+
const seenLowerPaths = new Set();
|
|
58
|
+
let foundEntry = false;
|
|
59
|
+
for (const file of bundle.Files) {
|
|
60
|
+
if (!file || typeof file.Content !== 'string') {
|
|
61
|
+
throw new RenderWorkerError('InvalidBundle', 'Each composition file must have string Content.');
|
|
62
|
+
}
|
|
63
|
+
ValidateBundleRelativePath(file.Path, `Files[${file.Path}]`);
|
|
64
|
+
registerUniqueRelativePath(seenLowerPaths, file.Path);
|
|
65
|
+
if (file.Path === bundle.EntryFile) {
|
|
66
|
+
foundEntry = true;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (!foundEntry) {
|
|
70
|
+
throw new RenderWorkerError('InvalidBundle', `EntryFile "${bundle.EntryFile}" was not found in Bundle.Files.`);
|
|
71
|
+
}
|
|
72
|
+
for (const asset of bundle.Assets) {
|
|
73
|
+
if (!asset || typeof asset !== 'object') {
|
|
74
|
+
throw new RenderWorkerError('InvalidBundle', 'Each staged asset must be an object.');
|
|
75
|
+
}
|
|
76
|
+
ValidateBundleRelativePath(asset.RelativePath, `Assets[${asset.Key ?? ''}]`);
|
|
77
|
+
registerUniqueRelativePath(seenLowerPaths, asset.RelativePath);
|
|
78
|
+
validateBase64String(asset.DataBase64, asset.RelativePath);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Validates a bundle-relative path according to Step 5 security rules.
|
|
83
|
+
*/
|
|
84
|
+
export function ValidateBundleRelativePath(relPath, label) {
|
|
85
|
+
if (typeof relPath !== 'string' || relPath.length === 0 || relPath.trim().length === 0) {
|
|
86
|
+
throw new RenderWorkerError('InvalidBundle', `${label} must be a non-empty relative path.`);
|
|
87
|
+
}
|
|
88
|
+
if (/[\x00-\x1f\x7f]/.test(relPath)) {
|
|
89
|
+
throw new RenderWorkerError('InvalidBundle', `${label} contains a control character.`);
|
|
90
|
+
}
|
|
91
|
+
if (relPath.includes('\\')) {
|
|
92
|
+
throw new RenderWorkerError('InvalidBundle', `${label} must not contain backslashes.`);
|
|
93
|
+
}
|
|
94
|
+
if (relPath.startsWith('/') || path.posix.isAbsolute(relPath) || path.win32.isAbsolute(relPath)) {
|
|
95
|
+
throw new RenderWorkerError('InvalidBundle', `${label} must not be an absolute path.`);
|
|
96
|
+
}
|
|
97
|
+
if (/^[A-Za-z]:/.test(relPath)) {
|
|
98
|
+
throw new RenderWorkerError('InvalidBundle', `${label} must not start with a drive letter.`);
|
|
99
|
+
}
|
|
100
|
+
const segments = relPath.split('/');
|
|
101
|
+
for (const segment of segments) {
|
|
102
|
+
if (segment === '' || segment === '.' || segment === '..') {
|
|
103
|
+
throw new RenderWorkerError('InvalidBundle', `${label} contains a forbidden path segment ("${segment}") in "${relPath}".`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Validates render request geometry, frame rate, and duration, throwing `InvalidRequest` on error.
|
|
109
|
+
*/
|
|
110
|
+
export function ValidateRenderGeometry(params) {
|
|
111
|
+
const { Format, Width, Height, Fps, DurationSeconds } = params;
|
|
112
|
+
if (typeof Width !== 'number' ||
|
|
113
|
+
!Number.isInteger(Width) ||
|
|
114
|
+
Width < MIN_FRAME_DIMENSION ||
|
|
115
|
+
Width > MAX_FRAME_DIMENSION) {
|
|
116
|
+
throw new RenderWorkerError('InvalidRequest', `Width must be an integer in ${MIN_FRAME_DIMENSION}..${MAX_FRAME_DIMENSION}, got ${String(Width)}.`);
|
|
117
|
+
}
|
|
118
|
+
if (typeof Height !== 'number' ||
|
|
119
|
+
!Number.isInteger(Height) ||
|
|
120
|
+
Height < MIN_FRAME_DIMENSION ||
|
|
121
|
+
Height > MAX_FRAME_DIMENSION) {
|
|
122
|
+
throw new RenderWorkerError('InvalidRequest', `Height must be an integer in ${MIN_FRAME_DIMENSION}..${MAX_FRAME_DIMENSION}, got ${String(Height)}.`);
|
|
123
|
+
}
|
|
124
|
+
const expectedRatio = expectedAspectRatio(Format);
|
|
125
|
+
const actualRatio = Width / Height;
|
|
126
|
+
const relativeError = Math.abs(actualRatio - expectedRatio) / expectedRatio;
|
|
127
|
+
if (relativeError > MAX_ASPECT_RATIO_TOLERANCE) {
|
|
128
|
+
throw new RenderWorkerError('InvalidRequest', `Dimensions ${Width}x${Height} do not match format ${Format} aspect ratio within 1%.`);
|
|
129
|
+
}
|
|
130
|
+
if (Fps !== undefined) {
|
|
131
|
+
if (typeof Fps !== 'number' || !Number.isFinite(Fps) || Fps < MIN_FPS || Fps > MAX_FPS) {
|
|
132
|
+
throw new RenderWorkerError('InvalidRequest', `Fps must be in ${MIN_FPS}..${MAX_FPS}, got ${String(Fps)}.`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
if (DurationSeconds !== undefined) {
|
|
136
|
+
if (typeof DurationSeconds !== 'number' ||
|
|
137
|
+
!Number.isFinite(DurationSeconds) ||
|
|
138
|
+
DurationSeconds <= 0 ||
|
|
139
|
+
DurationSeconds > MAX_DURATION_SECONDS) {
|
|
140
|
+
throw new RenderWorkerError('InvalidRequest', `DurationSeconds must be > 0 and <= ${MAX_DURATION_SECONDS}, got ${String(DurationSeconds)}.`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
const COMPOSITION_ID_ATTR_REGEX = /\bdata-composition-id\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>"']+)/i;
|
|
145
|
+
function isCompositionTagNameChar(ch) {
|
|
146
|
+
if (ch === undefined) {
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
return ((ch >= 'a' && ch <= 'z') ||
|
|
150
|
+
(ch >= 'A' && ch <= 'Z') ||
|
|
151
|
+
(ch >= '0' && ch <= '9') ||
|
|
152
|
+
ch === '-');
|
|
153
|
+
}
|
|
154
|
+
function isCompositionWordChar(ch) {
|
|
155
|
+
if (ch === undefined) {
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
return ((ch >= 'a' && ch <= 'z') ||
|
|
159
|
+
(ch >= 'A' && ch <= 'Z') ||
|
|
160
|
+
(ch >= '0' && ch <= '9') ||
|
|
161
|
+
ch === '_');
|
|
162
|
+
}
|
|
163
|
+
function findCompositionOpeningTag(html) {
|
|
164
|
+
let cursor = 0;
|
|
165
|
+
while (cursor < html.length) {
|
|
166
|
+
const openIdx = html.indexOf('<', cursor);
|
|
167
|
+
if (openIdx === -1) {
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
let maxNameEnd = openIdx + 1;
|
|
171
|
+
while (maxNameEnd < html.length && isCompositionTagNameChar(html[maxNameEnd])) {
|
|
172
|
+
maxNameEnd++;
|
|
173
|
+
}
|
|
174
|
+
let minPrefixEnd = -1;
|
|
175
|
+
for (let k = openIdx + 2; k <= maxNameEnd; k++) {
|
|
176
|
+
if (isCompositionWordChar(html[k - 1]) !== isCompositionWordChar(html[k])) {
|
|
177
|
+
minPrefixEnd = k;
|
|
178
|
+
break;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
if (minPrefixEnd === -1) {
|
|
182
|
+
cursor = maxNameEnd;
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
const closeIdx = html.indexOf('>', minPrefixEnd);
|
|
186
|
+
if (closeIdx === -1) {
|
|
187
|
+
return null;
|
|
188
|
+
}
|
|
189
|
+
if (COMPOSITION_ID_ATTR_REGEX.test(html.slice(minPrefixEnd, closeIdx))) {
|
|
190
|
+
return html.slice(openIdx, closeIdx + 1);
|
|
191
|
+
}
|
|
192
|
+
cursor = closeIdx + 1;
|
|
193
|
+
}
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Validates that the entry HTML's `data-width`, `data-height`, and `data-duration` attributes
|
|
198
|
+
* (if present on `[data-composition-id]`) match the request's `Width`, `Height`, and `DurationSeconds`,
|
|
199
|
+
* throwing `RenderWorkerError('GEOMETRY_MISMATCH', ...)` (HTTP 400) on mismatch.
|
|
200
|
+
*/
|
|
201
|
+
export function ValidateCompositionGeometryMatch(bundle, params) {
|
|
202
|
+
if (!bundle || !Array.isArray(bundle.Files)) {
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
const entry = bundle.Files.find((f) => f && f.Path === bundle.EntryFile);
|
|
206
|
+
if (!entry || typeof entry.Content !== 'string') {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
const compositionTag = findCompositionOpeningTag(entry.Content);
|
|
210
|
+
const scope = compositionTag ?? entry.Content;
|
|
211
|
+
const widthMatch = /\bdata-width\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>"']+))/i.exec(scope);
|
|
212
|
+
if (widthMatch) {
|
|
213
|
+
const rawWidth = (widthMatch[1] ?? widthMatch[2] ?? widthMatch[3] ?? '').trim();
|
|
214
|
+
const attrWidth = Number.parseFloat(rawWidth);
|
|
215
|
+
if (!Number.isFinite(attrWidth) || attrWidth !== params.Width) {
|
|
216
|
+
throw new RenderWorkerError('GEOMETRY_MISMATCH', `Entry HTML data-width (${rawWidth}) does not match request Width (${params.Width}).`);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
const heightMatch = /\bdata-height\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>"']+))/i.exec(scope);
|
|
220
|
+
if (heightMatch) {
|
|
221
|
+
const rawHeight = (heightMatch[1] ?? heightMatch[2] ?? heightMatch[3] ?? '').trim();
|
|
222
|
+
const attrHeight = Number.parseFloat(rawHeight);
|
|
223
|
+
if (!Number.isFinite(attrHeight) || attrHeight !== params.Height) {
|
|
224
|
+
throw new RenderWorkerError('GEOMETRY_MISMATCH', `Entry HTML data-height (${rawHeight}) does not match request Height (${params.Height}).`);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
if (params.DurationSeconds !== undefined) {
|
|
228
|
+
const durationMatch = /\bdata-duration\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>"']+))/i.exec(scope);
|
|
229
|
+
if (durationMatch) {
|
|
230
|
+
const rawDuration = (durationMatch[1] ?? durationMatch[2] ?? durationMatch[3] ?? '').trim();
|
|
231
|
+
const attrDuration = Number.parseFloat(rawDuration);
|
|
232
|
+
if (!Number.isFinite(attrDuration) || Math.abs(attrDuration - params.DurationSeconds) > 0.05) {
|
|
233
|
+
throw new RenderWorkerError('GEOMETRY_MISMATCH', `Entry HTML data-duration (${rawDuration}) does not match request DurationSeconds (${params.DurationSeconds}) within 0.05s tolerance.`);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Reads the entry HTML's `data-fps` attribute on `[data-composition-id]` (or falls back to `defaultFps`),
|
|
240
|
+
* range-checking it against `MIN_FPS..MAX_FPS` with `RenderWorkerError('InvalidRequest', ...)`.
|
|
241
|
+
*/
|
|
242
|
+
export function ResolveCompositionFps(bundle, defaultFps = 30) {
|
|
243
|
+
if (!bundle || !Array.isArray(bundle.Files)) {
|
|
244
|
+
return defaultFps;
|
|
245
|
+
}
|
|
246
|
+
const entry = bundle.Files.find((f) => f && f.Path === bundle.EntryFile);
|
|
247
|
+
if (!entry || typeof entry.Content !== 'string') {
|
|
248
|
+
return defaultFps;
|
|
249
|
+
}
|
|
250
|
+
const compositionTag = findCompositionOpeningTag(entry.Content);
|
|
251
|
+
const scope = compositionTag ?? entry.Content;
|
|
252
|
+
const fpsMatch = /\bdata-fps\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>"']+))/i.exec(scope);
|
|
253
|
+
if (!fpsMatch) {
|
|
254
|
+
return defaultFps;
|
|
255
|
+
}
|
|
256
|
+
const rawFps = (fpsMatch[1] ?? fpsMatch[2] ?? fpsMatch[3] ?? '').trim();
|
|
257
|
+
const parsedFps = Number(rawFps);
|
|
258
|
+
if (rawFps.length === 0 || !Number.isFinite(parsedFps) || parsedFps < MIN_FPS || parsedFps > MAX_FPS) {
|
|
259
|
+
throw new RenderWorkerError('InvalidRequest', `Fps must be in ${MIN_FPS}..${MAX_FPS}, got ${rawFps || String(parsedFps)}.`);
|
|
260
|
+
}
|
|
261
|
+
return parsedFps;
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Reads the entry HTML's `data-duration` attribute on `[data-composition-id]` (or falls back to
|
|
265
|
+
* `defaultDurationSeconds`), range-checking it against `(0, MAX_DURATION_SECONDS]` with
|
|
266
|
+
* `RenderWorkerError('InvalidRequest', ...)`.
|
|
267
|
+
*/
|
|
268
|
+
export function ResolveCompositionDuration(bundle, defaultDurationSeconds = 5) {
|
|
269
|
+
if (!bundle || !Array.isArray(bundle.Files)) {
|
|
270
|
+
return defaultDurationSeconds;
|
|
271
|
+
}
|
|
272
|
+
const entry = bundle.Files.find((f) => f && f.Path === bundle.EntryFile);
|
|
273
|
+
if (!entry || typeof entry.Content !== 'string') {
|
|
274
|
+
return defaultDurationSeconds;
|
|
275
|
+
}
|
|
276
|
+
const compositionTag = findCompositionOpeningTag(entry.Content);
|
|
277
|
+
const scope = compositionTag ?? entry.Content;
|
|
278
|
+
const durationMatch = /\bdata-duration\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>"']+))/i.exec(scope);
|
|
279
|
+
if (!durationMatch) {
|
|
280
|
+
return defaultDurationSeconds;
|
|
281
|
+
}
|
|
282
|
+
const rawDuration = (durationMatch[1] ?? durationMatch[2] ?? durationMatch[3] ?? '').trim();
|
|
283
|
+
const parsedDuration = Number(rawDuration);
|
|
284
|
+
if (rawDuration.length === 0 ||
|
|
285
|
+
!Number.isFinite(parsedDuration) ||
|
|
286
|
+
parsedDuration <= 0 ||
|
|
287
|
+
parsedDuration > MAX_DURATION_SECONDS) {
|
|
288
|
+
throw new RenderWorkerError('InvalidRequest', `DurationSeconds must be > 0 and <= ${MAX_DURATION_SECONDS}, got ${rawDuration || String(parsedDuration)}.`);
|
|
289
|
+
}
|
|
290
|
+
return parsedDuration;
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Stages a validated `RenderProjectBundle` into a fresh `mkdtemp` directory and injects the preamble
|
|
294
|
+
* into every `.html` / `.htm` file (unless `options.InjectPreamble === false`).
|
|
295
|
+
*/
|
|
296
|
+
export async function StageRenderBundle(bundle, options) {
|
|
297
|
+
ValidateRenderBundle(bundle);
|
|
298
|
+
const parentDir = options?.TempRoot ?? os.tmpdir();
|
|
299
|
+
await fs.mkdir(parentDir, { recursive: true });
|
|
300
|
+
const rootDir = await fs.mkdtemp(path.join(parentDir, 'mj-video-bundle-'));
|
|
301
|
+
const injectPreamble = options?.InjectPreamble ?? true;
|
|
302
|
+
const preambleOptions = BuildPreambleOptionsFromBundle(bundle, options?.Geometry);
|
|
303
|
+
try {
|
|
304
|
+
const entryPath = resolveInsideRoot(rootDir, bundle.EntryFile);
|
|
305
|
+
for (const file of bundle.Files) {
|
|
306
|
+
const targetPath = resolveInsideRoot(rootDir, file.Path);
|
|
307
|
+
const isHtml = /\.html?$/i.test(file.Path);
|
|
308
|
+
const content = injectPreamble && isHtml
|
|
309
|
+
? InjectPreambleIntoHtml(file.Content, preambleOptions)
|
|
310
|
+
: file.Content;
|
|
311
|
+
await fs.mkdir(path.dirname(targetPath), { recursive: true });
|
|
312
|
+
await fs.writeFile(targetPath, content, 'utf8');
|
|
313
|
+
}
|
|
314
|
+
for (const asset of bundle.Assets) {
|
|
315
|
+
const targetPath = resolveInsideRoot(rootDir, asset.RelativePath);
|
|
316
|
+
const bytes = decodeBase64Strict(asset.DataBase64, asset.RelativePath);
|
|
317
|
+
await fs.mkdir(path.dirname(targetPath), { recursive: true });
|
|
318
|
+
await fs.writeFile(targetPath, bytes);
|
|
319
|
+
}
|
|
320
|
+
if (injectPreamble) {
|
|
321
|
+
await stageBundledDefaultFonts(rootDir);
|
|
322
|
+
}
|
|
323
|
+
let cleaned = false;
|
|
324
|
+
return {
|
|
325
|
+
RootDir: rootDir,
|
|
326
|
+
EntryPath: entryPath,
|
|
327
|
+
Cleanup: async () => {
|
|
328
|
+
if (cleaned) {
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
cleaned = true;
|
|
332
|
+
await fs.rm(rootDir, { recursive: true, force: true });
|
|
333
|
+
},
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
catch (error) {
|
|
337
|
+
await fs.rm(rootDir, { recursive: true, force: true }).catch(() => undefined);
|
|
338
|
+
throw error;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* Injects the CSP `<meta>`, bundled default `@font-face` `<style>`, and `window.MJVideo`
|
|
343
|
+
* preamble into every `.html` / `.htm` file of a bundle that was staged with `InjectPreamble: false`,
|
|
344
|
+
* and stages the worker's bundled SIL OFL default fonts (`Inter` and `JetBrains Mono`) into `__mj_fonts/`.
|
|
345
|
+
*/
|
|
346
|
+
export async function ApplyPreambleToStagedBundle(rootDir, bundle, preambleOptions) {
|
|
347
|
+
await stageBundledDefaultFonts(rootDir);
|
|
348
|
+
for (const file of bundle.Files) {
|
|
349
|
+
if (!/\.html?$/i.test(file.Path)) {
|
|
350
|
+
continue;
|
|
351
|
+
}
|
|
352
|
+
const targetPath = resolveInsideRoot(rootDir, file.Path);
|
|
353
|
+
const withPreamble = InjectPreambleIntoHtml(file.Content, preambleOptions);
|
|
354
|
+
await fs.writeFile(targetPath, withPreamble, 'utf8');
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
async function stageBundledDefaultFonts(rootDir) {
|
|
358
|
+
const destDir = path.join(rootDir, '__mj_fonts');
|
|
359
|
+
await fs.mkdir(destDir, { recursive: true });
|
|
360
|
+
for (const fileName of BUNDLED_FONT_FILES) {
|
|
361
|
+
const srcPath = path.join(PACKAGE_FONTS_DIR, fileName);
|
|
362
|
+
const destPath = path.join(destDir, fileName);
|
|
363
|
+
await fs.copyFile(srcPath, destPath);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
function resolveInsideRoot(rootDir, relPath) {
|
|
367
|
+
ValidateBundleRelativePath(relPath, relPath);
|
|
368
|
+
const resolvedRoot = path.resolve(rootDir);
|
|
369
|
+
const resolvedTarget = path.resolve(resolvedRoot, ...relPath.split('/'));
|
|
370
|
+
const rootWithSep = resolvedRoot.endsWith(path.sep) ? resolvedRoot : `${resolvedRoot}${path.sep}`;
|
|
371
|
+
if (!resolvedTarget.startsWith(rootWithSep) || resolvedTarget === resolvedRoot) {
|
|
372
|
+
throw new RenderWorkerError('InvalidBundle', `Resolved path "${relPath}" escapes bundle directory.`);
|
|
373
|
+
}
|
|
374
|
+
return resolvedTarget;
|
|
375
|
+
}
|
|
376
|
+
function registerUniqueRelativePath(seenLowerPaths, relPath) {
|
|
377
|
+
const key = relPath.toLowerCase();
|
|
378
|
+
if (seenLowerPaths.has(key)) {
|
|
379
|
+
throw new RenderWorkerError('InvalidBundle', `Duplicate bundle path "${relPath}".`);
|
|
380
|
+
}
|
|
381
|
+
seenLowerPaths.add(key);
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* Validates that `dataBase64` is a well-formed base64 string and returns the decoded `Buffer`.
|
|
385
|
+
*/
|
|
386
|
+
export function ValidateStrictBase64(dataBase64, label, allowEmpty = true, errorCode = 'InvalidBundle') {
|
|
387
|
+
if (typeof dataBase64 !== 'string') {
|
|
388
|
+
throw new RenderWorkerError(errorCode, `${label} must be a base64 string.`);
|
|
389
|
+
}
|
|
390
|
+
const stripped = dataBase64.replace(/\s+/g, '');
|
|
391
|
+
if (stripped.length === 0) {
|
|
392
|
+
if (!allowEmpty) {
|
|
393
|
+
throw new RenderWorkerError(errorCode, `${label} must be a non-empty base64 string.`);
|
|
394
|
+
}
|
|
395
|
+
return Buffer.alloc(0);
|
|
396
|
+
}
|
|
397
|
+
if (stripped.length % 4 !== 0 ||
|
|
398
|
+
!/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(stripped)) {
|
|
399
|
+
throw new RenderWorkerError(errorCode, `${label} contains invalid base64 data.`);
|
|
400
|
+
}
|
|
401
|
+
return Buffer.from(stripped, 'base64');
|
|
402
|
+
}
|
|
403
|
+
function validateBase64String(dataBase64, label) {
|
|
404
|
+
ValidateStrictBase64(dataBase64, `Asset "${label}"`, true, 'InvalidBundle');
|
|
405
|
+
}
|
|
406
|
+
function decodeBase64Strict(dataBase64, label) {
|
|
407
|
+
return ValidateStrictBase64(dataBase64, `Asset "${label}"`, true, 'InvalidBundle');
|
|
408
|
+
}
|
|
409
|
+
function expectedAspectRatio(format) {
|
|
410
|
+
switch (format) {
|
|
411
|
+
case '16:9':
|
|
412
|
+
return 16 / 9;
|
|
413
|
+
case '9:16':
|
|
414
|
+
return 9 / 16;
|
|
415
|
+
case '1:1':
|
|
416
|
+
return 1;
|
|
417
|
+
default:
|
|
418
|
+
throw new RenderWorkerError('InvalidBundle', `Unsupported format "${String(format)}".`);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* Shared entry helper used by `CaptureStills`, `RunCheckCli`, and `MeasureText` to ensure
|
|
423
|
+
* `path.join(rootDir, 'index.html')` matches `entryFile` by always overwriting `index.html`
|
|
424
|
+
* when `entryFile !== 'index.html'` (VS-RND-1 Fix 7b / VS-RND-5 Fix 5).
|
|
425
|
+
*/
|
|
426
|
+
export async function EnsureIndexHtmlForServer(rootDir, entryFile) {
|
|
427
|
+
if (entryFile === 'index.html') {
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
const indexTarget = path.join(rootDir, 'index.html');
|
|
431
|
+
await fs.copyFile(path.join(rootDir, entryFile), indexTarget);
|
|
432
|
+
}
|
|
433
|
+
//# sourceMappingURL=bundle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundle.js","sourceRoot":"","sources":["../src/bundle.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { type CheckIssue, type VideoFormat } from '@memberjunction/video-studio-core';
|
|
2
|
+
import type { MeasuredText } from '../backend.js';
|
|
3
|
+
/** Check issue code emitted when a rendered text box extends outside the format's safe area. */
|
|
4
|
+
export declare const MJ_SAFE_AREA_CODE = "MJ_SAFE_AREA";
|
|
5
|
+
/** Check issue code emitted when rendered text has `FontSizePx` below the minimum threshold. */
|
|
6
|
+
export declare const MJ_MIN_TEXT_SIZE_CODE = "MJ_MIN_TEXT_SIZE";
|
|
7
|
+
/** Check issue code emitted when rendered text outside `data-mj-bound` contains an unapproved numeric literal. */
|
|
8
|
+
export declare const MJ_UNBOUND_LITERAL_RENDERED_CODE = "MJ_UNBOUND_LITERAL_RENDERED";
|
|
9
|
+
/** Check issue code emitted when a `data-mj-bound="<key>"` attribute is empty or not in `BoundDataLiterals`. */
|
|
10
|
+
export declare const MJ_BOUND_KEY_UNKNOWN_CODE = "MJ_BOUND_KEY_UNKNOWN";
|
|
11
|
+
/** Check issue code emitted at a settle timestamp when a `data-mj-bound="<key>"` element renders a numeric token not in `BoundDataLiterals[key]`. */
|
|
12
|
+
export declare const MJ_BOUND_VALUE_MISMATCH_CODE = "MJ_BOUND_VALUE_MISMATCH";
|
|
13
|
+
/** Check issue code emitted when a required provenance / as-of card substring is missing on the final frame. */
|
|
14
|
+
export declare const MJ_ASOF_CARD_MISSING_CODE = "MJ_ASOF_CARD_MISSING";
|
|
15
|
+
/** Check issue code emitted when rendered text uses a font family that is not bundled. */
|
|
16
|
+
export declare const MJ_UNBUNDLED_FONT_CODE = "MJ_UNBUNDLED_FONT";
|
|
17
|
+
/**
|
|
18
|
+
* Fractional safe-area insets (`Top`, `Bottom`, `Left`, `Right`) per video format.
|
|
19
|
+
*/
|
|
20
|
+
export interface SafeAreaInsets {
|
|
21
|
+
Top: number;
|
|
22
|
+
Bottom: number;
|
|
23
|
+
Left: number;
|
|
24
|
+
Right: number;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Tunable safe-area inset fractions per `VideoFormat` (VS-RND-5 Decision 3).
|
|
28
|
+
*
|
|
29
|
+
* - `16:9` and `1:1`: `0.05` on every side.
|
|
30
|
+
* - `9:16`: top `0.10`, bottom `0.20`, left `0.06`, right `0.12`.
|
|
31
|
+
*/
|
|
32
|
+
export declare const SAFE_AREA_INSETS: Readonly<Record<VideoFormat, SafeAreaInsets>>;
|
|
33
|
+
/**
|
|
34
|
+
* Tunable minimum text size as a fraction of the frame's short edge (VS-RND-5 Decision 3).
|
|
35
|
+
* At `1920x1080` or `1080x1920` (short edge `1080`), `0.025 * 1080 = 27px`.
|
|
36
|
+
*/
|
|
37
|
+
export declare const MIN_TEXT_SIZE_SHORT_EDGE_RATIO = 0.025;
|
|
38
|
+
/**
|
|
39
|
+
* Options for `EvaluateDomRules`.
|
|
40
|
+
*/
|
|
41
|
+
export interface DomRulesOptions {
|
|
42
|
+
Format: VideoFormat;
|
|
43
|
+
Width: number;
|
|
44
|
+
Height: number;
|
|
45
|
+
AllowedDataLiterals?: string[];
|
|
46
|
+
BoundDataLiterals?: Record<string, string[]>;
|
|
47
|
+
SettleTimestampsSeconds?: number[];
|
|
48
|
+
RequiredFinalFrameText?: string[];
|
|
49
|
+
FinalFrameTimestampSeconds?: number;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Evaluates pure DOM rules (`MJ_SAFE_AREA`, `MJ_MIN_TEXT_SIZE`, `MJ_UNBOUND_LITERAL_RENDERED`,
|
|
53
|
+
* `MJ_BOUND_KEY_UNKNOWN`, `MJ_BOUND_VALUE_MISMATCH`, `MJ_ASOF_CARD_MISSING`, `MJ_UNBUNDLED_FONT`)
|
|
54
|
+
* over a flat or per-timestamp list of `MeasuredText` items.
|
|
55
|
+
*/
|
|
56
|
+
export declare function EvaluateDomRules(measurements: readonly MeasuredText[], options: DomRulesOptions): CheckIssue[];
|
|
57
|
+
//# sourceMappingURL=dom-rules.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dom-rules.d.ts","sourceRoot":"","sources":["../../src/checks/dom-rules.ts"],"names":[],"mappings":"AAAA,OAAO,EAEH,KAAK,UAAU,EACf,KAAK,WAAW,EACnB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAGlD,gGAAgG;AAChG,eAAO,MAAM,iBAAiB,iBAAiB,CAAC;AAEhD,gGAAgG;AAChG,eAAO,MAAM,qBAAqB,qBAAqB,CAAC;AAExD,kHAAkH;AAClH,eAAO,MAAM,gCAAgC,gCAAgC,CAAC;AAE9E,gHAAgH;AAChH,eAAO,MAAM,yBAAyB,yBAAyB,CAAC;AAEhE,qJAAqJ;AACrJ,eAAO,MAAM,4BAA4B,4BAA4B,CAAC;AAEtE,gHAAgH;AAChH,eAAO,MAAM,yBAAyB,yBAAyB,CAAC;AAEhE,0FAA0F;AAC1F,eAAO,MAAM,sBAAsB,sBAAsB,CAAC;AAE1D;;GAEG;AACH,MAAM,WAAW,cAAc;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,EAAE,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,CAIzE,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,8BAA8B,QAAQ,CAAC;AAEpD;;GAEG;AACH,MAAM,WAAW,eAAe;IAC5B,MAAM,EAAE,WAAW,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC/B,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAC7C,uBAAuB,CAAC,EAAE,MAAM,EAAE,CAAC;IACnC,sBAAsB,CAAC,EAAE,MAAM,EAAE,CAAC;IAClC,0BAA0B,CAAC,EAAE,MAAM,CAAC;CACvC;AAKD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC5B,YAAY,EAAE,SAAS,YAAY,EAAE,EACrC,OAAO,EAAE,eAAe,GACzB,UAAU,EAAE,CA8Bd"}
|