@rendiv/renderer 0.1.0
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/browser.d.ts +9 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +36 -0
- package/dist/browser.js.map +1 -0
- package/dist/cancel-signal.d.ts +6 -0
- package/dist/cancel-signal.d.ts.map +1 -0
- package/dist/cancel-signal.js +8 -0
- package/dist/cancel-signal.js.map +1 -0
- package/dist/get-compositions.d.ts +4 -0
- package/dist/get-compositions.d.ts.map +1 -0
- package/dist/get-compositions.js +57 -0
- package/dist/get-compositions.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/render-frames.d.ts +17 -0
- package/dist/render-frames.d.ts.map +1 -0
- package/dist/render-frames.js +71 -0
- package/dist/render-frames.js.map +1 -0
- package/dist/render-media.d.ts +18 -0
- package/dist/render-media.d.ts.map +1 -0
- package/dist/render-media.js +59 -0
- package/dist/render-media.js.map +1 -0
- package/dist/render-still.d.ts +13 -0
- package/dist/render-still.d.ts.map +1 -0
- package/dist/render-still.js +42 -0
- package/dist/render-still.js.map +1 -0
- package/dist/serve.d.ts +7 -0
- package/dist/serve.d.ts.map +1 -0
- package/dist/serve.js +70 -0
- package/dist/serve.js.map +1 -0
- package/dist/stitch-frames-to-video.d.ts +11 -0
- package/dist/stitch-frames-to-video.d.ts.map +1 -0
- package/dist/stitch-frames-to-video.js +40 -0
- package/dist/stitch-frames-to-video.js.map +1 -0
- package/dist/types.d.ts +10 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +32 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type Browser, type Page } from 'playwright';
|
|
2
|
+
export declare function openBrowser(): Promise<Browser>;
|
|
3
|
+
export declare function closeBrowser(): Promise<void>;
|
|
4
|
+
export declare function ensureBrowser(): Promise<Browser>;
|
|
5
|
+
export declare function openPage(browser: Browser, url: string, viewport: {
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
}): Promise<Page>;
|
|
9
|
+
//# sourceMappingURL=browser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,YAAY,CAAC;AAI/D,wBAAsB,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC,CAcpD;AAED,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAKlD;AAED,wBAAsB,aAAa,IAAI,OAAO,CAAC,OAAO,CAAC,CAEtD;AAED,wBAAsB,QAAQ,CAC5B,OAAO,EAAE,OAAO,EAChB,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC1C,OAAO,CAAC,IAAI,CAAC,CAQf"}
|
package/dist/browser.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { chromium } from 'playwright';
|
|
2
|
+
let browserInstance = null;
|
|
3
|
+
export async function openBrowser() {
|
|
4
|
+
if (browserInstance && browserInstance.isConnected()) {
|
|
5
|
+
return browserInstance;
|
|
6
|
+
}
|
|
7
|
+
browserInstance = await chromium.launch({
|
|
8
|
+
headless: true,
|
|
9
|
+
args: [
|
|
10
|
+
'--disable-web-security',
|
|
11
|
+
'--disable-features=IsolateOrigins',
|
|
12
|
+
'--disable-site-isolation-trials',
|
|
13
|
+
'--no-sandbox',
|
|
14
|
+
],
|
|
15
|
+
});
|
|
16
|
+
return browserInstance;
|
|
17
|
+
}
|
|
18
|
+
export async function closeBrowser() {
|
|
19
|
+
if (browserInstance) {
|
|
20
|
+
await browserInstance.close();
|
|
21
|
+
browserInstance = null;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export async function ensureBrowser() {
|
|
25
|
+
return openBrowser();
|
|
26
|
+
}
|
|
27
|
+
export async function openPage(browser, url, viewport) {
|
|
28
|
+
const context = await browser.newContext({
|
|
29
|
+
viewport,
|
|
30
|
+
deviceScaleFactor: 1,
|
|
31
|
+
});
|
|
32
|
+
const page = await context.newPage();
|
|
33
|
+
await page.goto(url, { waitUntil: 'networkidle' });
|
|
34
|
+
return page;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=browser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAA2B,MAAM,YAAY,CAAC;AAE/D,IAAI,eAAe,GAAmB,IAAI,CAAC;AAE3C,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,IAAI,eAAe,IAAI,eAAe,CAAC,WAAW,EAAE,EAAE,CAAC;QACrD,OAAO,eAAe,CAAC;IACzB,CAAC;IACD,eAAe,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC;QACtC,QAAQ,EAAE,IAAI;QACd,IAAI,EAAE;YACJ,wBAAwB;YACxB,mCAAmC;YACnC,iCAAiC;YACjC,cAAc;SACf;KACF,CAAC,CAAC;IACH,OAAO,eAAe,CAAC;AACzB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,IAAI,eAAe,EAAE,CAAC;QACpB,MAAM,eAAe,CAAC,KAAK,EAAE,CAAC;QAC9B,eAAe,GAAG,IAAI,CAAC;IACzB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,OAAO,WAAW,EAAE,CAAC;AACvB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,OAAgB,EAChB,GAAW,EACX,QAA2C;IAE3C,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC;QACvC,QAAQ;QACR,iBAAiB,EAAE,CAAC;KACrB,CAAC,CAAC;IACH,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;IACrC,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC,CAAC;IACnD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cancel-signal.d.ts","sourceRoot":"","sources":["../src/cancel-signal.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,WAAW,CAAC;IACpB,MAAM,EAAE,MAAM,IAAI,CAAC;CACpB;AAED,wBAAgB,gBAAgB,IAAI,YAAY,CAM/C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cancel-signal.js","sourceRoot":"","sources":["../src/cancel-signal.ts"],"names":[],"mappings":"AAKA,MAAM,UAAU,gBAAgB;IAC9B,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,OAAO;QACL,MAAM,EAAE,UAAU,CAAC,MAAM;QACzB,MAAM,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE;KACjC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { CompositionInfo } from './types.js';
|
|
2
|
+
export declare function getCompositions(serveUrl: string): Promise<CompositionInfo[]>;
|
|
3
|
+
export declare function selectComposition(serveUrl: string, id: string, inputProps?: Record<string, unknown>): Promise<CompositionInfo>;
|
|
4
|
+
//# sourceMappingURL=get-compositions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-compositions.d.ts","sourceRoot":"","sources":["../src/get-compositions.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CA6ClF;AAED,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,MAAM,EACV,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACnC,OAAO,CAAC,eAAe,CAAC,CAa1B"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { openBrowser, openPage } from './browser.js';
|
|
2
|
+
import { startServer } from './serve.js';
|
|
3
|
+
export async function getCompositions(serveUrl) {
|
|
4
|
+
const server = await startServer(serveUrl);
|
|
5
|
+
const browser = await openBrowser();
|
|
6
|
+
try {
|
|
7
|
+
const page = await openPage(browser, server.url, {
|
|
8
|
+
width: 1920,
|
|
9
|
+
height: 1080,
|
|
10
|
+
});
|
|
11
|
+
// Capture console errors for debugging
|
|
12
|
+
const errors = [];
|
|
13
|
+
page.on('console', (msg) => {
|
|
14
|
+
if (msg.type() === 'error') {
|
|
15
|
+
errors.push(msg.text());
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
page.on('pageerror', (err) => {
|
|
19
|
+
errors.push(err.message);
|
|
20
|
+
});
|
|
21
|
+
// Wait for the entry to load
|
|
22
|
+
try {
|
|
23
|
+
await page.waitForFunction(() => window.__RENDIV_LOADED__ === true, {
|
|
24
|
+
timeout: 30000,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
catch (e) {
|
|
28
|
+
const errorDetails = errors.length > 0
|
|
29
|
+
? `\nBrowser errors:\n${errors.join('\n')}`
|
|
30
|
+
: '\nNo browser errors captured.';
|
|
31
|
+
throw new Error(`Timed out waiting for Rendiv bundle to load.${errorDetails}`);
|
|
32
|
+
}
|
|
33
|
+
// Small delay to ensure compositions are registered
|
|
34
|
+
await page.waitForTimeout(100);
|
|
35
|
+
const compositions = await page.evaluate(() => {
|
|
36
|
+
return window.__RENDIV_GET_COMPOSITIONS__();
|
|
37
|
+
});
|
|
38
|
+
await page.close();
|
|
39
|
+
return compositions;
|
|
40
|
+
}
|
|
41
|
+
finally {
|
|
42
|
+
server.close();
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
export async function selectComposition(serveUrl, id, inputProps) {
|
|
46
|
+
const compositions = await getCompositions(serveUrl);
|
|
47
|
+
const comp = compositions.find((c) => c.id === id);
|
|
48
|
+
if (!comp) {
|
|
49
|
+
const available = compositions.map((c) => c.id).join(', ');
|
|
50
|
+
throw new Error(`Composition "${id}" not found. Available: ${available || '(none)'}`);
|
|
51
|
+
}
|
|
52
|
+
if (inputProps) {
|
|
53
|
+
comp.defaultProps = { ...comp.defaultProps, ...inputProps };
|
|
54
|
+
}
|
|
55
|
+
return comp;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=get-compositions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-compositions.js","sourceRoot":"","sources":["../src/get-compositions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAGzC,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,QAAgB;IACpD,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,QAAQ,CAAC,CAAC;IAC3C,MAAM,OAAO,GAAG,MAAM,WAAW,EAAE,CAAC;IAEpC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,GAAG,EAAE;YAC/C,KAAK,EAAE,IAAI;YACX,MAAM,EAAE,IAAI;SACb,CAAC,CAAC;QAEH,uCAAuC;QACvC,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,IAAI,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,GAAG,EAAE,EAAE;YACzB,IAAI,GAAG,CAAC,IAAI,EAAE,KAAK,OAAO,EAAE,CAAC;gBAC3B,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,EAAE,CAAC,WAAW,EAAE,CAAC,GAAG,EAAE,EAAE;YAC3B,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC3B,CAAC,CAAC,CAAC;QAEH,6BAA6B;QAC7B,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,eAAe,CAAC,GAAG,EAAE,CAAE,MAAc,CAAC,iBAAiB,KAAK,IAAI,EAAE;gBAC3E,OAAO,EAAE,KAAK;aACf,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC;gBACpC,CAAC,CAAC,sBAAsB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;gBAC3C,CAAC,CAAC,+BAA+B,CAAC;YACpC,MAAM,IAAI,KAAK,CAAC,+CAA+C,YAAY,EAAE,CAAC,CAAC;QACjF,CAAC;QAED,oDAAoD;QACpD,MAAM,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;QAE/B,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE;YAC5C,OAAQ,MAAc,CAAC,2BAA2B,EAAE,CAAC;QACvD,CAAC,CAAC,CAAC;QAEH,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;QACnB,OAAO,YAAY,CAAC;IACtB,CAAC;YAAS,CAAC;QACT,MAAM,CAAC,KAAK,EAAE,CAAC;IACjB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,QAAgB,EAChB,EAAU,EACV,UAAoC;IAEpC,MAAM,YAAY,GAAG,MAAM,eAAe,CAAC,QAAQ,CAAC,CAAC;IACrD,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC,CAAkB,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IACpE,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,SAAS,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,CAAkB,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5E,MAAM,IAAI,KAAK,CACb,gBAAgB,EAAE,2BAA2B,SAAS,IAAI,QAAQ,EAAE,CACrE,CAAC;IACJ,CAAC;IACD,IAAI,UAAU,EAAE,CAAC;QACf,IAAI,CAAC,YAAY,GAAG,EAAE,GAAG,IAAI,CAAC,YAAY,EAAE,GAAG,UAAU,EAAE,CAAC;IAC9D,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { renderMedia, type RenderMediaOptions } from './render-media.js';
|
|
2
|
+
export { renderFrames, type RenderFramesOptions } from './render-frames.js';
|
|
3
|
+
export { renderStill, type RenderStillOptions } from './render-still.js';
|
|
4
|
+
export { stitchFramesToVideo, type StitchOptions } from './stitch-frames-to-video.js';
|
|
5
|
+
export { getCompositions, selectComposition } from './get-compositions.js';
|
|
6
|
+
export { openBrowser, closeBrowser, ensureBrowser } from './browser.js';
|
|
7
|
+
export { makeCancelSignal, type CancelSignal } from './cancel-signal.js';
|
|
8
|
+
export type { CompositionInfo } from './types.js';
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC5E,OAAO,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,EAAE,mBAAmB,EAAE,KAAK,aAAa,EAAE,MAAM,6BAA6B,CAAC;AACtF,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC3E,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACxE,OAAO,EAAE,gBAAgB,EAAE,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACzE,YAAY,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { renderMedia } from './render-media.js';
|
|
2
|
+
export { renderFrames } from './render-frames.js';
|
|
3
|
+
export { renderStill } from './render-still.js';
|
|
4
|
+
export { stitchFramesToVideo } from './stitch-frames-to-video.js';
|
|
5
|
+
export { getCompositions, selectComposition } from './get-compositions.js';
|
|
6
|
+
export { openBrowser, closeBrowser, ensureBrowser } from './browser.js';
|
|
7
|
+
export { makeCancelSignal } from './cancel-signal.js';
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAA2B,MAAM,mBAAmB,CAAC;AACzE,OAAO,EAAE,YAAY,EAA4B,MAAM,oBAAoB,CAAC;AAC5E,OAAO,EAAE,WAAW,EAA2B,MAAM,mBAAmB,CAAC;AACzE,OAAO,EAAE,mBAAmB,EAAsB,MAAM,6BAA6B,CAAC;AACtF,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC3E,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACxE,OAAO,EAAE,gBAAgB,EAAqB,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { CompositionInfo } from './types.js';
|
|
2
|
+
export interface RenderFramesOptions {
|
|
3
|
+
serveUrl: string;
|
|
4
|
+
composition: CompositionInfo;
|
|
5
|
+
outputDir: string;
|
|
6
|
+
inputProps?: Record<string, unknown>;
|
|
7
|
+
concurrency?: number;
|
|
8
|
+
frameRange?: [number, number];
|
|
9
|
+
onFrameRendered?: (info: {
|
|
10
|
+
frame: number;
|
|
11
|
+
total: number;
|
|
12
|
+
}) => void;
|
|
13
|
+
cancelSignal?: AbortSignal;
|
|
14
|
+
timeoutPerFrame?: number;
|
|
15
|
+
}
|
|
16
|
+
export declare function renderFrames(options: RenderFramesOptions): Promise<void>;
|
|
17
|
+
//# sourceMappingURL=render-frames.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-frames.d.ts","sourceRoot":"","sources":["../src/render-frames.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,eAAe,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACnE,YAAY,CAAC,EAAE,WAAW,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AA4BD,wBAAsB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CA2E9E"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { openBrowser, openPage } from './browser.js';
|
|
4
|
+
import { startServer } from './serve.js';
|
|
5
|
+
async function renderSingleFrame(page, frame, outputDir, timeoutPerFrame) {
|
|
6
|
+
// Set the frame and wait for it to be ready
|
|
7
|
+
await page.evaluate((f) => {
|
|
8
|
+
return window.__RENDIV_SET_FRAME__(f);
|
|
9
|
+
}, frame);
|
|
10
|
+
// Additional check for delay renders
|
|
11
|
+
await page.waitForFunction(() => window.__RENDIV_PENDING_HOLDS__() === 0, { timeout: timeoutPerFrame });
|
|
12
|
+
// Screenshot
|
|
13
|
+
const paddedFrame = String(frame).padStart(6, '0');
|
|
14
|
+
await page.screenshot({
|
|
15
|
+
path: path.join(outputDir, `frame-${paddedFrame}.png`),
|
|
16
|
+
type: 'png',
|
|
17
|
+
animations: 'disabled',
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
export async function renderFrames(options) {
|
|
21
|
+
const { serveUrl, composition, outputDir, inputProps = {}, concurrency = 1, frameRange, onFrameRendered, cancelSignal, timeoutPerFrame = 30000, } = options;
|
|
22
|
+
const [startFrame, endFrame] = frameRange ?? [0, composition.durationInFrames - 1];
|
|
23
|
+
const totalFrames = endFrame - startFrame + 1;
|
|
24
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
25
|
+
const server = await startServer(serveUrl);
|
|
26
|
+
const browser = await openBrowser();
|
|
27
|
+
try {
|
|
28
|
+
// Create page pool
|
|
29
|
+
const pages = [];
|
|
30
|
+
for (let i = 0; i < concurrency; i++) {
|
|
31
|
+
const page = await openPage(browser, server.url, {
|
|
32
|
+
width: composition.width,
|
|
33
|
+
height: composition.height,
|
|
34
|
+
});
|
|
35
|
+
// Wait for entry to load
|
|
36
|
+
await page.waitForFunction(() => window.__RENDIV_LOADED__ === true, {
|
|
37
|
+
timeout: 30000,
|
|
38
|
+
});
|
|
39
|
+
// Set composition and input props
|
|
40
|
+
await page.evaluate(({ id, props }) => {
|
|
41
|
+
window.__RENDIV_SET_INPUT_PROPS__(props);
|
|
42
|
+
window.__RENDIV_SET_COMPOSITION__(id);
|
|
43
|
+
}, { id: composition.id, props: inputProps });
|
|
44
|
+
// Wait for composition to render
|
|
45
|
+
await page.waitForTimeout(100);
|
|
46
|
+
pages.push(page);
|
|
47
|
+
}
|
|
48
|
+
// Render frames using a simple pool
|
|
49
|
+
const frameQueue = Array.from({ length: totalFrames }, (_, i) => startFrame + i);
|
|
50
|
+
let completedFrames = 0;
|
|
51
|
+
const renderNext = async (page) => {
|
|
52
|
+
while (frameQueue.length > 0) {
|
|
53
|
+
if (cancelSignal?.aborted)
|
|
54
|
+
return;
|
|
55
|
+
const frame = frameQueue.shift();
|
|
56
|
+
await renderSingleFrame(page, frame, outputDir, timeoutPerFrame);
|
|
57
|
+
completedFrames++;
|
|
58
|
+
onFrameRendered?.({ frame: completedFrames, total: totalFrames });
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
await Promise.all(pages.map((page) => renderNext(page)));
|
|
62
|
+
// Cleanup pages
|
|
63
|
+
for (const page of pages) {
|
|
64
|
+
await page.close();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
finally {
|
|
68
|
+
server.close();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=render-frames.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-frames.js","sourceRoot":"","sources":["../src/render-frames.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { CompositionInfo } from './types.js';
|
|
2
|
+
export interface RenderMediaOptions {
|
|
3
|
+
composition: CompositionInfo;
|
|
4
|
+
serveUrl: string;
|
|
5
|
+
codec?: 'mp4' | 'webm';
|
|
6
|
+
outputLocation: string;
|
|
7
|
+
inputProps?: Record<string, unknown>;
|
|
8
|
+
concurrency?: number;
|
|
9
|
+
onProgress?: (info: {
|
|
10
|
+
progress: number;
|
|
11
|
+
renderedFrames: number;
|
|
12
|
+
totalFrames: number;
|
|
13
|
+
}) => void;
|
|
14
|
+
frameRange?: [number, number];
|
|
15
|
+
cancelSignal?: AbortSignal;
|
|
16
|
+
}
|
|
17
|
+
export declare function renderMedia(options: RenderMediaOptions): Promise<void>;
|
|
18
|
+
//# sourceMappingURL=render-media.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-media.d.ts","sourceRoot":"","sources":["../src/render-media.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,eAAe,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAC/F,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,YAAY,CAAC,EAAE,WAAW,CAAC;CAC5B;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoE5E"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import os from 'node:os';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import { renderFrames } from './render-frames.js';
|
|
5
|
+
import { stitchFramesToVideo } from './stitch-frames-to-video.js';
|
|
6
|
+
export async function renderMedia(options) {
|
|
7
|
+
const { composition, serveUrl, codec = 'mp4', outputLocation, inputProps, concurrency, onProgress, frameRange, cancelSignal, } = options;
|
|
8
|
+
const totalFrames = frameRange
|
|
9
|
+
? frameRange[1] - frameRange[0] + 1
|
|
10
|
+
: composition.durationInFrames;
|
|
11
|
+
const tmpDir = path.join(os.tmpdir(), `rendiv-frames-${Date.now()}`);
|
|
12
|
+
fs.mkdirSync(tmpDir, { recursive: true });
|
|
13
|
+
// Ensure output directory exists
|
|
14
|
+
const outputDir = path.dirname(outputLocation);
|
|
15
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
16
|
+
try {
|
|
17
|
+
// Step 1: Render frames
|
|
18
|
+
await renderFrames({
|
|
19
|
+
serveUrl,
|
|
20
|
+
composition,
|
|
21
|
+
outputDir: tmpDir,
|
|
22
|
+
inputProps,
|
|
23
|
+
concurrency,
|
|
24
|
+
frameRange,
|
|
25
|
+
onFrameRendered: ({ frame, total }) => {
|
|
26
|
+
onProgress?.({
|
|
27
|
+
progress: (frame / total) * 0.9, // 90% for frame rendering
|
|
28
|
+
renderedFrames: frame,
|
|
29
|
+
totalFrames: total,
|
|
30
|
+
});
|
|
31
|
+
},
|
|
32
|
+
cancelSignal,
|
|
33
|
+
});
|
|
34
|
+
if (cancelSignal?.aborted)
|
|
35
|
+
return;
|
|
36
|
+
// Step 2: Stitch frames to video
|
|
37
|
+
onProgress?.({
|
|
38
|
+
progress: 0.9,
|
|
39
|
+
renderedFrames: totalFrames,
|
|
40
|
+
totalFrames,
|
|
41
|
+
});
|
|
42
|
+
await stitchFramesToVideo({
|
|
43
|
+
framesDir: tmpDir,
|
|
44
|
+
outputPath: outputLocation,
|
|
45
|
+
fps: composition.fps,
|
|
46
|
+
codec,
|
|
47
|
+
});
|
|
48
|
+
onProgress?.({
|
|
49
|
+
progress: 1.0,
|
|
50
|
+
renderedFrames: totalFrames,
|
|
51
|
+
totalFrames,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
finally {
|
|
55
|
+
// Cleanup temp frames
|
|
56
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=render-media.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-media.js","sourceRoot":"","sources":["../src/render-media.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,YAAY,EAA4B,MAAM,oBAAoB,CAAC;AAC5E,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAelE,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAA2B;IAC3D,MAAM,EACJ,WAAW,EACX,QAAQ,EACR,KAAK,GAAG,KAAK,EACb,cAAc,EACd,UAAU,EACV,WAAW,EACX,UAAU,EACV,UAAU,EACV,YAAY,GACb,GAAG,OAAO,CAAC;IAEZ,MAAM,WAAW,GAAG,UAAU;QAC5B,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC;QACnC,CAAC,CAAC,WAAW,CAAC,gBAAgB,CAAC;IAEjC,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,iBAAiB,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACrE,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE1C,iCAAiC;IACjC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IAC/C,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE7C,IAAI,CAAC;QACH,wBAAwB;QACxB,MAAM,YAAY,CAAC;YACjB,QAAQ;YACR,WAAW;YACX,SAAS,EAAE,MAAM;YACjB,UAAU;YACV,WAAW;YACX,UAAU;YACV,eAAe,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE;gBACpC,UAAU,EAAE,CAAC;oBACX,QAAQ,EAAE,CAAC,KAAK,GAAG,KAAK,CAAC,GAAG,GAAG,EAAE,0BAA0B;oBAC3D,cAAc,EAAE,KAAK;oBACrB,WAAW,EAAE,KAAK;iBACnB,CAAC,CAAC;YACL,CAAC;YACD,YAAY;SACb,CAAC,CAAC;QAEH,IAAI,YAAY,EAAE,OAAO;YAAE,OAAO;QAElC,iCAAiC;QACjC,UAAU,EAAE,CAAC;YACX,QAAQ,EAAE,GAAG;YACb,cAAc,EAAE,WAAW;YAC3B,WAAW;SACZ,CAAC,CAAC;QAEH,MAAM,mBAAmB,CAAC;YACxB,SAAS,EAAE,MAAM;YACjB,UAAU,EAAE,cAAc;YAC1B,GAAG,EAAE,WAAW,CAAC,GAAG;YACpB,KAAK;SACN,CAAC,CAAC;QAEH,UAAU,EAAE,CAAC;YACX,QAAQ,EAAE,GAAG;YACb,cAAc,EAAE,WAAW;YAC3B,WAAW;SACZ,CAAC,CAAC;IACL,CAAC;YAAS,CAAC;QACT,sBAAsB;QACtB,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACtD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { CompositionInfo } from './types.js';
|
|
2
|
+
export interface RenderStillOptions {
|
|
3
|
+
serveUrl: string;
|
|
4
|
+
composition: CompositionInfo;
|
|
5
|
+
output: string;
|
|
6
|
+
frame?: number;
|
|
7
|
+
inputProps?: Record<string, unknown>;
|
|
8
|
+
imageFormat?: 'png' | 'jpeg';
|
|
9
|
+
quality?: number;
|
|
10
|
+
timeoutPerFrame?: number;
|
|
11
|
+
}
|
|
12
|
+
export declare function renderStill(options: RenderStillOptions): Promise<void>;
|
|
13
|
+
//# sourceMappingURL=render-still.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-still.d.ts","sourceRoot":"","sources":["../src/render-still.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,eAAe,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,WAAW,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CA4D5E"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { openBrowser, openPage } from './browser.js';
|
|
4
|
+
import { startServer } from './serve.js';
|
|
5
|
+
export async function renderStill(options) {
|
|
6
|
+
const { serveUrl, composition, output, frame = 0, inputProps = {}, imageFormat = 'png', quality, timeoutPerFrame = 30000, } = options;
|
|
7
|
+
// Ensure output directory exists
|
|
8
|
+
const outputDir = path.dirname(output);
|
|
9
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
10
|
+
const server = await startServer(serveUrl);
|
|
11
|
+
const browser = await openBrowser();
|
|
12
|
+
try {
|
|
13
|
+
const page = await openPage(browser, server.url, {
|
|
14
|
+
width: composition.width,
|
|
15
|
+
height: composition.height,
|
|
16
|
+
});
|
|
17
|
+
await page.waitForFunction(() => window.__RENDIV_LOADED__ === true, {
|
|
18
|
+
timeout: 30000,
|
|
19
|
+
});
|
|
20
|
+
await page.evaluate(({ id, props }) => {
|
|
21
|
+
window.__RENDIV_SET_INPUT_PROPS__(props);
|
|
22
|
+
window.__RENDIV_SET_COMPOSITION__(id);
|
|
23
|
+
}, { id: composition.id, props: inputProps });
|
|
24
|
+
await page.waitForTimeout(100);
|
|
25
|
+
// Set frame
|
|
26
|
+
await page.evaluate((f) => {
|
|
27
|
+
return window.__RENDIV_SET_FRAME__(f);
|
|
28
|
+
}, frame);
|
|
29
|
+
await page.waitForFunction(() => window.__RENDIV_PENDING_HOLDS__() === 0, { timeout: timeoutPerFrame });
|
|
30
|
+
await page.screenshot({
|
|
31
|
+
path: output,
|
|
32
|
+
type: imageFormat,
|
|
33
|
+
quality: imageFormat === 'jpeg' ? (quality ?? 80) : undefined,
|
|
34
|
+
animations: 'disabled',
|
|
35
|
+
});
|
|
36
|
+
await page.close();
|
|
37
|
+
}
|
|
38
|
+
finally {
|
|
39
|
+
server.close();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=render-still.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-still.js","sourceRoot":"","sources":["../src/render-still.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAczC,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAA2B;IAC3D,MAAM,EACJ,QAAQ,EACR,WAAW,EACX,MAAM,EACN,KAAK,GAAG,CAAC,EACT,UAAU,GAAG,EAAE,EACf,WAAW,GAAG,KAAK,EACnB,OAAO,EACP,eAAe,GAAG,KAAK,GACxB,GAAG,OAAO,CAAC;IAEZ,iCAAiC;IACjC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACvC,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE7C,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,QAAQ,CAAC,CAAC;IAC3C,MAAM,OAAO,GAAG,MAAM,WAAW,EAAE,CAAC;IAEpC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,GAAG,EAAE;YAC/C,KAAK,EAAE,WAAW,CAAC,KAAK;YACxB,MAAM,EAAE,WAAW,CAAC,MAAM;SAC3B,CAAC,CAAC;QAEH,MAAM,IAAI,CAAC,eAAe,CAAC,GAAG,EAAE,CAAE,MAAc,CAAC,iBAAiB,KAAK,IAAI,EAAE;YAC3E,OAAO,EAAE,KAAK;SACf,CAAC,CAAC;QAEH,MAAM,IAAI,CAAC,QAAQ,CACjB,CAAC,EAAE,EAAE,EAAE,KAAK,EAAkD,EAAE,EAAE;YAC/D,MAAc,CAAC,0BAA0B,CAAC,KAAK,CAAC,CAAC;YACjD,MAAc,CAAC,0BAA0B,CAAC,EAAE,CAAC,CAAC;QACjD,CAAC,EACD,EAAE,EAAE,EAAE,WAAW,CAAC,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,CAC1C,CAAC;QAEF,MAAM,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;QAE/B,YAAY;QACZ,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAS,EAAE,EAAE;YAChC,OAAQ,MAAc,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC;QACjD,CAAC,EAAE,KAAK,CAAC,CAAC;QAEV,MAAM,IAAI,CAAC,eAAe,CACxB,GAAG,EAAE,CAAE,MAAc,CAAC,wBAAwB,EAAE,KAAK,CAAC,EACtD,EAAE,OAAO,EAAE,eAAe,EAAE,CAC7B,CAAC;QAEF,MAAM,IAAI,CAAC,UAAU,CAAC;YACpB,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,WAAW,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS;YAC7D,UAAU,EAAE,UAAU;SACvB,CAAC,CAAC;QAEH,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;YAAS,CAAC;QACT,MAAM,CAAC,KAAK,EAAE,CAAC;IACjB,CAAC;AACH,CAAC"}
|
package/dist/serve.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../src/serve.ts"],"names":[],"mappings":"AA0BA,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,SAAI,GAAG,OAAO,CAAC,WAAW,CAAC,CAoDpF"}
|
package/dist/serve.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import http from 'node:http';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
const MIME_TYPES = {
|
|
5
|
+
'.html': 'text/html',
|
|
6
|
+
'.js': 'application/javascript',
|
|
7
|
+
'.mjs': 'application/javascript',
|
|
8
|
+
'.css': 'text/css',
|
|
9
|
+
'.json': 'application/json',
|
|
10
|
+
'.png': 'image/png',
|
|
11
|
+
'.jpg': 'image/jpeg',
|
|
12
|
+
'.jpeg': 'image/jpeg',
|
|
13
|
+
'.gif': 'image/gif',
|
|
14
|
+
'.svg': 'image/svg+xml',
|
|
15
|
+
'.webp': 'image/webp',
|
|
16
|
+
'.woff': 'font/woff',
|
|
17
|
+
'.woff2': 'font/woff2',
|
|
18
|
+
'.ttf': 'font/ttf',
|
|
19
|
+
'.otf': 'font/otf',
|
|
20
|
+
'.mp4': 'video/mp4',
|
|
21
|
+
'.webm': 'video/webm',
|
|
22
|
+
'.mp3': 'audio/mpeg',
|
|
23
|
+
'.wav': 'audio/wav',
|
|
24
|
+
};
|
|
25
|
+
export function startServer(rootDir, preferredPort = 0) {
|
|
26
|
+
return new Promise((resolve, reject) => {
|
|
27
|
+
const server = http.createServer((req, res) => {
|
|
28
|
+
const urlPath = decodeURIComponent(req.url ?? '/');
|
|
29
|
+
let filePath = path.join(rootDir, urlPath === '/' ? 'index.html' : urlPath);
|
|
30
|
+
// Try with .html extension if no extension
|
|
31
|
+
if (!path.extname(filePath) && !fs.existsSync(filePath)) {
|
|
32
|
+
filePath += '.html';
|
|
33
|
+
}
|
|
34
|
+
if (!fs.existsSync(filePath)) {
|
|
35
|
+
res.writeHead(404);
|
|
36
|
+
res.end('Not Found');
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const stat = fs.statSync(filePath);
|
|
40
|
+
if (stat.isDirectory()) {
|
|
41
|
+
filePath = path.join(filePath, 'index.html');
|
|
42
|
+
if (!fs.existsSync(filePath)) {
|
|
43
|
+
res.writeHead(404);
|
|
44
|
+
res.end('Not Found');
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
49
|
+
const contentType = MIME_TYPES[ext] || 'application/octet-stream';
|
|
50
|
+
res.writeHead(200, {
|
|
51
|
+
'Content-Type': contentType,
|
|
52
|
+
'Access-Control-Allow-Origin': '*',
|
|
53
|
+
'Cache-Control': 'no-cache',
|
|
54
|
+
});
|
|
55
|
+
const stream = fs.createReadStream(filePath);
|
|
56
|
+
stream.pipe(res);
|
|
57
|
+
});
|
|
58
|
+
server.on('error', reject);
|
|
59
|
+
server.listen(preferredPort, '127.0.0.1', () => {
|
|
60
|
+
const address = server.address();
|
|
61
|
+
const port = typeof address === 'object' && address ? address.port : 0;
|
|
62
|
+
resolve({
|
|
63
|
+
url: `http://127.0.0.1:${port}`,
|
|
64
|
+
port,
|
|
65
|
+
close: () => server.close(),
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=serve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serve.js","sourceRoot":"","sources":["../src/serve.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface StitchOptions {
|
|
2
|
+
framesDir: string;
|
|
3
|
+
outputPath: string;
|
|
4
|
+
fps: number;
|
|
5
|
+
codec?: 'mp4' | 'webm';
|
|
6
|
+
crf?: number;
|
|
7
|
+
pixelFormat?: string;
|
|
8
|
+
onProgress?: (progress: number) => void;
|
|
9
|
+
}
|
|
10
|
+
export declare function stitchFramesToVideo(options: StitchOptions): Promise<void>;
|
|
11
|
+
//# sourceMappingURL=stitch-frames-to-video.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stitch-frames-to-video.d.ts","sourceRoot":"","sources":["../src/stitch-frames-to-video.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IACvB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC;AAED,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAuD/E"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
// @ts-ignore - @ffmpeg-installer/ffmpeg has no types
|
|
4
|
+
import ffmpegInstaller from '@ffmpeg-installer/ffmpeg';
|
|
5
|
+
const ffmpegPath = ffmpegInstaller.path;
|
|
6
|
+
export async function stitchFramesToVideo(options) {
|
|
7
|
+
const { framesDir, outputPath, fps, codec = 'mp4', crf = 18, pixelFormat = 'yuv420p', } = options;
|
|
8
|
+
const inputPattern = path.join(framesDir, 'frame-%06d.png');
|
|
9
|
+
const args = [
|
|
10
|
+
'-y',
|
|
11
|
+
'-framerate', String(fps),
|
|
12
|
+
'-i', inputPattern,
|
|
13
|
+
];
|
|
14
|
+
if (codec === 'mp4') {
|
|
15
|
+
args.push('-c:v', 'libx264', '-crf', String(crf), '-pix_fmt', pixelFormat, '-movflags', '+faststart');
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
args.push('-c:v', 'libvpx-vp9', '-crf', String(crf), '-b:v', '0');
|
|
19
|
+
}
|
|
20
|
+
args.push(outputPath);
|
|
21
|
+
return new Promise((resolve, reject) => {
|
|
22
|
+
const proc = spawn(ffmpegPath, args, { stdio: ['ignore', 'pipe', 'pipe'] });
|
|
23
|
+
let stderrData = '';
|
|
24
|
+
proc.stderr.on('data', (data) => {
|
|
25
|
+
stderrData += data.toString();
|
|
26
|
+
});
|
|
27
|
+
proc.on('close', (code) => {
|
|
28
|
+
if (code === 0) {
|
|
29
|
+
resolve();
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
reject(new Error(`FFmpeg exited with code ${code}:\n${stderrData}`));
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
proc.on('error', (err) => {
|
|
36
|
+
reject(new Error(`Failed to spawn FFmpeg: ${err.message}`));
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=stitch-frames-to-video.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stitch-frames-to-video.js","sourceRoot":"","sources":["../src/stitch-frames-to-video.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,qDAAqD;AACrD,OAAO,eAAe,MAAM,0BAA0B,CAAC;AAEvD,MAAM,UAAU,GAAW,eAAe,CAAC,IAAI,CAAC;AAYhD,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,OAAsB;IAC9D,MAAM,EACJ,SAAS,EACT,UAAU,EACV,GAAG,EACH,KAAK,GAAG,KAAK,EACb,GAAG,GAAG,EAAE,EACR,WAAW,GAAG,SAAS,GACxB,GAAG,OAAO,CAAC;IAEZ,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;IAE5D,MAAM,IAAI,GAAa;QACrB,IAAI;QACJ,YAAY,EAAE,MAAM,CAAC,GAAG,CAAC;QACzB,IAAI,EAAE,YAAY;KACnB,CAAC;IAEF,IAAI,KAAK,KAAK,KAAK,EAAE,CAAC;QACpB,IAAI,CAAC,IAAI,CACP,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,EACnB,UAAU,EAAE,WAAW,EACvB,WAAW,EAAE,YAAY,CAC1B,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,IAAI,CAAC,IAAI,CACP,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,EACnB,MAAM,EAAE,GAAG,CACZ,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAEtB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,IAAI,GAAG,KAAK,CAAC,UAAU,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;QAE5E,IAAI,UAAU,GAAG,EAAE,CAAC;QACpB,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE;YACtC,UAAU,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAChC,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YACxB,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;gBACf,OAAO,EAAE,CAAC;YACZ,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,IAAI,KAAK,CAAC,2BAA2B,IAAI,MAAM,UAAU,EAAE,CAAC,CAAC,CAAC;YACvE,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YACvB,MAAM,CAAC,IAAI,KAAK,CAAC,2BAA2B,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QAC9D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,gBAAgB,EAAE,MAAM,CAAC;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC;CAC/B"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@rendiv/renderer",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"@ffmpeg-installer/ffmpeg": "^1.1.0",
|
|
19
|
+
"playwright": "^1.49.0"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@types/node": "^22.0.0",
|
|
23
|
+
"typescript": "^5.7.0",
|
|
24
|
+
"@rendiv/tsconfig": "0.0.0"
|
|
25
|
+
},
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "tsc",
|
|
28
|
+
"dev": "tsc --watch",
|
|
29
|
+
"typecheck": "tsc --noEmit",
|
|
30
|
+
"clean": "rm -rf dist"
|
|
31
|
+
}
|
|
32
|
+
}
|