@twick/render-server 0.15.0 → 0.15.2

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/package.json.bak CHANGED
@@ -1,14 +1,22 @@
1
1
  {
2
2
  "name": "@twick/render-server",
3
- "version": "0.15.0",
3
+ "version": "0.15.2",
4
4
  "license": "SEE LICENSE IN LICENSE.md",
5
- "type": "module",
6
- "main": "dist/index.js",
5
+ "main": "./dist/index.cjs",
6
+ "module": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js",
12
+ "require": "./dist/index.cjs"
13
+ }
14
+ },
7
15
  "bin": {
8
16
  "twick-render-server": "./dist/cli.js"
9
17
  },
10
18
  "scripts": {
11
- "build": "tsc",
19
+ "build": "tsup",
12
20
  "dev": "tsx watch src/server.ts",
13
21
  "start": "node dist/server.js",
14
22
  "test:render": "tsx src/test-render.ts",
@@ -18,12 +26,12 @@
18
26
  "access": "public"
19
27
  },
20
28
  "dependencies": {
21
- "@twick/2d": "^0.15.0",
22
- "@twick/core": "^0.15.0",
23
- "@twick/ffmpeg": "^0.15.0",
24
- "@twick/renderer": "^0.15.0",
25
- "@twick/ui": "^0.15.0",
26
- "@twick/visualizer": "^0.15.0",
29
+ "@twick/2d": "^0.15.2",
30
+ "@twick/core": "^0.15.2",
31
+ "@twick/ffmpeg": "^0.15.2",
32
+ "@twick/renderer": "^0.15.2",
33
+ "@twick/ui": "^0.15.2",
34
+ "@twick/visualizer": "0.15.2",
27
35
  "cors": "^2.8.5",
28
36
  "express": "^4.18.2",
29
37
  "express-rate-limit": "^8.0.1",
@@ -35,6 +43,7 @@
35
43
  "@types/express": "^4.17.21",
36
44
  "@types/node": "^20.10.0",
37
45
  "rimraf": "^5.0.5",
46
+ "tsup": "^8.0.0",
38
47
  "tsx": "^4.7.0",
39
48
  "typescript": "5.4.2"
40
49
  },
package/src/server.ts CHANGED
@@ -2,7 +2,7 @@ import express from "express";
2
2
  import cors from "cors";
3
3
  import path from "path";
4
4
  import { fileURLToPath } from "url";
5
- import renderTwickVideo from "./renderer.js";
5
+ import renderTwickVideo from "./renderer";
6
6
 
7
7
  const PORT = process.env.PORT || 3001;
8
8
  const BASE_PATH = `http://localhost:${PORT}`;
package/tsconfig.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "compilerOptions": {
3
3
  "target": "ES2022",
4
- "module": "ESNext",
5
- "moduleResolution": "bundler",
4
+ "module": "Node16",
5
+ "moduleResolution": "Node16",
6
6
  "allowSyntheticDefaultImports": true,
7
7
  "esModuleInterop": true,
8
8
  "allowJs": true,
@@ -18,5 +18,5 @@
18
18
  "noEmit": false
19
19
  },
20
20
  "include": ["src/**/*"],
21
- "exclude": ["node_modules", "dist"]
21
+ "exclude": ["node_modules", "dist", "src/**/*.test.ts", "src/test-render.ts"]
22
22
  }
