@memberjunction/video-studio-render-worker 0.0.1-seed.1 → 6.2.0-edge.8
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/server.js
ADDED
|
@@ -0,0 +1,526 @@
|
|
|
1
|
+
import { createHash, randomUUID, timingSafeEqual } from 'node:crypto';
|
|
2
|
+
import * as http from 'node:http';
|
|
3
|
+
import { RENDER_WORKER_ROUTES, } from '@memberjunction/video-studio-core';
|
|
4
|
+
import { RenderWorkerError, } from './backend.js';
|
|
5
|
+
import { StageRenderBundle, ValidateCompositionGeometryMatch, ValidateRenderGeometry, } from './bundle.js';
|
|
6
|
+
import { RunCheckJob, RunContactSheetJob, RunKeyframesJob, RunRenderJob, RunStillsJob, } from './jobs.js';
|
|
7
|
+
import { RunLintGate } from './lint-gate.js';
|
|
8
|
+
/** Default bind host for the render worker HTTP server. */
|
|
9
|
+
export const DEFAULT_HOST = '127.0.0.1';
|
|
10
|
+
/** Default bind port (`0` selects an ephemeral OS-assigned port). */
|
|
11
|
+
export const DEFAULT_PORT = 0;
|
|
12
|
+
/** Default maximum JSON request body size in megabytes (256 MiB). */
|
|
13
|
+
export const DEFAULT_MAX_BODY_MB = 256;
|
|
14
|
+
/** Default maximum JSON request body size in bytes (256 MiB). */
|
|
15
|
+
export const DEFAULT_MAX_BODY_BYTES = DEFAULT_MAX_BODY_MB * 1024 * 1024;
|
|
16
|
+
/** Default maximum concurrent jobs (`/check`, `/render`, `/stills`, `/contact-sheet`, `/keyframes`). */
|
|
17
|
+
export const DEFAULT_CONCURRENCY = 1;
|
|
18
|
+
/** Default per-job timeout ceiling (30 minutes). */
|
|
19
|
+
export const DEFAULT_MAX_TIMEOUT_MS = 30 * 60 * 1000;
|
|
20
|
+
/** Default timeout for non-render jobs (`/check`, `/stills`, `/contact-sheet`, `/keyframes`, pre-render lint) (5 minutes). */
|
|
21
|
+
export const DEFAULT_NON_RENDER_TIMEOUT_MS = 5 * 60 * 1000;
|
|
22
|
+
/** Default heartbeat interval for streaming `/render` responses (15 seconds). */
|
|
23
|
+
export const DEFAULT_HEARTBEAT_MS = 15_000;
|
|
24
|
+
/** Default TTL for unfetched rendered MP4 buffers in the video store (10 minutes). */
|
|
25
|
+
export const DEFAULT_VIDEO_TTL_MS = 10 * 60 * 1000;
|
|
26
|
+
/**
|
|
27
|
+
* Returns `true` when `host` is a loopback address (`127.0.0.1`, `::1`, `::ffff:127.0.0.1`, or `localhost`).
|
|
28
|
+
*/
|
|
29
|
+
export function IsLoopbackHost(host) {
|
|
30
|
+
const normalized = host.trim().toLowerCase().replace(/^\[|\]$/g, '');
|
|
31
|
+
return (normalized === '127.0.0.1' ||
|
|
32
|
+
normalized === '::1' ||
|
|
33
|
+
normalized === '::ffff:127.0.0.1' ||
|
|
34
|
+
normalized === 'localhost');
|
|
35
|
+
}
|
|
36
|
+
function assertLoopbackOrToken(host, bearerToken) {
|
|
37
|
+
if (!IsLoopbackHost(host) && !bearerToken) {
|
|
38
|
+
throw new Error(`Refusing to bind render worker to non-loopback host "${host}" without a bearer token.`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Creates an HTTP server implementing all `RENDER_WORKER_ROUTES`.
|
|
43
|
+
*
|
|
44
|
+
* Notice that this module does NOT import `hyperframes-backend.ts`; callers inject `Backend`.
|
|
45
|
+
*/
|
|
46
|
+
export function CreateRenderWorkerServer(options) {
|
|
47
|
+
const backend = options.Backend;
|
|
48
|
+
const defaultHost = options.Host?.trim() || DEFAULT_HOST;
|
|
49
|
+
const defaultPort = options.Port !== undefined && Number.isFinite(options.Port) && options.Port >= 0
|
|
50
|
+
? options.Port
|
|
51
|
+
: DEFAULT_PORT;
|
|
52
|
+
const bearerToken = (options.Token ?? options.BearerToken)?.trim() || undefined;
|
|
53
|
+
assertLoopbackOrToken(defaultHost, bearerToken);
|
|
54
|
+
const maxBodyBytes = options.MaxBodyBytes ??
|
|
55
|
+
(options.MaxBodyMb !== undefined && Number.isFinite(options.MaxBodyMb) && options.MaxBodyMb > 0
|
|
56
|
+
? Math.round(options.MaxBodyMb * 1024 * 1024)
|
|
57
|
+
: DEFAULT_MAX_BODY_BYTES);
|
|
58
|
+
const maxConcurrency = Math.max(1, options.Concurrency ?? DEFAULT_CONCURRENCY);
|
|
59
|
+
const maxTimeoutMs = Math.max(50, options.MaxTimeoutMs ?? DEFAULT_MAX_TIMEOUT_MS);
|
|
60
|
+
const nonRenderTimeoutMs = Math.min(maxTimeoutMs, Math.max(50, options.NonRenderTimeoutMs ?? DEFAULT_NON_RENDER_TIMEOUT_MS));
|
|
61
|
+
const tempRoot = options.TempRoot?.trim() || undefined;
|
|
62
|
+
const heartbeatMs = Math.max(10, options.HeartbeatIntervalMs ?? DEFAULT_HEARTBEAT_MS);
|
|
63
|
+
const videoTtlMs = Math.max(10, options.VideoTtlMs ?? DEFAULT_VIDEO_TTL_MS);
|
|
64
|
+
const semaphore = new AsyncSemaphore(maxConcurrency);
|
|
65
|
+
const activeAbortControllers = new Set();
|
|
66
|
+
const videoStore = new Map();
|
|
67
|
+
let boundPort = 0;
|
|
68
|
+
const storeVideo = (bytes) => {
|
|
69
|
+
const videoId = randomUUID();
|
|
70
|
+
const timer = setTimeout(() => {
|
|
71
|
+
videoStore.delete(videoId);
|
|
72
|
+
}, videoTtlMs);
|
|
73
|
+
timer.unref();
|
|
74
|
+
videoStore.set(videoId, { Bytes: bytes, Timer: timer });
|
|
75
|
+
return videoId;
|
|
76
|
+
};
|
|
77
|
+
const takeVideo = (videoId) => {
|
|
78
|
+
const entry = videoStore.get(videoId);
|
|
79
|
+
if (!entry) {
|
|
80
|
+
return undefined;
|
|
81
|
+
}
|
|
82
|
+
clearTimeout(entry.Timer);
|
|
83
|
+
videoStore.delete(videoId);
|
|
84
|
+
return entry.Bytes;
|
|
85
|
+
};
|
|
86
|
+
const httpServer = http.createServer((req, res) => {
|
|
87
|
+
void handleRequest(req, res).catch((err) => {
|
|
88
|
+
if (!res.headersSent) {
|
|
89
|
+
sendErrorJson(res, toRenderWorkerError(err));
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
res.destroy();
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
async function handleRequest(req, res) {
|
|
97
|
+
const method = req.method ?? 'GET';
|
|
98
|
+
const urlPath = (req.url ?? '/').split('?')[0] ?? '/';
|
|
99
|
+
if (bearerToken && !verifyBearerToken(req.headers.authorization, bearerToken)) {
|
|
100
|
+
sendErrorJson(res, new RenderWorkerError('Unauthorized', 'Missing or invalid Bearer token.'));
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
if (method === 'GET' && urlPath === RENDER_WORKER_ROUTES.Health) {
|
|
104
|
+
const health = await backend.Health();
|
|
105
|
+
sendJson(res, health.Healthy ? 200 : 503, health);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
if (method === 'GET' && urlPath.startsWith(`${RENDER_WORKER_ROUTES.Video}/`)) {
|
|
109
|
+
const videoId = decodeURIComponent(urlPath.slice(RENDER_WORKER_ROUTES.Video.length + 1));
|
|
110
|
+
const videoBytes = videoId ? takeVideo(videoId) : undefined;
|
|
111
|
+
if (!videoBytes) {
|
|
112
|
+
sendErrorJson(res, new RenderWorkerError('NotFound', `Video "${videoId}" was not found.`));
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
res.writeHead(200, {
|
|
116
|
+
'Content-Type': 'video/mp4',
|
|
117
|
+
'Content-Length': String(videoBytes.byteLength),
|
|
118
|
+
'Cache-Control': 'no-store',
|
|
119
|
+
});
|
|
120
|
+
res.end(Buffer.from(videoBytes));
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
if (method === 'POST' && urlPath === RENDER_WORKER_ROUTES.Check) {
|
|
124
|
+
const body = await readJsonBody(req, maxBodyBytes);
|
|
125
|
+
const result = await runHeavyJobWithGuards(req, res, nonRenderTimeoutMs, (signal) => RunCheckJob(body, backend, signal, { TempRoot: tempRoot }));
|
|
126
|
+
if (result !== undefined) {
|
|
127
|
+
sendJson(res, 200, result);
|
|
128
|
+
}
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
if (method === 'POST' && urlPath === RENDER_WORKER_ROUTES.Stills) {
|
|
132
|
+
const body = await readJsonBody(req, maxBodyBytes);
|
|
133
|
+
const result = await runHeavyJobWithGuards(req, res, body.TimeoutMs ?? nonRenderTimeoutMs, (signal) => RunStillsJob(body, backend, signal, { TempRoot: tempRoot }));
|
|
134
|
+
if (result !== undefined) {
|
|
135
|
+
sendJson(res, 200, result);
|
|
136
|
+
}
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
if (method === 'POST' && urlPath === RENDER_WORKER_ROUTES.ContactSheet) {
|
|
140
|
+
const body = await readJsonBody(req, maxBodyBytes);
|
|
141
|
+
const result = await runHeavyJobWithGuards(req, res, nonRenderTimeoutMs, (signal) => RunContactSheetJob(body, backend, signal, { TempRoot: tempRoot }));
|
|
142
|
+
if (result !== undefined) {
|
|
143
|
+
sendJson(res, 200, result);
|
|
144
|
+
}
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
if (method === 'POST' && urlPath === RENDER_WORKER_ROUTES.Keyframes) {
|
|
148
|
+
const body = await readJsonBody(req, maxBodyBytes);
|
|
149
|
+
const result = await runHeavyJobWithGuards(req, res, nonRenderTimeoutMs, (signal) => RunKeyframesJob(body, backend, signal, { TempRoot: tempRoot }));
|
|
150
|
+
if (result !== undefined) {
|
|
151
|
+
sendJson(res, 200, result);
|
|
152
|
+
}
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
if (method === 'POST' && urlPath === RENDER_WORKER_ROUTES.Render) {
|
|
156
|
+
const body = await readJsonBody(req, maxBodyBytes);
|
|
157
|
+
await handleStreamingRender(req, res, body);
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
sendErrorJson(res, new RenderWorkerError('NotFound', `Route ${method} ${urlPath} was not found.`));
|
|
161
|
+
}
|
|
162
|
+
async function handleStreamingRender(req, res, body) {
|
|
163
|
+
if (!body || typeof body !== 'object' || !body.Bundle) {
|
|
164
|
+
throw new RenderWorkerError('InvalidRequest', 'RenderRequest.Bundle is required.');
|
|
165
|
+
}
|
|
166
|
+
ValidateRenderGeometry({
|
|
167
|
+
Format: body.Bundle.Format,
|
|
168
|
+
Width: body.Width,
|
|
169
|
+
Height: body.Height,
|
|
170
|
+
Fps: body.Fps,
|
|
171
|
+
DurationSeconds: body.DurationSeconds,
|
|
172
|
+
});
|
|
173
|
+
ValidateCompositionGeometryMatch(body.Bundle, {
|
|
174
|
+
Width: body.Width,
|
|
175
|
+
Height: body.Height,
|
|
176
|
+
DurationSeconds: body.DurationSeconds,
|
|
177
|
+
});
|
|
178
|
+
const controller = new AbortController();
|
|
179
|
+
activeAbortControllers.add(controller);
|
|
180
|
+
let timedOut = false;
|
|
181
|
+
let activeTimeoutMs = maxTimeoutMs;
|
|
182
|
+
const effectiveTimeout = Math.min(maxTimeoutMs, typeof body.TimeoutMs === 'number' && body.TimeoutMs > 0
|
|
183
|
+
? body.TimeoutMs
|
|
184
|
+
: maxTimeoutMs);
|
|
185
|
+
const preLintTimeoutMs = Math.min(nonRenderTimeoutMs, effectiveTimeout);
|
|
186
|
+
activeTimeoutMs = preLintTimeoutMs;
|
|
187
|
+
const onDisconnect = () => {
|
|
188
|
+
if (!res.writableEnded) {
|
|
189
|
+
controller.abort();
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
req.once('aborted', onDisconnect);
|
|
193
|
+
res.once('close', onDisconnect);
|
|
194
|
+
let timeoutTimer;
|
|
195
|
+
let heartbeatTimer;
|
|
196
|
+
let acquired = false;
|
|
197
|
+
let preStage;
|
|
198
|
+
try {
|
|
199
|
+
await semaphore.Acquire(controller.signal);
|
|
200
|
+
acquired = true;
|
|
201
|
+
timeoutTimer = setTimeout(() => {
|
|
202
|
+
timedOut = true;
|
|
203
|
+
controller.abort();
|
|
204
|
+
}, preLintTimeoutMs);
|
|
205
|
+
timeoutTimer.unref();
|
|
206
|
+
preStage = await StageRenderBundle(body.Bundle, {
|
|
207
|
+
TempRoot: tempRoot,
|
|
208
|
+
Geometry: {
|
|
209
|
+
Width: body.Width,
|
|
210
|
+
Height: body.Height,
|
|
211
|
+
Fps: body.Fps,
|
|
212
|
+
DurationSeconds: body.DurationSeconds,
|
|
213
|
+
},
|
|
214
|
+
});
|
|
215
|
+
if (controller.signal.aborted) {
|
|
216
|
+
throw new RenderWorkerError('Cancelled', 'Render job was cancelled.');
|
|
217
|
+
}
|
|
218
|
+
const check = await RunLintGate(body.Bundle, preStage.RootDir, backend);
|
|
219
|
+
if (controller.signal.aborted) {
|
|
220
|
+
throw new RenderWorkerError('Cancelled', 'Render job was cancelled.');
|
|
221
|
+
}
|
|
222
|
+
if (check.BlockRender) {
|
|
223
|
+
throw new RenderWorkerError('LintBlocked', 'Composition failed pre-render lint checks.', check.Issues);
|
|
224
|
+
}
|
|
225
|
+
clearTimeout(timeoutTimer);
|
|
226
|
+
activeTimeoutMs = effectiveTimeout;
|
|
227
|
+
timeoutTimer = setTimeout(() => {
|
|
228
|
+
timedOut = true;
|
|
229
|
+
controller.abort();
|
|
230
|
+
}, effectiveTimeout);
|
|
231
|
+
timeoutTimer.unref();
|
|
232
|
+
res.writeHead(200, {
|
|
233
|
+
'Content-Type': 'application/x-ndjson; charset=utf-8',
|
|
234
|
+
'Cache-Control': 'no-cache, no-transform',
|
|
235
|
+
Connection: 'keep-alive',
|
|
236
|
+
});
|
|
237
|
+
const writeEvent = (event) => {
|
|
238
|
+
if (!res.writableEnded && !res.destroyed) {
|
|
239
|
+
res.write(`${JSON.stringify(event)}\n`);
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
heartbeatTimer = setInterval(() => {
|
|
243
|
+
writeEvent({ Type: 'Heartbeat' });
|
|
244
|
+
}, heartbeatMs);
|
|
245
|
+
heartbeatTimer.unref();
|
|
246
|
+
try {
|
|
247
|
+
const renderResult = await RunRenderJob(body, backend, (progress) => {
|
|
248
|
+
writeEvent({ Type: 'Progress', Progress: progress });
|
|
249
|
+
}, controller.signal, { SkipLintGate: true, TempRoot: tempRoot, StagedRootDir: preStage.RootDir });
|
|
250
|
+
const videoId = storeVideo(renderResult.Video);
|
|
251
|
+
const metadata = {
|
|
252
|
+
VideoID: videoId,
|
|
253
|
+
VideoSizeBytes: renderResult.Video.byteLength,
|
|
254
|
+
Format: renderResult.Format,
|
|
255
|
+
MimeType: renderResult.MimeType,
|
|
256
|
+
Width: renderResult.Width,
|
|
257
|
+
Height: renderResult.Height,
|
|
258
|
+
Fps: renderResult.Fps,
|
|
259
|
+
DurationSeconds: renderResult.DurationSeconds,
|
|
260
|
+
FrameCount: renderResult.FrameCount,
|
|
261
|
+
HasAudio: renderResult.HasAudio,
|
|
262
|
+
RendererVersion: renderResult.RendererVersion,
|
|
263
|
+
RenderDurationMs: renderResult.RenderDurationMs,
|
|
264
|
+
};
|
|
265
|
+
writeEvent({ Type: 'Result', Result: metadata });
|
|
266
|
+
}
|
|
267
|
+
catch (err) {
|
|
268
|
+
const mappedErr = timedOut
|
|
269
|
+
? new RenderWorkerError('Timeout', `Render job exceeded timeout of ${activeTimeoutMs} ms.`)
|
|
270
|
+
: toRenderWorkerError(err);
|
|
271
|
+
writeEvent({ Type: 'Error', Error: mappedErr.ToBody() });
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
catch (err) {
|
|
275
|
+
if (timedOut) {
|
|
276
|
+
throw new RenderWorkerError('Timeout', `Render job exceeded timeout of ${activeTimeoutMs} ms.`);
|
|
277
|
+
}
|
|
278
|
+
throw err;
|
|
279
|
+
}
|
|
280
|
+
finally {
|
|
281
|
+
if (heartbeatTimer !== undefined) {
|
|
282
|
+
clearInterval(heartbeatTimer);
|
|
283
|
+
}
|
|
284
|
+
if (timeoutTimer !== undefined) {
|
|
285
|
+
clearTimeout(timeoutTimer);
|
|
286
|
+
}
|
|
287
|
+
req.removeListener('aborted', onDisconnect);
|
|
288
|
+
res.removeListener('close', onDisconnect);
|
|
289
|
+
activeAbortControllers.delete(controller);
|
|
290
|
+
if (acquired) {
|
|
291
|
+
semaphore.Release();
|
|
292
|
+
}
|
|
293
|
+
let cleanupErr;
|
|
294
|
+
if (preStage !== undefined) {
|
|
295
|
+
try {
|
|
296
|
+
await preStage.Cleanup();
|
|
297
|
+
}
|
|
298
|
+
catch (err) {
|
|
299
|
+
cleanupErr = err;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
if (res.headersSent && !res.writableEnded && !res.destroyed) {
|
|
303
|
+
res.end();
|
|
304
|
+
}
|
|
305
|
+
if (cleanupErr !== undefined) {
|
|
306
|
+
throw cleanupErr;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
async function runHeavyJobWithGuards(req, res, requestedTimeoutMs, fn) {
|
|
311
|
+
return runWithSemaphoreAndTimeout(req, res, requestedTimeoutMs, fn);
|
|
312
|
+
}
|
|
313
|
+
async function runWithSemaphoreAndTimeout(req, res, requestedTimeoutMs, fn) {
|
|
314
|
+
const controller = new AbortController();
|
|
315
|
+
activeAbortControllers.add(controller);
|
|
316
|
+
let timedOut = false;
|
|
317
|
+
const effectiveTimeout = Math.min(maxTimeoutMs, typeof requestedTimeoutMs === 'number' && requestedTimeoutMs > 0
|
|
318
|
+
? requestedTimeoutMs
|
|
319
|
+
: maxTimeoutMs);
|
|
320
|
+
const onDisconnect = () => {
|
|
321
|
+
if (!res.writableEnded) {
|
|
322
|
+
controller.abort();
|
|
323
|
+
}
|
|
324
|
+
};
|
|
325
|
+
req.once('aborted', onDisconnect);
|
|
326
|
+
res.once('close', onDisconnect);
|
|
327
|
+
let timeoutTimer;
|
|
328
|
+
let acquired = false;
|
|
329
|
+
try {
|
|
330
|
+
await semaphore.Acquire(controller.signal);
|
|
331
|
+
acquired = true;
|
|
332
|
+
timeoutTimer = setTimeout(() => {
|
|
333
|
+
timedOut = true;
|
|
334
|
+
controller.abort();
|
|
335
|
+
}, effectiveTimeout);
|
|
336
|
+
timeoutTimer.unref();
|
|
337
|
+
return await fn(controller.signal);
|
|
338
|
+
}
|
|
339
|
+
catch (err) {
|
|
340
|
+
if (timedOut) {
|
|
341
|
+
throw new RenderWorkerError('Timeout', `Render job exceeded timeout of ${effectiveTimeout} ms.`);
|
|
342
|
+
}
|
|
343
|
+
throw err;
|
|
344
|
+
}
|
|
345
|
+
finally {
|
|
346
|
+
if (timeoutTimer !== undefined) {
|
|
347
|
+
clearTimeout(timeoutTimer);
|
|
348
|
+
}
|
|
349
|
+
req.removeListener('aborted', onDisconnect);
|
|
350
|
+
res.removeListener('close', onDisconnect);
|
|
351
|
+
activeAbortControllers.delete(controller);
|
|
352
|
+
if (acquired) {
|
|
353
|
+
semaphore.Release();
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
return {
|
|
358
|
+
get HttpServer() {
|
|
359
|
+
return httpServer;
|
|
360
|
+
},
|
|
361
|
+
get Port() {
|
|
362
|
+
return boundPort;
|
|
363
|
+
},
|
|
364
|
+
async Listen(port = defaultPort, host = defaultHost) {
|
|
365
|
+
assertLoopbackOrToken(host, bearerToken);
|
|
366
|
+
return new Promise((resolve, reject) => {
|
|
367
|
+
const onError = (err) => {
|
|
368
|
+
httpServer.removeListener('listening', onListening);
|
|
369
|
+
reject(err);
|
|
370
|
+
};
|
|
371
|
+
const onListening = () => {
|
|
372
|
+
httpServer.removeListener('error', onError);
|
|
373
|
+
const addr = httpServer.address();
|
|
374
|
+
boundPort = typeof addr === 'object' && addr ? addr.port : port;
|
|
375
|
+
resolve(boundPort);
|
|
376
|
+
};
|
|
377
|
+
httpServer.once('error', onError);
|
|
378
|
+
httpServer.once('listening', onListening);
|
|
379
|
+
httpServer.listen(port, host);
|
|
380
|
+
});
|
|
381
|
+
},
|
|
382
|
+
async Close() {
|
|
383
|
+
for (const controller of activeAbortControllers) {
|
|
384
|
+
controller.abort();
|
|
385
|
+
}
|
|
386
|
+
activeAbortControllers.clear();
|
|
387
|
+
for (const entry of videoStore.values()) {
|
|
388
|
+
clearTimeout(entry.Timer);
|
|
389
|
+
}
|
|
390
|
+
videoStore.clear();
|
|
391
|
+
if (!httpServer.listening) {
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
httpServer.closeIdleConnections();
|
|
395
|
+
httpServer.closeAllConnections();
|
|
396
|
+
await new Promise((resolve) => {
|
|
397
|
+
httpServer.close(() => resolve());
|
|
398
|
+
});
|
|
399
|
+
},
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
class AsyncSemaphore {
|
|
403
|
+
constructor(maxConcurrency) {
|
|
404
|
+
this.activeCount = 0;
|
|
405
|
+
this.queue = [];
|
|
406
|
+
this.maxConcurrency = maxConcurrency;
|
|
407
|
+
}
|
|
408
|
+
Acquire(signal) {
|
|
409
|
+
if (signal.aborted) {
|
|
410
|
+
return Promise.reject(new RenderWorkerError('Cancelled', 'Render job was cancelled while queued.'));
|
|
411
|
+
}
|
|
412
|
+
if (this.activeCount < this.maxConcurrency) {
|
|
413
|
+
this.activeCount++;
|
|
414
|
+
return Promise.resolve();
|
|
415
|
+
}
|
|
416
|
+
return new Promise((resolve, reject) => {
|
|
417
|
+
const onAbort = () => {
|
|
418
|
+
const idx = this.queue.findIndex((item) => item.OnAbort === onAbort);
|
|
419
|
+
if (idx >= 0) {
|
|
420
|
+
this.queue.splice(idx, 1);
|
|
421
|
+
}
|
|
422
|
+
reject(new RenderWorkerError('Cancelled', 'Render job was cancelled while queued.'));
|
|
423
|
+
};
|
|
424
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
425
|
+
this.queue.push({ Resolve: resolve, Reject: reject, Signal: signal, OnAbort: onAbort });
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
Release() {
|
|
429
|
+
while (this.queue.length > 0) {
|
|
430
|
+
const next = this.queue.shift();
|
|
431
|
+
next.Signal.removeEventListener('abort', next.OnAbort);
|
|
432
|
+
if (!next.Signal.aborted) {
|
|
433
|
+
next.Resolve();
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
this.activeCount = Math.max(0, this.activeCount - 1);
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
function verifyBearerToken(authHeader, expectedToken) {
|
|
441
|
+
if (!authHeader || !authHeader.startsWith('Bearer ')) {
|
|
442
|
+
return false;
|
|
443
|
+
}
|
|
444
|
+
const provided = authHeader.slice('Bearer '.length);
|
|
445
|
+
const expectedHash = createHash('sha256').update(expectedToken, 'utf8').digest();
|
|
446
|
+
const providedHash = createHash('sha256').update(provided, 'utf8').digest();
|
|
447
|
+
return timingSafeEqual(expectedHash, providedHash);
|
|
448
|
+
}
|
|
449
|
+
async function readJsonBody(req, maxBytes) {
|
|
450
|
+
const contentLengthHeader = req.headers['content-length'];
|
|
451
|
+
if (contentLengthHeader) {
|
|
452
|
+
const declared = Number.parseInt(contentLengthHeader, 10);
|
|
453
|
+
if (Number.isFinite(declared) && declared > maxBytes) {
|
|
454
|
+
req.resume();
|
|
455
|
+
throw new RenderWorkerError('BodyTooLarge', `Request body Content-Length (${declared}) exceeds limit (${maxBytes}).`);
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
const chunks = [];
|
|
459
|
+
let totalBytes = 0;
|
|
460
|
+
for await (const chunk of req) {
|
|
461
|
+
const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
462
|
+
totalBytes += buf.byteLength;
|
|
463
|
+
if (totalBytes > maxBytes) {
|
|
464
|
+
throw new RenderWorkerError('BodyTooLarge', `Request body exceeded maximum size of ${maxBytes} bytes.`);
|
|
465
|
+
}
|
|
466
|
+
chunks.push(buf);
|
|
467
|
+
}
|
|
468
|
+
const raw = Buffer.concat(chunks).toString('utf8');
|
|
469
|
+
if (!raw.trim()) {
|
|
470
|
+
throw new RenderWorkerError('InvalidRequest', 'Request body must be non-empty JSON.');
|
|
471
|
+
}
|
|
472
|
+
try {
|
|
473
|
+
return JSON.parse(raw);
|
|
474
|
+
}
|
|
475
|
+
catch {
|
|
476
|
+
throw new RenderWorkerError('InvalidRequest', 'Request body is not valid JSON.');
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
function toRenderWorkerError(error) {
|
|
480
|
+
if (error instanceof RenderWorkerError) {
|
|
481
|
+
return error;
|
|
482
|
+
}
|
|
483
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
484
|
+
return new RenderWorkerError('Internal', message || 'Internal render worker error.');
|
|
485
|
+
}
|
|
486
|
+
function statusCodeForErrorCode(code) {
|
|
487
|
+
switch (code) {
|
|
488
|
+
case 'Unauthorized':
|
|
489
|
+
return 401;
|
|
490
|
+
case 'NotFound':
|
|
491
|
+
return 404;
|
|
492
|
+
case 'BodyTooLarge':
|
|
493
|
+
return 413;
|
|
494
|
+
case 'InvalidRequest':
|
|
495
|
+
case 'InvalidBundle':
|
|
496
|
+
case 'TooManyStills':
|
|
497
|
+
case 'GEOMETRY_MISMATCH':
|
|
498
|
+
return 400;
|
|
499
|
+
case 'LintBlocked':
|
|
500
|
+
return 422;
|
|
501
|
+
case 'Timeout':
|
|
502
|
+
return 504;
|
|
503
|
+
case 'Cancelled':
|
|
504
|
+
return 499;
|
|
505
|
+
case 'DependencyMissing':
|
|
506
|
+
return 503;
|
|
507
|
+
case 'Internal':
|
|
508
|
+
default:
|
|
509
|
+
return 500;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
function sendJson(res, statusCode, payload) {
|
|
513
|
+
const json = JSON.stringify(payload);
|
|
514
|
+
res.writeHead(statusCode, {
|
|
515
|
+
'Content-Type': 'application/json; charset=utf-8',
|
|
516
|
+
'Content-Length': String(Buffer.byteLength(json, 'utf8')),
|
|
517
|
+
'Cache-Control': 'no-store',
|
|
518
|
+
});
|
|
519
|
+
res.end(json);
|
|
520
|
+
}
|
|
521
|
+
function sendErrorJson(res, error) {
|
|
522
|
+
const status = statusCodeForErrorCode(error.Code);
|
|
523
|
+
const body = error.ToBody();
|
|
524
|
+
sendJson(res, status, body);
|
|
525
|
+
}
|
|
526
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,10 +1,48 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/video-studio-render-worker",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "
|
|
5
|
-
"
|
|
3
|
+
"version": "6.2.0-edge.8",
|
|
4
|
+
"description": "Isolated HyperFrames and headless Chromium render worker for MemberJunction Video Studio",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"/dist",
|
|
10
|
+
"/assets"
|
|
11
|
+
],
|
|
12
|
+
"bin": {
|
|
13
|
+
"mj-video-render-worker": "dist/main.js"
|
|
14
|
+
},
|
|
15
|
+
"engines": {
|
|
16
|
+
"node": ">=22"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@hyperframes/core": "0.8.134",
|
|
20
|
+
"@hyperframes/engine": "0.8.134",
|
|
21
|
+
"@hyperframes/lint": "0.8.134",
|
|
22
|
+
"@hyperframes/parsers": "0.8.134",
|
|
23
|
+
"@hyperframes/producer": "0.8.134",
|
|
24
|
+
"@hyperframes/studio-server": "0.8.134",
|
|
25
|
+
"@memberjunction/video-studio-core": "6.2.0-edge.8",
|
|
26
|
+
"hyperframes": "0.8.134"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@types/node": "24.10.11",
|
|
30
|
+
"typescript": "^5.9.3",
|
|
31
|
+
"tsc-alias": "^1.8.10",
|
|
32
|
+
"vitest": "^4.0.18"
|
|
33
|
+
},
|
|
34
|
+
"author": "MemberJunction.com",
|
|
35
|
+
"license": "BUSL-1.1",
|
|
6
36
|
"repository": {
|
|
7
37
|
"type": "git",
|
|
8
|
-
"url": "
|
|
38
|
+
"url": "https://github.com/MemberJunction/MJ"
|
|
39
|
+
},
|
|
40
|
+
"scripts": {
|
|
41
|
+
"build": "tsc && tsc-alias -f",
|
|
42
|
+
"test": "vitest run",
|
|
43
|
+
"test:types": "tsc --noEmit",
|
|
44
|
+
"test:watch": "vitest",
|
|
45
|
+
"test:coverage": "vitest run --coverage",
|
|
46
|
+
"browser:install": "node --input-type=module -e \"import { createRequire } from 'node:module'; import { pathToFileURL } from 'node:url'; const req = createRequire(import.meta.resolve('@hyperframes/engine')); process.argv = ['node', 'puppeteer', 'browsers', 'install', 'chrome-headless-shell']; await import(pathToFileURL(req.resolve('puppeteer/lib/puppeteer/node/cli.js')).href);\""
|
|
9
47
|
}
|
|
10
|
-
}
|
|
48
|
+
}
|