@clipkit/renderer 1.0.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/LICENSE +201 -0
- package/README.md +71 -0
- package/dist/.tmp-harness.js +2011 -0
- package/dist/harness/embedded.d.ts +2 -0
- package/dist/harness/embedded.d.ts.map +1 -0
- package/dist/harness/embedded.js +2015 -0
- package/dist/harness/embedded.js.map +1 -0
- package/dist/harness/harness.d.ts +23 -0
- package/dist/harness/harness.d.ts.map +1 -0
- package/dist/harness/harness.js +93 -0
- package/dist/harness/harness.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/render.d.ts +14 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/render.js +148 -0
- package/dist/render.js.map +1 -0
- package/dist/still.d.ts +21 -0
- package/dist/still.d.ts.map +1 -0
- package/dist/still.js +119 -0
- package/dist/still.js.map +1 -0
- package/dist/types.d.ts +40 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +56 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embedded.js","sourceRoot":"","sources":["../../src/harness/embedded.ts"],"names":[],"mappings":"AAAA,wCAAwC;AACxC,iEAAiE;AAEjE,MAAM,CAAC,MAAM,UAAU,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA29DzB,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type RenderResolution } from '@clipkit/runtime';
|
|
2
|
+
import type { Source } from '@clipkit/protocol';
|
|
3
|
+
interface HarnessOptions {
|
|
4
|
+
backend?: 'auto' | 'webgpu' | 'webgl2';
|
|
5
|
+
resolution?: RenderResolution;
|
|
6
|
+
bitrate?: number;
|
|
7
|
+
}
|
|
8
|
+
interface StillOptions {
|
|
9
|
+
time?: number;
|
|
10
|
+
backend?: 'auto' | 'webgpu' | 'webgl2';
|
|
11
|
+
}
|
|
12
|
+
declare global {
|
|
13
|
+
interface Window {
|
|
14
|
+
__clipkitReportProgress?: (frame: number, total: number) => Promise<void>;
|
|
15
|
+
__clipkitReportError?: (message: string) => Promise<void>;
|
|
16
|
+
__clipkitReportResult?: (base64Mp4: string) => Promise<void>;
|
|
17
|
+
__clipkitStillReady?: () => Promise<void>;
|
|
18
|
+
runHarness: (source: Source, options?: HarnessOptions) => Promise<void>;
|
|
19
|
+
renderStill: (source: Source, options?: StillOptions) => Promise<void>;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export {};
|
|
23
|
+
//# sourceMappingURL=harness.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"harness.d.ts","sourceRoot":"","sources":["../../src/harness/harness.ts"],"names":[],"mappings":"AAeA,OAAO,EAAkB,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAEhD,UAAU,cAAc;IACtB,OAAO,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACvC,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,YAAY;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAC;CACxC;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,uBAAuB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;QAC1E,oBAAoB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;QAC1D,qBAAqB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;QAC7D,mBAAmB,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;QAC1C,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;QACxE,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;KACxE;CACF"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// Browser-side harness — runs inside the headless Chrome that Playwright
|
|
2
|
+
// drives. Bundled into a single self-contained script at build time
|
|
3
|
+
// (scripts/build-harness.mjs) and embedded as a string in ./embedded.ts,
|
|
4
|
+
// which the renderer injects into the page via addScriptTag.
|
|
5
|
+
//
|
|
6
|
+
// It talks to Node through Playwright-exposed functions (wired in ../render.ts
|
|
7
|
+
// and ../still.ts):
|
|
8
|
+
// __clipkitReportProgress(frame, total) — optional, per-frame
|
|
9
|
+
// __clipkitReportError(message) — fatal
|
|
10
|
+
// __clipkitReportResult(base64Mp4) — runHarness success
|
|
11
|
+
// __clipkitStillReady() — renderStill: canvas is ready to screenshot
|
|
12
|
+
//
|
|
13
|
+
// All it does is instantiate @clipkit/runtime and render the Source. The engine
|
|
14
|
+
// is the runtime; this is glue.
|
|
15
|
+
import { ClipkitRuntime } from '@clipkit/runtime';
|
|
16
|
+
// Render the full composition to an MP4 via the runtime's WebCodecs exporter.
|
|
17
|
+
window.runHarness = async function runHarness(source, options = {}) {
|
|
18
|
+
try {
|
|
19
|
+
const width = source.width ?? 1920;
|
|
20
|
+
const height = source.height ?? 1080;
|
|
21
|
+
const canvas = document.createElement('canvas');
|
|
22
|
+
canvas.width = width;
|
|
23
|
+
canvas.height = height;
|
|
24
|
+
canvas.style.cssText = 'position:fixed; top:0; left:0;';
|
|
25
|
+
document.body.appendChild(canvas);
|
|
26
|
+
const runtime = new ClipkitRuntime(canvas);
|
|
27
|
+
const ok = await runtime.init({ backend: options.backend ?? 'auto' });
|
|
28
|
+
if (!ok) {
|
|
29
|
+
throw new Error(`runtime.init() failed (backend preference: ${options.backend ?? 'auto'}). ` +
|
|
30
|
+
`Try forcing backend 'webgl2'.`);
|
|
31
|
+
}
|
|
32
|
+
runtime.load(source);
|
|
33
|
+
await runtime.preload();
|
|
34
|
+
const fps = source.frame_rate ?? 30;
|
|
35
|
+
const duration = typeof source.duration === 'number' ? source.duration : 10;
|
|
36
|
+
const totalFrames = Math.max(1, Math.ceil(duration * fps));
|
|
37
|
+
const blob = await runtime.export({
|
|
38
|
+
framerate: fps,
|
|
39
|
+
renderResolution: options.resolution,
|
|
40
|
+
...(options.bitrate ? { bitrate: options.bitrate } : {}),
|
|
41
|
+
onProgress: (progress01) => {
|
|
42
|
+
const frame = Math.round(progress01 * totalFrames);
|
|
43
|
+
window.__clipkitReportProgress?.(frame, totalFrames).catch(() => { });
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
const base64 = arrayBufferToBase64(await blob.arrayBuffer());
|
|
47
|
+
await window.__clipkitReportResult?.(base64);
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
const message = err instanceof Error ? (err.stack ?? err.message) : String(err);
|
|
51
|
+
await window.__clipkitReportError?.(message);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
// Render one frame at `time` and leave it on a full-size canvas, then signal
|
|
55
|
+
// readiness so Node can screenshot it (works regardless of preserveDrawingBuffer).
|
|
56
|
+
window.renderStill = async function renderStill(source, options = {}) {
|
|
57
|
+
try {
|
|
58
|
+
const width = source.width ?? 1920;
|
|
59
|
+
const height = source.height ?? 1080;
|
|
60
|
+
const canvas = document.createElement('canvas');
|
|
61
|
+
canvas.id = '__clipkit_still';
|
|
62
|
+
canvas.width = width;
|
|
63
|
+
canvas.height = height;
|
|
64
|
+
canvas.style.cssText = `position:fixed; top:0; left:0; width:${width}px; height:${height}px;`;
|
|
65
|
+
document.body.appendChild(canvas);
|
|
66
|
+
const runtime = new ClipkitRuntime(canvas);
|
|
67
|
+
const ok = await runtime.init({ backend: options.backend ?? 'auto' });
|
|
68
|
+
if (!ok) {
|
|
69
|
+
throw new Error(`runtime.init() failed (backend preference: ${options.backend ?? 'auto'}).`);
|
|
70
|
+
}
|
|
71
|
+
runtime.load(source);
|
|
72
|
+
await runtime.preload();
|
|
73
|
+
await runtime.renderAsync(source, options.time ?? 0);
|
|
74
|
+
await runtime.gpuFinish();
|
|
75
|
+
await window.__clipkitStillReady?.();
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
const message = err instanceof Error ? (err.stack ?? err.message) : String(err);
|
|
79
|
+
await window.__clipkitReportError?.(message);
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
// btoa overflows on multi-MB buffers; chunk it.
|
|
83
|
+
function arrayBufferToBase64(buffer) {
|
|
84
|
+
const bytes = new Uint8Array(buffer);
|
|
85
|
+
const CHUNK = 0x8000; // 32 KB
|
|
86
|
+
let out = '';
|
|
87
|
+
for (let i = 0; i < bytes.length; i += CHUNK) {
|
|
88
|
+
const chunk = bytes.subarray(i, Math.min(i + CHUNK, bytes.length));
|
|
89
|
+
out += String.fromCharCode.apply(null, Array.from(chunk));
|
|
90
|
+
}
|
|
91
|
+
return btoa(out);
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=harness.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"harness.js","sourceRoot":"","sources":["../../src/harness/harness.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAChF,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/render.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { RenderOptions, RenderResult } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Render a ClipKit `Source` to an MP4 buffer using local headless Chrome.
|
|
4
|
+
*
|
|
5
|
+
* Requires Google Chrome (or Chromium) installed on the machine.
|
|
6
|
+
*
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { render } from '@clipkit/renderer';
|
|
9
|
+
* const { buffer } = await render({ source });
|
|
10
|
+
* await writeFile('out.mp4', buffer);
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
export declare function render(options: RenderOptions): Promise<RenderResult>;
|
|
14
|
+
//# sourceMappingURL=render.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AA6B9D;;;;;;;;;;GAUG;AACH,wBAAsB,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,CA8G1E"}
|
package/dist/render.js
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
// @clipkit/renderer — render a ClipKit Source to MP4 on your own machine.
|
|
2
|
+
//
|
|
3
|
+
// Drives Playwright + a bundled in-page harness: launches headless Chrome,
|
|
4
|
+
// loads @clipkit/runtime, renders the composition, and returns the runtime's
|
|
5
|
+
// own WebCodecs MP4. No server, no ffmpeg, no GPU-container recipe — just
|
|
6
|
+
// JSON → MP4, locally. (The hosted/cloud rendering pipeline is separate.)
|
|
7
|
+
import { createServer } from 'node:http';
|
|
8
|
+
import { chromium } from 'playwright';
|
|
9
|
+
import { HARNESS_JS } from './harness/embedded.js';
|
|
10
|
+
const DEFAULT_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes
|
|
11
|
+
const HARNESS_HTML = `<!doctype html><html><body></body></html>`;
|
|
12
|
+
// WebCodecs' VideoEncoder (used by the runtime's MP4 exporter) is gated to
|
|
13
|
+
// secure contexts. about:blank isn't one; http://127.0.0.1 is. So we serve the
|
|
14
|
+
// harness page from a throwaway localhost server for the render's lifetime.
|
|
15
|
+
async function startHarnessServer() {
|
|
16
|
+
const server = createServer((_req, res) => {
|
|
17
|
+
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
18
|
+
res.end(HARNESS_HTML);
|
|
19
|
+
});
|
|
20
|
+
await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve));
|
|
21
|
+
const port = server.address().port;
|
|
22
|
+
return {
|
|
23
|
+
url: `http://127.0.0.1:${port}/`,
|
|
24
|
+
close: () => new Promise((resolve) => server.close(() => resolve())),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
// On GPU-less Linux / CI, pin ANGLE's SwiftShader software path so WebGL2 works
|
|
28
|
+
// headless. On macOS / Windows, plain headless uses the system GPU. We always
|
|
29
|
+
// use *system* Chrome (channel: 'chrome') because Playwright's bundled chromium
|
|
30
|
+
// is the headless_shell variant and ships without WebCodecs.
|
|
31
|
+
const ON_LINUX = process.platform === 'linux';
|
|
32
|
+
const SOFTWARE_GL = ['--enable-unsafe-webgpu', '--use-angle=swiftshader'];
|
|
33
|
+
const BASE_FLAGS = ['--no-sandbox', '--disable-dev-shm-usage'];
|
|
34
|
+
/**
|
|
35
|
+
* Render a ClipKit `Source` to an MP4 buffer using local headless Chrome.
|
|
36
|
+
*
|
|
37
|
+
* Requires Google Chrome (or Chromium) installed on the machine.
|
|
38
|
+
*
|
|
39
|
+
* ```ts
|
|
40
|
+
* import { render } from '@clipkit/renderer';
|
|
41
|
+
* const { buffer } = await render({ source });
|
|
42
|
+
* await writeFile('out.mp4', buffer);
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export async function render(options) {
|
|
46
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
47
|
+
const width = options.source.width ?? 1920;
|
|
48
|
+
const height = options.source.height ?? 1080;
|
|
49
|
+
const launchOpts = ON_LINUX
|
|
50
|
+
? {
|
|
51
|
+
// New-headless is the full browser (needed for WebCodecs); pass it
|
|
52
|
+
// explicitly with headless:false so Playwright doesn't add legacy --headless.
|
|
53
|
+
headless: false,
|
|
54
|
+
args: options.showBrowser
|
|
55
|
+
? [...SOFTWARE_GL, ...BASE_FLAGS]
|
|
56
|
+
: [...SOFTWARE_GL, ...BASE_FLAGS, '--headless=new'],
|
|
57
|
+
channel: 'chrome',
|
|
58
|
+
}
|
|
59
|
+
: {
|
|
60
|
+
headless: !options.showBrowser,
|
|
61
|
+
args: BASE_FLAGS,
|
|
62
|
+
channel: 'chrome',
|
|
63
|
+
};
|
|
64
|
+
let browser = null;
|
|
65
|
+
let harnessServer = null;
|
|
66
|
+
try {
|
|
67
|
+
harnessServer = await startHarnessServer();
|
|
68
|
+
browser = await chromium.launch(launchOpts);
|
|
69
|
+
const context = await browser.newContext({ viewport: { width, height } });
|
|
70
|
+
const page = await context.newPage();
|
|
71
|
+
if (options.onLog) {
|
|
72
|
+
page.on('console', (m) => options.onLog(`[page:${m.type()}] ${m.text()}`));
|
|
73
|
+
}
|
|
74
|
+
let resolveResult;
|
|
75
|
+
let rejectResult;
|
|
76
|
+
const resultPromise = new Promise((resolve, reject) => {
|
|
77
|
+
resolveResult = resolve;
|
|
78
|
+
rejectResult = reject;
|
|
79
|
+
});
|
|
80
|
+
await page.exposeFunction('__clipkitReportProgress', (frame, total) => {
|
|
81
|
+
options.onProgress?.(frame, total);
|
|
82
|
+
});
|
|
83
|
+
await page.exposeFunction('__clipkitReportError', (message) => {
|
|
84
|
+
rejectResult(new Error(`render harness error:\n${message}`));
|
|
85
|
+
});
|
|
86
|
+
await page.exposeFunction('__clipkitReportResult', (base64Mp4) => {
|
|
87
|
+
try {
|
|
88
|
+
resolveResult(Buffer.from(base64Mp4, 'base64'));
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
rejectResult(err instanceof Error ? err : new Error(String(err)));
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
page.on('pageerror', (err) => rejectResult(new Error(`page error: ${err.message}`)));
|
|
95
|
+
page.on('crash', () => rejectResult(new Error('chromium tab crashed during render')));
|
|
96
|
+
// localhost = secure context, so WebCodecs is available.
|
|
97
|
+
await page.goto(harnessServer.url, { waitUntil: 'domcontentloaded' });
|
|
98
|
+
await page.addScriptTag({ content: HARNESS_JS });
|
|
99
|
+
page
|
|
100
|
+
.evaluate(([sourceJson, backend, resolution, bitrate]) => {
|
|
101
|
+
const src = JSON.parse(sourceJson);
|
|
102
|
+
const w = window;
|
|
103
|
+
const opts = { backend };
|
|
104
|
+
if (resolution)
|
|
105
|
+
opts.resolution = resolution;
|
|
106
|
+
if (bitrate)
|
|
107
|
+
opts.bitrate = bitrate;
|
|
108
|
+
return w.runHarness(src, opts);
|
|
109
|
+
}, [
|
|
110
|
+
JSON.stringify(options.source),
|
|
111
|
+
options.backend ?? 'auto',
|
|
112
|
+
options.resolution ?? '',
|
|
113
|
+
options.bitrate ?? 0,
|
|
114
|
+
])
|
|
115
|
+
.catch((err) => {
|
|
116
|
+
// Browser close during a long render races with page.evaluate; the real
|
|
117
|
+
// error is already on resultPromise. Swallow the cascade.
|
|
118
|
+
void err;
|
|
119
|
+
});
|
|
120
|
+
let timer;
|
|
121
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
122
|
+
timer = setTimeout(() => reject(new Error(`render timed out after ${timeoutMs} ms`)), timeoutMs);
|
|
123
|
+
});
|
|
124
|
+
try {
|
|
125
|
+
const buffer = await Promise.race([resultPromise, timeoutPromise]);
|
|
126
|
+
return {
|
|
127
|
+
buffer,
|
|
128
|
+
ext: 'mp4',
|
|
129
|
+
mime: 'video/mp4',
|
|
130
|
+
width,
|
|
131
|
+
height,
|
|
132
|
+
durationSec: typeof options.source.duration === 'number' ? options.source.duration : 0,
|
|
133
|
+
frameRate: options.source.frame_rate ?? 30,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
finally {
|
|
137
|
+
if (timer)
|
|
138
|
+
clearTimeout(timer);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
finally {
|
|
142
|
+
if (browser)
|
|
143
|
+
await browser.close().catch(() => { });
|
|
144
|
+
if (harnessServer)
|
|
145
|
+
await harnessServer.close().catch(() => { });
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=render.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"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"}
|
package/dist/still.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Source } from '@clipkit/protocol';
|
|
2
|
+
export interface StillOptions {
|
|
3
|
+
/** The Source to render. */
|
|
4
|
+
source: Source;
|
|
5
|
+
/** Composition time in seconds to capture. Default 0. */
|
|
6
|
+
time?: number;
|
|
7
|
+
/** Runtime backend preference. Default 'auto'. */
|
|
8
|
+
backend?: 'auto' | 'webgpu' | 'webgl2';
|
|
9
|
+
/**
|
|
10
|
+
* Directory served at the harness origin's root, so the Source can reference
|
|
11
|
+
* sidecar assets (e.g. local fonts) by absolute path. Path traversal 404s.
|
|
12
|
+
*/
|
|
13
|
+
staticRoot?: string;
|
|
14
|
+
/** Hard timeout in milliseconds. Default 60s. */
|
|
15
|
+
timeoutMs?: number;
|
|
16
|
+
/** Show the Chrome window instead of headless (debugging). */
|
|
17
|
+
showBrowser?: boolean;
|
|
18
|
+
}
|
|
19
|
+
/** Render one frame of `source` at `time` seconds; resolves to PNG bytes. */
|
|
20
|
+
export declare function renderStill(options: StillOptions): Promise<Buffer>;
|
|
21
|
+
//# sourceMappingURL=still.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"still.d.ts","sourceRoot":"","sources":["../src/still.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAwBhD,MAAM,WAAW,YAAY;IAC3B,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,yDAAyD;IACzD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kDAAkD;IAClD,OAAO,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACvC;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8DAA8D;IAC9D,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAiCD,6EAA6E;AAC7E,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAwExE"}
|
package/dist/still.js
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
// Single-frame render — returns a PNG Buffer of the composition at one time.
|
|
2
|
+
// Uses a Playwright element screenshot of the harness canvas (no WebCodecs, so
|
|
3
|
+
// it works regardless of preserveDrawingBuffer).
|
|
4
|
+
import { createServer } from 'node:http';
|
|
5
|
+
import { createReadStream, existsSync, statSync } from 'node:fs';
|
|
6
|
+
import { extname, join, normalize, resolve, sep } from 'node:path';
|
|
7
|
+
import { chromium } from 'playwright';
|
|
8
|
+
import { HARNESS_JS } from './harness/embedded.js';
|
|
9
|
+
const DEFAULT_TIMEOUT_MS = 60 * 1000;
|
|
10
|
+
const HARNESS_HTML = `<!doctype html><html><body></body></html>`;
|
|
11
|
+
const ON_LINUX = process.platform === 'linux';
|
|
12
|
+
const SOFTWARE_GL = ['--enable-unsafe-webgpu', '--use-angle=swiftshader'];
|
|
13
|
+
const BASE_FLAGS = ['--no-sandbox', '--disable-dev-shm-usage'];
|
|
14
|
+
const CHROMIUM_FLAGS = ON_LINUX ? [...SOFTWARE_GL, ...BASE_FLAGS] : BASE_FLAGS;
|
|
15
|
+
const MIME = {
|
|
16
|
+
'.woff2': 'font/woff2',
|
|
17
|
+
'.woff': 'font/woff',
|
|
18
|
+
'.ttf': 'font/ttf',
|
|
19
|
+
'.otf': 'font/otf',
|
|
20
|
+
'.png': 'image/png',
|
|
21
|
+
'.jpg': 'image/jpeg',
|
|
22
|
+
'.jpeg': 'image/jpeg',
|
|
23
|
+
'.webp': 'image/webp',
|
|
24
|
+
'.svg': 'image/svg+xml',
|
|
25
|
+
'.json': 'application/json',
|
|
26
|
+
};
|
|
27
|
+
async function startStillServer(staticRoot) {
|
|
28
|
+
const root = staticRoot ? resolve(staticRoot) : null;
|
|
29
|
+
const server = createServer((req, res) => {
|
|
30
|
+
const urlPath = decodeURIComponent((req.url ?? '/').split('?')[0]);
|
|
31
|
+
if (urlPath === '/' || !root) {
|
|
32
|
+
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
33
|
+
res.end(HARNESS_HTML);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const filePath = normalize(join(root, urlPath));
|
|
37
|
+
if (!filePath.startsWith(root + sep) || !existsSync(filePath) || !statSync(filePath).isFile()) {
|
|
38
|
+
res.writeHead(404);
|
|
39
|
+
res.end();
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
res.writeHead(200, {
|
|
43
|
+
'Content-Type': MIME[extname(filePath).toLowerCase()] ?? 'application/octet-stream',
|
|
44
|
+
'Access-Control-Allow-Origin': '*',
|
|
45
|
+
});
|
|
46
|
+
createReadStream(filePath).pipe(res);
|
|
47
|
+
});
|
|
48
|
+
await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve));
|
|
49
|
+
const port = server.address().port;
|
|
50
|
+
return {
|
|
51
|
+
url: `http://127.0.0.1:${port}/`,
|
|
52
|
+
close: () => new Promise((resolve) => server.close(() => resolve())),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
/** Render one frame of `source` at `time` seconds; resolves to PNG bytes. */
|
|
56
|
+
export async function renderStill(options) {
|
|
57
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
58
|
+
const launchOpts = {
|
|
59
|
+
headless: !options.showBrowser,
|
|
60
|
+
args: CHROMIUM_FLAGS,
|
|
61
|
+
channel: 'chrome',
|
|
62
|
+
};
|
|
63
|
+
let browser = null;
|
|
64
|
+
let server = null;
|
|
65
|
+
try {
|
|
66
|
+
server = await startStillServer(options.staticRoot);
|
|
67
|
+
browser = await chromium.launch(launchOpts);
|
|
68
|
+
const context = await browser.newContext({
|
|
69
|
+
viewport: {
|
|
70
|
+
width: options.source.width ?? 1920,
|
|
71
|
+
height: options.source.height ?? 1080,
|
|
72
|
+
},
|
|
73
|
+
deviceScaleFactor: 1,
|
|
74
|
+
});
|
|
75
|
+
const page = await context.newPage();
|
|
76
|
+
let resolveReady;
|
|
77
|
+
let rejectReady;
|
|
78
|
+
const readyPromise = new Promise((resolve, reject) => {
|
|
79
|
+
resolveReady = resolve;
|
|
80
|
+
rejectReady = reject;
|
|
81
|
+
});
|
|
82
|
+
await page.exposeFunction('__clipkitStillReady', () => resolveReady());
|
|
83
|
+
await page.exposeFunction('__clipkitReportError', (message) => {
|
|
84
|
+
rejectReady(new Error(`render harness error:\n${message}`));
|
|
85
|
+
});
|
|
86
|
+
page.on('pageerror', (err) => rejectReady(new Error(`page error: ${err.message}`)));
|
|
87
|
+
page.on('crash', () => rejectReady(new Error('chromium tab crashed during still render')));
|
|
88
|
+
await page.goto(server.url, { waitUntil: 'domcontentloaded' });
|
|
89
|
+
await page.addScriptTag({ content: HARNESS_JS });
|
|
90
|
+
page
|
|
91
|
+
.evaluate(([sourceJson, time, backend]) => {
|
|
92
|
+
const src = JSON.parse(sourceJson);
|
|
93
|
+
return window.renderStill(src, { time, backend });
|
|
94
|
+
}, [JSON.stringify(options.source), options.time ?? 0, options.backend ?? 'auto'])
|
|
95
|
+
.catch(() => {
|
|
96
|
+
// Errors surface via __clipkitReportError / pageerror; the evaluate
|
|
97
|
+
// rejection here is the browser-close race.
|
|
98
|
+
});
|
|
99
|
+
let timer;
|
|
100
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
101
|
+
timer = setTimeout(() => reject(new Error(`still render timed out after ${timeoutMs} ms`)), timeoutMs);
|
|
102
|
+
});
|
|
103
|
+
try {
|
|
104
|
+
await Promise.race([readyPromise, timeoutPromise]);
|
|
105
|
+
}
|
|
106
|
+
finally {
|
|
107
|
+
if (timer)
|
|
108
|
+
clearTimeout(timer);
|
|
109
|
+
}
|
|
110
|
+
return await page.locator('#__clipkit_still').screenshot({ type: 'png' });
|
|
111
|
+
}
|
|
112
|
+
finally {
|
|
113
|
+
if (browser)
|
|
114
|
+
await browser.close().catch(() => { });
|
|
115
|
+
if (server)
|
|
116
|
+
await server.close().catch(() => { });
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=still.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"still.js","sourceRoot":"","sources":["../src/still.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { Source } from '@clipkit/protocol';
|
|
2
|
+
export type RenderResolution = 'source' | '480p' | '720p' | '1080p' | '1440p' | '4k';
|
|
3
|
+
export interface RenderOptions {
|
|
4
|
+
/** The ClipKit Source to render. */
|
|
5
|
+
source: Source;
|
|
6
|
+
/**
|
|
7
|
+
* Runtime backend. Default 'auto' lets the runtime negotiate
|
|
8
|
+
* WebGPU → WebGL2. Force 'webgl2' for the most portable software path.
|
|
9
|
+
*/
|
|
10
|
+
backend?: 'auto' | 'webgpu' | 'webgl2';
|
|
11
|
+
/**
|
|
12
|
+
* Output resolution. Default 'source' (no scaling — matches the Source's
|
|
13
|
+
* dimensions). Named tiers anchor on height and keep the Source's aspect.
|
|
14
|
+
*/
|
|
15
|
+
resolution?: RenderResolution;
|
|
16
|
+
/** Override the auto-selected video bitrate (bits/second). */
|
|
17
|
+
bitrate?: number;
|
|
18
|
+
/** Called per frame during encode. `frame` is the latest; `total` the expected count. */
|
|
19
|
+
onProgress?: (frame: number, total: number) => void;
|
|
20
|
+
/** Called with each in-page console line (debugging). */
|
|
21
|
+
onLog?: (line: string) => void;
|
|
22
|
+
/** Hard timeout in ms. The render fails if no result arrives in time. Default 5 min. */
|
|
23
|
+
timeoutMs?: number;
|
|
24
|
+
/** Show the Chrome window instead of running headless (debugging). */
|
|
25
|
+
showBrowser?: boolean;
|
|
26
|
+
}
|
|
27
|
+
export interface RenderResult {
|
|
28
|
+
/** Encoded MP4 (H.264) bytes. */
|
|
29
|
+
buffer: Buffer;
|
|
30
|
+
/** Output file extension — always 'mp4'. */
|
|
31
|
+
ext: 'mp4';
|
|
32
|
+
/** Content-type. */
|
|
33
|
+
mime: 'video/mp4';
|
|
34
|
+
/** Composition width / height / duration / fps (echoed from the Source). */
|
|
35
|
+
width: number;
|
|
36
|
+
height: number;
|
|
37
|
+
durationSec: number;
|
|
38
|
+
frameRate: number;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAEhD,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,IAAI,CAAC;AAErF,MAAM,WAAW,aAAa;IAC5B,oCAAoC;IACpC,MAAM,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACvC;;;OAGG;IACH,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,8DAA8D;IAC9D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yFAAyF;IACzF,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,yDAAyD;IACzD,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,wFAAwF;IACxF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sEAAsE;IACtE,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,iCAAiC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,4CAA4C;IAC5C,GAAG,EAAE,KAAK,CAAC;IACX,oBAAoB;IACpB,IAAI,EAAE,WAAW,CAAC;IAClB,4EAA4E;IAC5E,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,sCAAsC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@clipkit/renderer",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Render a ClipKit Source to MP4 locally — headless Chrome + WebCodecs, driven by Playwright. The Node-side renderer for @clipkit/runtime.",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"README.md",
|
|
18
|
+
"LICENSE"
|
|
19
|
+
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build:harness": "node ./scripts/build-harness.mjs",
|
|
22
|
+
"prebuild": "npm run build:harness",
|
|
23
|
+
"predev": "npm run build:harness",
|
|
24
|
+
"pretypecheck": "npm run build:harness",
|
|
25
|
+
"build": "tsc",
|
|
26
|
+
"dev": "tsc --watch",
|
|
27
|
+
"typecheck": "tsc --noEmit",
|
|
28
|
+
"clean": "rm -rf dist src/harness/embedded.ts"
|
|
29
|
+
},
|
|
30
|
+
"keywords": [
|
|
31
|
+
"clipkit",
|
|
32
|
+
"video",
|
|
33
|
+
"renderer",
|
|
34
|
+
"mp4",
|
|
35
|
+
"webcodecs",
|
|
36
|
+
"headless",
|
|
37
|
+
"playwright"
|
|
38
|
+
],
|
|
39
|
+
"repository": {
|
|
40
|
+
"type": "git",
|
|
41
|
+
"url": "git+https://github.com/clipkit-video/clipkit.git",
|
|
42
|
+
"directory": "packages/renderer"
|
|
43
|
+
},
|
|
44
|
+
"homepage": "https://clipkit.dev",
|
|
45
|
+
"bugs": "https://github.com/clipkit-video/clipkit/issues",
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"@clipkit/protocol": "^1.0.0",
|
|
48
|
+
"@clipkit/runtime": "^1.0.0",
|
|
49
|
+
"playwright": "^1.49.0"
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@types/node": "^22.0.0",
|
|
53
|
+
"esbuild": "^0.24.0",
|
|
54
|
+
"typescript": "^5.7.3"
|
|
55
|
+
}
|
|
56
|
+
}
|