package/tsup.config.ts ADDED
@@ -0,0 +1,49 @@
1
+ import { defineConfig } from 'tsup';
2
+
3
+ export default defineConfig([
4
+ // Build index.ts in both CJS and ESM for library exports
5
+ {
6
+ entry: ['src/index.ts'],
7
+ format: ['cjs', 'esm'],
8
+ dts: true,
9
+ splitting: false,
10
+ sourcemap: true,
11
+ clean: true,
12
+ outDir: 'dist',
13
+ external: [
14
+ '@twick/2d',
15
+ '@twick/core',
16
+ '@twick/ffmpeg',
17
+ '@twick/renderer',
18
+ '@twick/ui',
19
+ '@twick/visualizer',
20
+ 'cors',
21
+ 'express',
22
+ 'express-rate-limit',
23
+ 'node-fetch',
24
+ 'path'
25
+ ],
26
+ },
27
+ // Build cli.ts and server.ts only as ESM (they use import.meta)
28
+ {
29
+ entry: ['src/cli.ts', 'src/server.ts'],
30
+ format: ['esm'],
31
+ dts: false, // No need for declarations for CLI/server files
32
+ splitting: false,
33
+ sourcemap: true,
34
+ outDir: 'dist',
35
+ external: [
36
+ '@twick/2d',
37
+ '@twick/core',
38
+ '@twick/ffmpeg',
39
+ '@twick/renderer',
40
+ '@twick/ui',
41
+ '@twick/visualizer',
42
+ 'cors',
43
+ 'express',
44
+ 'express-rate-limit',
45
+ 'node-fetch',
46
+ 'path'
47
+ ],
48
+ },
49
+ ]);
package/dist/cli.d.ts DELETED
@@ -1,3 +0,0 @@
1
- #!/usr/bin/env node
2
- export {};
3
- //# sourceMappingURL=cli.d.ts.map
package/dist/cli.d.ts.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,YAAY,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;GAiBG;AACH,QAAA,MAAM,gBAAgB,GAAU,WAAW,GAAG,EAAE,UAAU,GAAG,oBAiC5D,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
package/dist/renderer.js DELETED
@@ -1,55 +0,0 @@
1
- import { renderVideo } from "@twick/renderer";
2
- /**
3
- * Renders a Twick video with the provided variables and settings.
4
- * Processes project variables, merges settings with defaults, and
5
- * generates a video file using the Twick renderer.
6
- *
7
- * @param variables - Project variables containing input configuration
8
- * @param settings - Optional render settings to override defaults
9
- * @returns Promise resolving to the path of the rendered video file
10
- *
11
- * @example
12
- * ```js
13
- * const videoPath = await renderTwickVideo(
14
- * { input: { properties: { width: 1920, height: 1080 } } },
15
- * { quality: "high", outFile: "my-video.mp4" }
16
- * );
17
- * // videoPath = "./output/my-video.mp4"
18
- * ```
19
- */
20
- const renderTwickVideo = async (variables, settings) => {
21
- try {
22
- const { input } = variables;
23
- const { properties } = input;
24
- // Merge user settings with defaults
25
- const mergedSettings = {
26
- logProgress: true,
27
- outDir: "./output",
28
- outFile: properties.reqesutId ?? `video-${Date.now()}` + ".mp4",
29
- quality: "medium",
30
- projectSettings: {
31
- exporter: {
32
- name: "@twick/core/wasm",
33
- },
34
- size: {
35
- x: properties.width,
36
- y: properties.height,
37
- },
38
- },
39
- ...settings, // Allow user settings to override defaults
40
- };
41
- const file = await renderVideo({
42
- projectFile: "@twick/visualizer/dist/project.js",
43
- variables: variables,
44
- settings: mergedSettings,
45
- });
46
- console.log("Successfully rendered: ", file);
47
- return file;
48
- }
49
- catch (error) {
50
- console.error("Render error:", error);
51
- throw error;
52
- }
53
- };
54
- export default renderTwickVideo;
55
- //# sourceMappingURL=renderer.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"renderer.js","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE9C;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,gBAAgB,GAAG,KAAK,EAAE,SAAc,EAAE,QAAa,EAAE,EAAE;IAC/D,IAAI,CAAC;QACH,MAAM,EAAE,KAAK,EAAE,GAAG,SAAS,CAAC;QAC5B,MAAM,EAAE,UAAU,EAAE,GAAG,KAAK,CAAC;QAC7B,oCAAoC;QACpC,MAAM,cAAc,GAAG;YACrB,WAAW,EAAE,IAAI;YACjB,MAAM,EAAE,UAAU;YAClB,OAAO,EAAE,UAAU,CAAC,SAAS,IAAI,SAAS,IAAI,CAAC,GAAG,EAAE,EAAE,GAAG,MAAM;YAC/D,OAAO,EAAE,QAAQ;YACjB,eAAe,EAAE;gBACf,QAAQ,EAAE;oBACR,IAAI,EAAE,kBAAkB;iBACzB;gBACD,IAAI,EAAE;oBACJ,CAAC,EAAE,UAAU,CAAC,KAAK;oBACnB,CAAC,EAAE,UAAU,CAAC,MAAM;iBACrB;aACF;YACD,GAAG,QAAQ,EAAE,2CAA2C;SACzD,CAAC;QAEF,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC;YAC7B,WAAW,EAAE,mCAAmC;YAChD,SAAS,EAAE,SAAS;YACpB,QAAQ,EAAE,cAAc;SACzB,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,yBAAyB,EAAE,IAAI,CAAC,CAAC;QAC7C,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC;QACtC,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
package/dist/server.d.ts DELETED
@@ -1,3 +0,0 @@
1
- declare const nodeApp: import("express").Express;
2
- export default nodeApp;
3
- //# sourceMappingURL=server.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AA6FA,QAAA,MAAM,OAAO,EAAE,OAAO,SAAS,EAAE,OAAmB,CAAC;AAiGrD,eAAe,OAAO,CAAC"}
package/dist/server.js DELETED
@@ -1,175 +0,0 @@
1
- import express from "express";
2
- import cors from "cors";
3
- import path from "path";
4
- import { fileURLToPath } from "url";
5
- import renderTwickVideo from "./renderer.js";
6
- const PORT = process.env.PORT || 3001;
7
- const BASE_PATH = `http://localhost:${PORT}`;
8
- const __filename = fileURLToPath(import.meta.url);
9
- const __dirname = path.dirname(__filename);
10
- // Rate limiting configuration
11
- const RATE_LIMIT_WINDOW_MS = 15 * 60 * 1000; // 15 minutes
12
- const RATE_LIMIT_MAX_REQUESTS = 100; // Maximum requests per window
13
- const RATE_LIMIT_CLEANUP_INTERVAL_MS = 60 * 1000; // Cleanup every minute
14
- const rateLimitStore = new Map();
15
- // Cleanup expired entries periodically
16
- setInterval(() => {
17
- const now = Date.now();
18
- for (const [key, entry] of rateLimitStore.entries()) {
19
- if (now > entry.resetTime) {
20
- rateLimitStore.delete(key);
21
- }
22
- }
23
- }, RATE_LIMIT_CLEANUP_INTERVAL_MS);
24
- /**
25
- * Rate limiting middleware for API endpoints.
26
- * Tracks request counts per IP address and enforces rate limits
27
- * to prevent abuse of the render server.
28
- *
29
- * @param req - Express request object
30
- * @param res - Express response object
31
- * @param next - Express next function
32
- *
33
- * @example
34
- * ```js
35
- * app.use('/api', rateLimitMiddleware);
36
- * // Applies rate limiting to all /api routes
37
- * ```
38
- */
39
- const rateLimitMiddleware = (req, res, next) => {
40
- const clientIP = req.ip || req.connection.remoteAddress || 'unknown';
41
- const now = Date.now();
42
- // Get or create rate limit entry for this IP
43
- let entry = rateLimitStore.get(clientIP);
44
- if (!entry || now > entry.resetTime) {
45
- // New window or expired entry
46
- entry = {
47
- count: 1,
48
- resetTime: now + RATE_LIMIT_WINDOW_MS
49
- };
50
- rateLimitStore.set(clientIP, entry);
51
- }
52
- else {
53
- // Increment count in current window
54
- entry.count++;
55
- if (entry.count > RATE_LIMIT_MAX_REQUESTS) {
56
- // Rate limit exceeded
57
- const retryAfter = Math.ceil((entry.resetTime - now) / 1000);
58
- res.set('Retry-After', retryAfter.toString());
59
- res.set('X-RateLimit-Limit', RATE_LIMIT_MAX_REQUESTS.toString());
60
- res.set('X-RateLimit-Remaining', '0');
61
- res.set('X-RateLimit-Reset', new Date(entry.resetTime).toISOString());
62
- return res.status(429).json({
63
- success: false,
64
- error: 'Too many requests',
65
- message: `Rate limit exceeded. Try again in ${retryAfter} seconds.`,
66
- retryAfter
67
- });
68
- }
69
- }
70
- // Add rate limit headers
71
- res.set('X-RateLimit-Limit', RATE_LIMIT_MAX_REQUESTS.toString());
72
- res.set('X-RateLimit-Remaining', (RATE_LIMIT_MAX_REQUESTS - entry.count).toString());
73
- res.set('X-RateLimit-Reset', new Date(entry.resetTime).toISOString());
74
- next();
75
- };
76
- const nodeApp = express();
77
- nodeApp.use(cors());
78
- nodeApp.use(express.json());
79
- // Serve static files from output directory
80
- nodeApp.use("/output", express.static(path.join(__dirname, "../output")));
81
- /**
82
- * POST endpoint for video rendering requests.
83
- * Accepts project variables and settings, renders the video,
84
- * and returns a download URL for the completed video.
85
- *
86
- * @param req - Express request object containing variables and settings
87
- * @param res - Express response object
88
- *
89
- * @example
90
- * ```js
91
- * POST /api/render-video
92
- * Body: { variables: {...}, settings: {...} }
93
- * Response: { success: true, downloadUrl: "..." }
94
- * ```
95
- */
96
- nodeApp.post("/api/render-video", async (req, res) => {
97
- const { variables, settings } = req.body;
98
- try {
99
- const outputPath = await renderTwickVideo(variables, settings);
100
- res.json({
101
- success: true,
102
- downloadUrl: `${BASE_PATH}/download/${path.basename(outputPath)}`,
103
- });
104
- }
105
- catch (error) {
106
- console.error("Render error:", error);
107
- res.status(500).json({
108
- success: false,
109
- error: error instanceof Error ? error.message : "Unknown error",
110
- });
111
- }
112
- });
113
- /**
114
- * GET endpoint for downloading rendered videos.
115
- * Serves video files with rate limiting and security checks
116
- * to prevent path traversal attacks.
117
- *
118
- * @param req - Express request object with filename parameter
119
- * @param res - Express response object
120
- *
121
- * @example
122
- * ```js
123
- * GET /download/video-123.mp4
124
- * // Downloads the specified video file
125
- * ```
126
- */
127
- nodeApp.get("/download/:filename", rateLimitMiddleware, (req, res) => {
128
- const outputDir = path.resolve(__dirname, "../output");
129
- const requestedPath = path.resolve(outputDir, req.params.filename);
130
- if (!requestedPath.startsWith(outputDir + path.sep)) {
131
- // Attempted path traversal or access outside output directory
132
- res.status(403).json({
133
- success: false,
134
- error: "Forbidden",
135
- });
136
- return;
137
- }
138
- res.download(requestedPath, (err) => {
139
- if (err) {
140
- res.status(404).json({
141
- success: false,
142
- error: "File not found",
143
- });
144
- }
145
- });
146
- });
147
- /**
148
- * Health check endpoint for monitoring server status.
149
- * Returns server status and current timestamp for health monitoring.
150
- *
151
- * @param req - Express request object
152
- * @param res - Express response object
153
- *
154
- * @example
155
- * ```js
156
- * GET /health
157
- * Response: { status: "ok", timestamp: "2024-01-01T00:00:00.000Z" }
158
- * ```
159
- */
160
- nodeApp.get("/health", (req, res) => {
161
- res.json({
162
- status: "ok",
163
- timestamp: new Date().toISOString(),
164
- });
165
- });
166
- // Export the app for programmatic usage
167
- export default nodeApp;
168
- // Start the server
169
- nodeApp.listen(PORT, () => {
170
- console.log(`Render server running on port ${PORT}`);
171
- console.log(`Health check: ${BASE_PATH}/health`);
172
- console.log(`API endpoint: ${BASE_PATH}/api/render-video`);
173
- console.log(`Download endpoint rate limited: ${RATE_LIMIT_MAX_REQUESTS} requests per ${RATE_LIMIT_WINDOW_MS / 60000} minutes`);
174
- });
175
- //# sourceMappingURL=server.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -1,10 +0,0 @@
1
- /**
2
- * Test file for rendering a video with an example project
3
- *
4
- * This script demonstrates how to use the renderTwickVideo function
5
- * to create a video from a Twick project configuration.
6
- *
7
- * Run with: tsx src/test-render.ts
8
- */
9
- export {};
10
- //# sourceMappingURL=test-render.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"test-render.d.ts","sourceRoot":"","sources":["../src/test-render.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
@@ -1,219 +0,0 @@
1
- /**
2
- * Test file for rendering a video with an example project
3
- *
4
- * This script demonstrates how to use the renderTwickVideo function
5
- * to create a video from a Twick project configuration.
6
- *
7
- * Run with: tsx src/test-render.ts
8
- */
9
- import { renderTwickVideo } from "./index.js";
10
- import { fileURLToPath } from "url";
11
- import { dirname, join } from "path";
12
- const __filename = fileURLToPath(import.meta.url);
13
- const __dirname = dirname(__filename);
14
- /**
15
- * Example project configuration
16
- * This creates a simple video with:
17
- * - A colored background rectangle
18
- * - Animated text elements
19
- * - Audio track
20
- */
21
- const exampleProject = {
22
- input: {
23
- properties: {
24
- width: 1920,
25
- height: 1080,
26
- fps: 30,
27
- },
28
- tracks: [
29
- {
30
- id: "t-background",
31
- type: "element",
32
- name: "background",
33
- elements: [
34
- {
35
- id: "e-bg-1",
36
- trackId: "t-background",
37
- type: "rect",
38
- s: 0,
39
- e: 10,
40
- props: {
41
- width: 1920,
42
- height: 1080,
43
- fill: "#1a1a2e",
44
- },
45
- },
46
- ],
47
- },
48
- {
49
- id: "t-text",
50
- type: "element",
51
- name: "text",
52
- elements: [
53
- {
54
- id: "e-text-1",
55
- trackId: "t-text",
56
- type: "text",
57
- s: 1,
58
- e: 4,
59
- t: "Welcome to Twick!",
60
- props: {
61
- fill: "#ffffff",
62
- fontSize: 72,
63
- fontFamily: "Arial",
64
- fontWeight: "bold",
65
- x: 0,
66
- y: -200,
67
- },
68
- animation: {
69
- name: "fade",
70
- animate: "enter",
71
- duration: 1,
72
- },
73
- textEffect: {
74
- name: "typewriter",
75
- duration: 2,
76
- },
77
- },
78
- {
79
- id: "e-text-2",
80
- trackId: "t-text",
81
- type: "text",
82
- s: 4,
83
- e: 7,
84
- t: "Create Amazing Videos",
85
- props: {
86
- fill: "#4ecdc4",
87
- fontSize: 64,
88
- fontFamily: "Arial",
89
- fontWeight: "bold",
90
- x: 0,
91
- y: 0,
92
- },
93
- animation: {
94
- name: "rise",
95
- animate: "enter",
96
- duration: 1,
97
- },
98
- },
99
- {
100
- id: "e-text-3",
101
- trackId: "t-text",
102
- type: "text",
103
- s: 7,
104
- e: 10,
105
- t: "Programmatically!",
106
- props: {
107
- fill: "#ffd700",
108
- fontSize: 80,
109
- fontFamily: "Arial",
110
- fontWeight: "bold",
111
- x: 0,
112
- y: 200,
113
- },
114
- animation: {
115
- name: "fade",
116
- animate: "enter",
117
- duration: 1,
118
- },
119
- },
120
- ],
121
- },
122
- {
123
- id: "t-shapes",
124
- type: "element",
125
- name: "shapes",
126
- elements: [
127
- {
128
- id: "e-circle-1",
129
- trackId: "t-shapes",
130
- type: "circle",
131
- s: 2,
132
- e: 8,
133
- props: {
134
- width: 200,
135
- height: 200,
136
- fill: "#ff6b6b",
137
- x: -400,
138
- y: 0,
139
- },
140
- animation: {
141
- name: "fade",
142
- animate: "enter",
143
- duration: 1,
144
- },
145
- },
146
- {
147
- id: "e-rect-1",
148
- trackId: "t-shapes",
149
- type: "rect",
150
- s: 5,
151
- e: 10,
152
- props: {
153
- width: 300,
154
- height: 150,
155
- fill: "#4ecdc4",
156
- x: 400,
157
- y: 0,
158
- },
159
- animation: {
160
- name: "rise",
161
- animate: "enter",
162
- duration: 1,
163
- },
164
- },
165
- ],
166
- },
167
- ],
168
- version: 1,
169
- },
170
- };
171
- /**
172
- * Render settings
173
- */
174
- const renderSettings = {
175
- outFile: `test-video-${Date.now()}.mp4`,
176
- outDir: join(__dirname, "../output"),
177
- quality: "medium",
178
- logProgress: true,
179
- };
180
- /**
181
- * Main test function
182
- */
183
- async function testVideoRender() {
184
- console.log("🎬 Starting video render test...\n");
185
- console.log("📋 Project Configuration:");
186
- console.log(` Resolution: ${exampleProject.input.properties.width}x${exampleProject.input.properties.height}`);
187
- console.log(` FPS: ${exampleProject.input.properties.fps}`);
188
- console.log(` Tracks: ${exampleProject.input.tracks.length}`);
189
- console.log(` Total Elements: ${exampleProject.input.tracks.reduce((sum, track) => sum + track.elements.length, 0)}\n`);
190
- try {
191
- console.log("🔄 Rendering video...");
192
- const startTime = Date.now();
193
- const outputPath = await renderTwickVideo(exampleProject, renderSettings);
194
- const endTime = Date.now();
195
- const duration = ((endTime - startTime) / 1000).toFixed(2);
196
- console.log("\n✅ Video rendered successfully!");
197
- console.log(`📁 Output file: ${outputPath}`);
198
- console.log(`⏱️ Render time: ${duration}s`);
199
- console.log(`\n🎉 Test completed successfully!`);
200
- return outputPath;
201
- }
202
- catch (error) {
203
- console.error("\n❌ Render failed:");
204
- console.error(error);
205
- if (error instanceof Error) {
206
- console.error(` Error: ${error.message}`);
207
- if (error.stack) {
208
- console.error(` Stack: ${error.stack}`);
209
- }
210
- }
211
- process.exit(1);
212
- }
213
- }
214
- // Run the test
215
- testVideoRender().catch((error) => {
216
- console.error("Fatal error:", error);
217
- process.exit(1);
218
- });
219
- //# sourceMappingURL=test-render.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"test-render.js","sourceRoot":"","sources":["../src/test-render.ts"],"names":[],"mappings":"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"}