@twick/render-server 0.14.18 → 0.15.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/README.md CHANGED
@@ -16,6 +16,8 @@ npm install @twick/render-server
16
16
  pnpm add @twick/render-server
17
17
  ```
18
18
 
19
+ **Note:** All required dependencies (`@twick/visualizer`, `@twick/media-utils`, and other Twick packages) are automatically installed with `@twick/render-server`.
20
+
19
21
  ## Quick Start
20
22
 
21
23
  ### Option 1: Scaffold a Server (Recommended)
@@ -0,0 +1,10 @@
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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-render.d.ts","sourceRoot":"","sources":["../src/test-render.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
@@ -0,0 +1,219 @@
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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-render.js","sourceRoot":"","sources":["../src/test-render.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@twick/render-server",
3
- "version": "0.14.18",
3
+ "version": "0.15.0",
4
4
  "license": "SEE LICENSE IN LICENSE.md",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -11,19 +11,19 @@
11
11
  "build": "tsc",
12
12
  "dev": "tsx watch src/server.ts",
13
13
  "start": "node dist/server.js",
14
+ "test:render": "tsx src/test-render.ts",
14
15
  "clean": "rimraf dist"
15
16
  },
16
17
  "publishConfig": {
17
18
  "access": "public"
18
19
  },
19
20
  "dependencies": {
20
- "@twick/2d": "0.14.18",
21
- "@twick/core": "0.14.18",
22
- "@twick/ffmpeg": "0.14.18",
23
- "@twick/renderer": "0.14.18",
24
- "@twick/ui": "0.14.18",
25
- "@twick/visualizer": "0.14.18",
26
- "@types/express-rate-limit": "^6.0.2",
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",
27
27
  "cors": "^2.8.5",
28
28
  "express": "^4.18.2",
29
29
  "express-rate-limit": "^8.0.1",
@@ -39,6 +39,6 @@
39
39
  "typescript": "5.4.2"
40
40
  },
41
41
  "engines": {
42
- "node": ">=18.0.0"
42
+ "node": ">=20.0.0"
43
43
  }
44
44
  }
package/package.json.bak CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@twick/render-server",
3
- "version": "0.14.18",
3
+ "version": "0.15.0",
4
4
  "license": "SEE LICENSE IN LICENSE.md",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -11,19 +11,19 @@
11
11
  "build": "tsc",
12
12
  "dev": "tsx watch src/server.ts",
13
13
  "start": "node dist/server.js",
14
+ "test:render": "tsx src/test-render.ts",
14
15
  "clean": "rimraf dist"
15
16
  },
16
17
  "publishConfig": {
17
18
  "access": "public"
18
19
  },
19
20
  "dependencies": {
20
- "@twick/2d": "0.14.18",
21
- "@twick/core": "0.14.18",
22
- "@twick/ffmpeg": "0.14.18",
23
- "@twick/renderer": "0.14.18",
24
- "@twick/ui": "0.14.18",
25
- "@twick/visualizer": "0.14.18",
26
- "@types/express-rate-limit": "^6.0.2",
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",
27
27
  "cors": "^2.8.5",
28
28
  "express": "^4.18.2",
29
29
  "express-rate-limit": "^8.0.1",
@@ -39,6 +39,6 @@
39
39
  "typescript": "5.4.2"
40
40
  },
41
41
  "engines": {
42
- "node": ">=18.0.0"
42
+ "node": ">=20.0.0"
43
43
  }
44
44
  }
@@ -0,0 +1,228 @@
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
+
10
+ import { renderTwickVideo } from "./index.js";
11
+ import { fileURLToPath } from "url";
12
+ import { dirname, join } from "path";
13
+
14
+ const __filename = fileURLToPath(import.meta.url);
15
+ const __dirname = dirname(__filename);
16
+
17
+ /**
18
+ * Example project configuration
19
+ * This creates a simple video with:
20
+ * - A colored background rectangle
21
+ * - Animated text elements
22
+ * - Audio track
23
+ */
24
+ const exampleProject = {
25
+ input: {
26
+ properties: {
27
+ width: 1920,
28
+ height: 1080,
29
+ fps: 30,
30
+ },
31
+ tracks: [
32
+ {
33
+ id: "t-background",
34
+ type: "element",
35
+ name: "background",
36
+ elements: [
37
+ {
38
+ id: "e-bg-1",
39
+ trackId: "t-background",
40
+ type: "rect",
41
+ s: 0,
42
+ e: 10,
43
+ props: {
44
+ width: 1920,
45
+ height: 1080,
46
+ fill: "#1a1a2e",
47
+ },
48
+ },
49
+ ],
50
+ },
51
+ {
52
+ id: "t-text",
53
+ type: "element",
54
+ name: "text",
55
+ elements: [
56
+ {
57
+ id: "e-text-1",
58
+ trackId: "t-text",
59
+ type: "text",
60
+ s: 1,
61
+ e: 4,
62
+ t: "Welcome to Twick!",
63
+ props: {
64
+ fill: "#ffffff",
65
+ fontSize: 72,
66
+ fontFamily: "Arial",
67
+ fontWeight: "bold",
68
+ x: 0,
69
+ y: -200,
70
+ },
71
+ animation: {
72
+ name: "fade",
73
+ animate: "enter",
74
+ duration: 1,
75
+ },
76
+ textEffect: {
77
+ name: "typewriter",
78
+ duration: 2,
79
+ },
80
+ },
81
+ {
82
+ id: "e-text-2",
83
+ trackId: "t-text",
84
+ type: "text",
85
+ s: 4,
86
+ e: 7,
87
+ t: "Create Amazing Videos",
88
+ props: {
89
+ fill: "#4ecdc4",
90
+ fontSize: 64,
91
+ fontFamily: "Arial",
92
+ fontWeight: "bold",
93
+ x: 0,
94
+ y: 0,
95
+ },
96
+ animation: {
97
+ name: "rise",
98
+ animate: "enter",
99
+ duration: 1,
100
+ },
101
+ },
102
+ {
103
+ id: "e-text-3",
104
+ trackId: "t-text",
105
+ type: "text",
106
+ s: 7,
107
+ e: 10,
108
+ t: "Programmatically!",
109
+ props: {
110
+ fill: "#ffd700",
111
+ fontSize: 80,
112
+ fontFamily: "Arial",
113
+ fontWeight: "bold",
114
+ x: 0,
115
+ y: 200,
116
+ },
117
+ animation: {
118
+ name: "fade",
119
+ animate: "enter",
120
+ duration: 1,
121
+ },
122
+ },
123
+ ],
124
+ },
125
+ {
126
+ id: "t-shapes",
127
+ type: "element",
128
+ name: "shapes",
129
+ elements: [
130
+ {
131
+ id: "e-circle-1",
132
+ trackId: "t-shapes",
133
+ type: "circle",
134
+ s: 2,
135
+ e: 8,
136
+ props: {
137
+ width: 200,
138
+ height: 200,
139
+ fill: "#ff6b6b",
140
+ x: -400,
141
+ y: 0,
142
+ },
143
+ animation: {
144
+ name: "fade",
145
+ animate: "enter",
146
+ duration: 1,
147
+ },
148
+ },
149
+ {
150
+ id: "e-rect-1",
151
+ trackId: "t-shapes",
152
+ type: "rect",
153
+ s: 5,
154
+ e: 10,
155
+ props: {
156
+ width: 300,
157
+ height: 150,
158
+ fill: "#4ecdc4",
159
+ x: 400,
160
+ y: 0,
161
+ },
162
+ animation: {
163
+ name: "rise",
164
+ animate: "enter",
165
+ duration: 1,
166
+ },
167
+ },
168
+ ],
169
+ },
170
+ ],
171
+ version: 1,
172
+ },
173
+ };
174
+
175
+ /**
176
+ * Render settings
177
+ */
178
+ const renderSettings = {
179
+ outFile: `test-video-${Date.now()}.mp4`,
180
+ outDir: join(__dirname, "../output"),
181
+ quality: "medium",
182
+ logProgress: true,
183
+ };
184
+
185
+ /**
186
+ * Main test function
187
+ */
188
+ async function testVideoRender() {
189
+ console.log("šŸŽ¬ Starting video render test...\n");
190
+ console.log("šŸ“‹ Project Configuration:");
191
+ console.log(` Resolution: ${exampleProject.input.properties.width}x${exampleProject.input.properties.height}`);
192
+ console.log(` FPS: ${exampleProject.input.properties.fps}`);
193
+ console.log(` Tracks: ${exampleProject.input.tracks.length}`);
194
+ console.log(` Total Elements: ${exampleProject.input.tracks.reduce((sum, track) => sum + track.elements.length, 0)}\n`);
195
+
196
+ try {
197
+ console.log("šŸ”„ Rendering video...");
198
+ const startTime = Date.now();
199
+
200
+ const outputPath = await renderTwickVideo(exampleProject, renderSettings);
201
+
202
+ const endTime = Date.now();
203
+ const duration = ((endTime - startTime) / 1000).toFixed(2);
204
+
205
+ console.log("\nāœ… Video rendered successfully!");
206
+ console.log(`šŸ“ Output file: ${outputPath}`);
207
+ console.log(`ā±ļø Render time: ${duration}s`);
208
+ console.log(`\nšŸŽ‰ Test completed successfully!`);
209
+
210
+ return outputPath;
211
+ } catch (error) {
212
+ console.error("\nāŒ Render failed:");
213
+ console.error(error);
214
+ if (error instanceof Error) {
215
+ console.error(` Error: ${error.message}`);
216
+ if (error.stack) {
217
+ console.error(` Stack: ${error.stack}`);
218
+ }
219
+ }
220
+ process.exit(1);
221
+ }
222
+ }
223
+
224
+ // Run the test
225
+ testVideoRender().catch((error) => {
226
+ console.error("Fatal error:", error);
227
+ process.exit(1);
228
+ });