@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 +2 -0
- package/dist/test-render.d.ts +10 -0
- package/dist/test-render.d.ts.map +1 -0
- package/dist/test-render.js +219 -0
- package/dist/test-render.js.map +1 -0
- package/package.json +9 -9
- package/package.json.bak +9 -9
- package/src/test-render.ts +228 -0
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.
|
|
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.
|
|
21
|
-
"@twick/core": "0.
|
|
22
|
-
"@twick/ffmpeg": "0.
|
|
23
|
-
"@twick/renderer": "0.
|
|
24
|
-
"@twick/ui": "0.
|
|
25
|
-
"@twick/visualizer": "0.
|
|
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": ">=
|
|
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.
|
|
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.
|
|
21
|
-
"@twick/core": "0.
|
|
22
|
-
"@twick/ffmpeg": "0.
|
|
23
|
-
"@twick/renderer": "0.
|
|
24
|
-
"@twick/ui": "0.
|
|
25
|
-
"@twick/visualizer": "0.
|
|
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": ">=
|
|
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
|
+
});
|