@twick/visualizer 0.0.1

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/src/sample.ts ADDED
@@ -0,0 +1,450 @@
1
+ export const sample = {
2
+ "input": {
3
+ "properties": {
4
+ "width": 720,
5
+ "height": 1280,
6
+ "video_format": "mp4",
7
+ "video_codec": "libx264",
8
+ "audio_codec": "aac",
9
+ "video_bitrate": "2500k",
10
+ "audio_bitrate": "128k",
11
+ "fps": 30
12
+ },
13
+ "backgroundMusic": "",
14
+ "backgroundMusicLevel": 1,
15
+ "bucket_name": "kifferai-assets",
16
+ "context": {
17
+ "scriptInput": {
18
+ "scriptStyle": "PRODUCT_DEMONSTRATION"
19
+ },
20
+ "requestId": "f5d5db7a-8911-4b28-9c3c-71d91c83ddda",
21
+ "campaignId": "campaign",
22
+ "productUrl": "",
23
+ "pageId": "page",
24
+ "userId": "b1436dea-50e1-7049-cf34-6e49702da72a",
25
+ "productName": "product",
26
+ "orgId": "a251d9971a55"
27
+ },
28
+ "basePath": "carlyn",
29
+ "timeline": [
30
+ {
31
+ "id": "t-scene",
32
+ "type": "scene",
33
+ "elements": [
34
+ {
35
+ "id": "e-244f8d5a3bbc",
36
+ "type": "video",
37
+ "s": 0,
38
+ "e": 4.74,
39
+ "objectFit": "cover",
40
+ "props": {
41
+ "time": 8.428,
42
+ "src": "https://static-assets.kifferai.com/developmen/a251d9971a55/c436f351-ee9c-49c2-a26f-e7a7733c77ff/video_1746786031627-96448ec8-6430-4d4b-bb89-ebdbfeade7fa-normalized-1747225095191.mp4",
43
+ "play": true,
44
+ "decoder": "web",
45
+ "volume": 1,
46
+ "playbackRate": 2.4
47
+ },
48
+ "frame": {
49
+ "size": [
50
+ 720,
51
+ 1280
52
+ ],
53
+ "layout": false,
54
+ "clip": "true"
55
+ }
56
+ },
57
+ {
58
+ "id": "e-ef2f208db319",
59
+ "type": "video",
60
+ "s": 4.74,
61
+ "e": 6.774,
62
+ "objectFit": "cover",
63
+ "props": {
64
+ "time": 0,
65
+ "src": "https://static-assets.kifferai.com/developmen/a251d9971a55/63e0e7c3-5939-41a2-95c7-4e47e8be1ebf/video_1746786032120-6e4ab84c-d0dd-401e-b5e8-13d49fd8fe67-normalized-1747225095053.mp4",
66
+ "play": true,
67
+ "decoder": "web",
68
+ "volume": 1,
69
+ "playbackRate": 2
70
+ },
71
+ "frame": {
72
+ "size": [
73
+ 720,
74
+ 1280
75
+ ],
76
+ "layout": false,
77
+ "clip": "true"
78
+ }
79
+ },
80
+ {
81
+ "id": "e-477f620c0ec7",
82
+ "type": "video",
83
+ "s": 6.774,
84
+ "e": 9.395,
85
+ "objectFit": "cover",
86
+ "props": {
87
+ "time": 18.222499999999997,
88
+ "src": "https://static-assets.kifferai.com/developmen/a251d9971a55/e66b4682-096d-46c5-b1b2-1e2e6a46fe8d/video_1746790653457-7e9e9a1d-9410-4bb3-bec1-7474fa88286c-normalized-1747225095442.mp4",
89
+ "play": true,
90
+ "decoder": "web",
91
+ "volume": 1,
92
+ "playbackRate": 2
93
+ },
94
+ "frame": {
95
+ "size": [
96
+ 2292.281711648068,
97
+ 1286.2247382025269
98
+ ],
99
+ "layout": false,
100
+ "clip": "true",
101
+ "rotation": 0,
102
+ "x": 269.48206359326264,
103
+ "y": 6.293648227413769
104
+ }
105
+ },
106
+ {
107
+ "id": "e-8e7713322971",
108
+ "type": "video",
109
+ "s": 9.395,
110
+ "e": 11.045625,
111
+ "objectFit": "cover",
112
+ "props": {
113
+ "time": 0,
114
+ "src": "https://static-assets.kifferai.com/developmen/a251d9971a55/785c23ac-46b9-412e-afa6-a2cb56359409/video_1746791788884-91cb1098-d5f0-4528-83ee-40396774362e-normalized-1747225092682.mp4",
115
+ "play": true,
116
+ "decoder": "web",
117
+ "volume": 1,
118
+ "playbackRate": 1.6
119
+ },
120
+ "frame": {
121
+ "size": [
122
+ 2308.2048543926235,
123
+ 1295.1593905203056
124
+ ],
125
+ "layout": false,
126
+ "clip": "true",
127
+ "rotation": 0,
128
+ "x": -13.276787982361498,
129
+ "y": 7.751279402190107
130
+ }
131
+ },
132
+ {
133
+ "id": "e-7531e6fa1e0d",
134
+ "type": "video",
135
+ "s": 11.046,
136
+ "e": 12.07,
137
+ "objectFit": "cover",
138
+ "props": {
139
+ "time": 7.721,
140
+ "src": "https://static-assets.kifferai.com/developmen/a251d9971a55/9e75d848-ee72-417c-a0ab-9b03cbe8a8e8/video_1746791788884-91cb1098-d5f0-4528-83ee-40396774362e-normalized-1747225094687.mp4",
141
+ "play": true,
142
+ "decoder": "web",
143
+ "volume": 1,
144
+ "playbackRate": 1.25
145
+ },
146
+ "frame": {
147
+ "size": [
148
+ 2311.1861840816873,
149
+ 1296.8322477347244
150
+ ],
151
+ "layout": false,
152
+ "clip": "true",
153
+ "rotation": 0,
154
+ "x": 449.37247349257666,
155
+ "y": 9.38850926628038
156
+ }
157
+ },
158
+ {
159
+ "id": "e-3b7b7272a680",
160
+ "type": "video",
161
+ "s": 12.07,
162
+ "e": 12.65,
163
+ "objectFit": "cover",
164
+ "props": {
165
+ "time": 15.761000000000001,
166
+ "src": "https://static-assets.kifferai.com/developmen/a251d9971a55/c8411732-b0c8-45a9-808d-e5adf6396cc0/video_1746791788884-91cb1098-d5f0-4528-83ee-40396774362e-normalized-1747225095328.mp4",
167
+ "play": true,
168
+ "decoder": "web"
169
+ },
170
+ "frame": {
171
+ "size": [
172
+ 2350.1907312156336,
173
+ 1318.718132515439
174
+ ],
175
+ "layout": false,
176
+ "clip": "true",
177
+ "rotation": 0,
178
+ "x": 172.4452216608522,
179
+ "y": 15.93068052161425
180
+ }
181
+ },
182
+ {
183
+ "id": "e-6121e86e1529",
184
+ "type": "video",
185
+ "s": 12.65,
186
+ "e": 12.97,
187
+ "objectFit": "cover",
188
+ "props": {
189
+ "time": 16.467,
190
+ "src": "https://static-assets.kifferai.com/developmen/a251d9971a55/ebdd6f60-5750-4228-a5cd-f321f60664c2/video_1746791788884-91cb1098-d5f0-4528-83ee-40396774362e-normalized-1747225093091.mp4",
191
+ "play": true,
192
+ "decoder": "web"
193
+ },
194
+ "frame": {
195
+ "size": [
196
+ 2250.6441550073,
197
+ 1262.861442531874
198
+ ],
199
+ "layout": false,
200
+ "clip": "true",
201
+ "rotation": 0,
202
+ "x": 349.31120819483976,
203
+ "y": 10.893313528412591
204
+ }
205
+ },
206
+ {
207
+ "id": "e-1b1fe6998ebd",
208
+ "type": "video",
209
+ "s": 12.97,
210
+ "e": 16.644000000000002,
211
+ "objectFit": "cover",
212
+ "props": {
213
+ "time": 23.286,
214
+ "src": "https://static-assets.kifferai.com/developmen/a251d9971a55/d0156321-eb31-4168-adc0-9c4ad1fd3963/video_1746791788884-91cb1098-d5f0-4528-83ee-40396774362e-normalized-1747225092630.mp4",
215
+ "play": true,
216
+ "decoder": "web"
217
+ },
218
+ "frame": {
219
+ "size": [
220
+ 2338.697802344495,
221
+ 1312.2693224266334
222
+ ],
223
+ "layout": false,
224
+ "clip": "true",
225
+ "rotation": 0,
226
+ "x": 105.53672564636827,
227
+ "y": 12.299877537072007
228
+ }
229
+ }
230
+ ],
231
+ "name": "scene"
232
+ },
233
+ {
234
+ "id": "t-83fa5f365f7f",
235
+ "type": "audio",
236
+ "name": "audio",
237
+ "elements": [
238
+ {
239
+ "id": "e-50848c2d8271",
240
+ "type": "audio",
241
+ "s": 0,
242
+ "e": 16.587755,
243
+ "props": {
244
+ "time": 0,
245
+ "src": "https://static-assets.kifferai.com/developmen/a251d9971a55/brand-music/Unstoppable-Reprise-909549aa-6807-482b-ab92-bce7e6834fe7.mp3",
246
+ "play": true
247
+ },
248
+ "frame": {
249
+ "size": [
250
+ 720,
251
+ 1280
252
+ ],
253
+ "layout": false,
254
+ "clip": "true"
255
+ }
256
+ }
257
+ ]
258
+ },
259
+ {
260
+ "id": "t-795891203a03",
261
+ "type": "element",
262
+ "name": "element",
263
+ "elements": [
264
+ {
265
+ "id": "e-6c32ca5f728e",
266
+ "type": "text",
267
+ "s": 0.009,
268
+ "e": 4.691000000000001,
269
+ "t": "GOD WILL BREAK YOU",
270
+ "props": {
271
+ "fill": "#ffd700",
272
+ "font": {
273
+ "size": 48,
274
+ "family": "Poppins"
275
+ },
276
+ "fontSize": 54,
277
+ "fontFamily": "Impact",
278
+ "stroke": "#000000",
279
+ "lineWidth": 0.25,
280
+ "fontWeight": "bold",
281
+ "fontStyle": "Italic",
282
+ "rotation": 0,
283
+ "x": -11.306514773940933,
284
+ "y": 103.95475034024639
285
+ }
286
+ },
287
+ {
288
+ "id": "e-39e2112fa735",
289
+ "type": "text",
290
+ "s": 4.824,
291
+ "e": 6.709,
292
+ "t": "BREAK YOU AGAIN",
293
+ "props": {
294
+ "fill": "#FFFFFF",
295
+ "font": {
296
+ "size": 48,
297
+ "family": "Poppins"
298
+ },
299
+ "fontSize": 54,
300
+ "fontFamily": "Impact",
301
+ "stroke": "#000000",
302
+ "lineWidth": 0.25,
303
+ "fontWeight": "bold",
304
+ "fontStyle": "normal",
305
+ "rotation": 0,
306
+ "x": 2.261302954788164,
307
+ "y": 128.8134949868271
308
+ }
309
+ },
310
+ {
311
+ "id": "e-384f59e94253",
312
+ "type": "text",
313
+ "s": 4.904,
314
+ "e": 6.7059999999999995,
315
+ "t": "AND THEN",
316
+ "props": {
317
+ "fill": "#fffd70",
318
+ "font": {
319
+ "size": 48,
320
+ "family": "Poppins"
321
+ },
322
+ "fontSize": 54,
323
+ "fontFamily": "Impact",
324
+ "stroke": "#000000",
325
+ "lineWidth": 0.25,
326
+ "fontWeight": "bold",
327
+ "fontStyle": "Italic",
328
+ "rotation": 0,
329
+ "x": 0,
330
+ "y": 201.12984304960742
331
+ }
332
+ },
333
+ {
334
+ "id": "e-180cab9f1871",
335
+ "type": "text",
336
+ "s": 6.891,
337
+ "e": 9.343,
338
+ "t": "BREAK YOU ONCE AGAIN",
339
+ "props": {
340
+ "fill": "#ffd700",
341
+ "font": {
342
+ "size": 48,
343
+ "family": "Poppins"
344
+ },
345
+ "fontSize": 54,
346
+ "fontFamily": "Impact",
347
+ "stroke": "#000000",
348
+ "lineWidth": 0.25,
349
+ "fontWeight": "bold",
350
+ "fontStyle": "Italic",
351
+ "rotation": 0,
352
+ "x": 4.522605909576328,
353
+ "y": 81.35589157062759
354
+ }
355
+ },
356
+ {
357
+ "id": "e-7eada9ab2394",
358
+ "type": "text",
359
+ "s": 9.521,
360
+ "e": 10.993,
361
+ "t": "BUT",
362
+ "props": {
363
+ "fill": "#ffd700",
364
+ "font": {
365
+ "size": 48,
366
+ "family": "Poppins"
367
+ },
368
+ "fontSize": 54,
369
+ "fontFamily": "Impact",
370
+ "stroke": "#000000",
371
+ "lineWidth": 0.25,
372
+ "fontWeight": "bold",
373
+ "fontStyle": "Italic"
374
+ }
375
+ },
376
+ {
377
+ "id": "e-03039d49039b",
378
+ "type": "text",
379
+ "s": 11.171,
380
+ "e": 12.831999999999999,
381
+ "t": "IN THE END",
382
+ "props": {
383
+ "fill": "#ffd700",
384
+ "font": {
385
+ "size": 48,
386
+ "family": "Poppins"
387
+ },
388
+ "fontSize": 54,
389
+ "fontFamily": "Impact",
390
+ "stroke": "#000000",
391
+ "lineWidth": 0.25,
392
+ "fontWeight": "bold",
393
+ "fontStyle": "Italic",
394
+ "rotation": 0,
395
+ "x": 2.2613029547882206,
396
+ "y": 108.4745220941702
397
+ }
398
+ },
399
+ {
400
+ "id": "e-91d44d6180f9",
401
+ "type": "text",
402
+ "s": 13.077,
403
+ "e": 16.543,
404
+ "t": "HE WILL MAKE YOU",
405
+ "props": {
406
+ "fill": "#FFFFFF",
407
+ "font": {
408
+ "size": 48,
409
+ "family": "Poppins"
410
+ },
411
+ "fontSize": 54,
412
+ "fontFamily": "Impact",
413
+ "stroke": "#000000",
414
+ "lineWidth": 0.25,
415
+ "fontWeight": "bold",
416
+ "fontStyle": "normal",
417
+ "rotation": 0,
418
+ "x": 0,
419
+ "y": 27.118630523542492
420
+ }
421
+ },
422
+ {
423
+ "id": "e-ebf12eac0207",
424
+ "type": "text",
425
+ "s": 13.811,
426
+ "e": 16.534,
427
+ "t": "UNSTOPPABLE",
428
+ "props": {
429
+ "fill": "#ffd700",
430
+ "font": {
431
+ "size": 48,
432
+ "family": "Poppins"
433
+ },
434
+ "rotation": 0,
435
+ "x": -6.783908864364491,
436
+ "y": 99.43497858632281,
437
+ "fontSize": 58,
438
+ "fontFamily": "Impact",
439
+ "stroke": "#000000",
440
+ "lineWidth": 0.25,
441
+ "fontWeight": "bold",
442
+ "fontStyle": "Italic"
443
+ }
444
+ }
445
+ ]
446
+ }
447
+ ]
448
+ },
449
+ "version": 1
450
+ }
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Main visualizer component that renders the scene with video, audio, captions and other elements
3
+ * based on the provided input configuration.
4
+ */
5
+
6
+ import "./global.css";
7
+ import { Rect, makeScene2D, View2D } from "@revideo/2d";
8
+ import { all, useScene } from "@revideo/core";
9
+
10
+ import { DEFAULT_BACKGROUND_COLOR, TIMELINE_TYPES } from "./helpers/constants";
11
+ import { VideoInput } from "./helpers/types";
12
+ import { logger } from "./helpers/log.utils";
13
+ import {
14
+ makeAudioTimeline,
15
+ makeCaptionTimeline,
16
+ makeElementTimeline,
17
+ makeSceneTimeline,
18
+ makeVideoTimeline,
19
+ } from "./components/timeline";
20
+
21
+ /**
22
+ * Creates and configures the main scene for video visualization
23
+ * @param {string} name - Name of the scene
24
+ * @param {Function} generator - Generator function that handles scene setup and animation
25
+ * @returns {Scene2D} Configured scene object
26
+ */
27
+ export const scene = makeScene2D("scene", function* (view: View2D) {
28
+ // Get input configuration from scene variables
29
+ const input = useScene().variables.get("input", null)() as VideoInput | null;
30
+
31
+ if (input) {
32
+ logger("Scene updated");
33
+
34
+ // Add background rectangle with specified or default color
35
+ yield view.add(
36
+ <Rect
37
+ fill={input.backgroundColor ?? DEFAULT_BACKGROUND_COLOR}
38
+ size={"100%"}
39
+ />
40
+ );
41
+
42
+ // Process timeline elements if present
43
+ if (input.timeline) {
44
+ const movie = [];
45
+ let index = 1;
46
+
47
+ // Iterate through each timeline element and create appropriate visualization
48
+ for (const timeline of input.timeline) {
49
+ switch (timeline.type) {
50
+ case TIMELINE_TYPES.VIDEO:
51
+ movie.push(makeVideoTimeline({ view, timeline }));
52
+ break;
53
+ case TIMELINE_TYPES.AUDIO:
54
+ movie.push(makeAudioTimeline({ view, timeline }));
55
+ break;
56
+ case TIMELINE_TYPES.CAPTION:
57
+ movie.push(
58
+ makeCaptionTimeline({
59
+ view,
60
+ timeline,
61
+ })
62
+ );
63
+ break;
64
+ case TIMELINE_TYPES.SCENE:
65
+ movie.push(makeSceneTimeline({ view, timeline }));
66
+ break;
67
+ case TIMELINE_TYPES.ELEMENT:
68
+ movie.push(makeElementTimeline({ view, timeline }));
69
+ break;
70
+ }
71
+ index++;
72
+ }
73
+
74
+ // Execute all timeline animations in parallel
75
+ yield* all(...movie);
76
+ }
77
+ }
78
+ });
package/tsconfig.json ADDED
@@ -0,0 +1,10 @@
1
+ {
2
+ "extends": "@revideo/2d/tsconfig.project.json",
3
+ "include": ["src"],
4
+ "compilerOptions": {
5
+ "noEmit": false,
6
+ "outDir": "dist",
7
+ "module": "CommonJS",
8
+ "skipLibCheck": true
9
+ }
10
+ }
package/typedoc.json ADDED
@@ -0,0 +1,15 @@
1
+ {
2
+ "$schema": "https://typedoc.org/schema.json",
3
+ "entryPoints": ["./src/index.ts"],
4
+ "out": "docs",
5
+ "name": "@twick/visualizer",
6
+ "excludePrivate": true,
7
+ "excludeProtected": true,
8
+ "excludeExternals": true,
9
+ "theme": "default",
10
+ "readme": "README.md",
11
+ "plugin": ["typedoc-plugin-markdown"],
12
+ "categorizeByGroup": true,
13
+ "categoryOrder": ["Core", "Utils", "*"],
14
+ "hideBreadcrumbs": true
15
+ }
package/vite.config.ts ADDED
@@ -0,0 +1,15 @@
1
+ import { defineConfig } from "vite";
2
+ import motionCanvas from '@revideo/vite-plugin';
3
+
4
+ export default defineConfig({
5
+ plugins: [motionCanvas()],
6
+ build: {
7
+ rollupOptions: {
8
+ output: {
9
+ entryFileNames: '[name].js',
10
+ chunkFileNames: '[name].js',
11
+ assetFileNames: '[name].[ext]'
12
+ }
13
+ }
14
+ }
15
+ });