@gannochenko/staticstripes 0.0.23 → 0.0.24
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/Makefile +8 -0
- package/dist/ffmpeg.d.ts +32 -0
- package/dist/ffmpeg.d.ts.map +1 -1
- package/dist/ffmpeg.js +118 -0
- package/dist/ffmpeg.js.map +1 -1
- package/dist/html-project-parser.d.ts +16 -0
- package/dist/html-project-parser.d.ts.map +1 -1
- package/dist/html-project-parser.js +204 -0
- package/dist/html-project-parser.js.map +1 -1
- package/dist/sample-sequences.d.ts.map +1 -1
- package/dist/sample-sequences.js +286 -0
- package/dist/sample-sequences.js.map +1 -1
- package/dist/sequence.d.ts.map +1 -1
- package/dist/sequence.js +28 -2
- package/dist/sequence.js.map +1 -1
- package/dist/stream.d.ts +17 -0
- package/dist/stream.d.ts.map +1 -1
- package/dist/stream.js +28 -0
- package/dist/stream.js.map +1 -1
- package/dist/type.d.ts +11 -1
- package/dist/type.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/ffmpeg.ts +161 -0
- package/src/html-project-parser.ts +238 -2
- package/src/sample-sequences.ts +293 -0
- package/src/sequence.ts +28 -2
- package/src/stream.ts +50 -0
- package/src/type.ts +11 -1
package/src/sample-sequences.ts
CHANGED
|
@@ -36,6 +36,16 @@ export const getSampleSequences = (
|
|
|
36
36
|
objectFitContainAmbientBrightness: -0.1,
|
|
37
37
|
objectFitContainAmbientSaturation: 0.7,
|
|
38
38
|
objectFitContainPillarboxColor: '#000000',
|
|
39
|
+
objectFitKenBurns: 'zoom-in' as const,
|
|
40
|
+
objectFitKenBurnsZoom: 30,
|
|
41
|
+
objectFitKenBurnsEffectDuration: 0,
|
|
42
|
+
objectFitKenBurnsEasing: 'linear' as const,
|
|
43
|
+
objectFitKenBurnsFocalX: 50,
|
|
44
|
+
objectFitKenBurnsFocalY: 50,
|
|
45
|
+
objectFitKenBurnsPanStartX: 0,
|
|
46
|
+
objectFitKenBurnsPanStartY: 0,
|
|
47
|
+
objectFitKenBurnsPanEndX: 100,
|
|
48
|
+
objectFitKenBurnsPanEndY: 100,
|
|
39
49
|
chromakey: false,
|
|
40
50
|
chromakeyBlend: 0.1,
|
|
41
51
|
sound: 'on' as const,
|
|
@@ -60,6 +70,16 @@ export const getSampleSequences = (
|
|
|
60
70
|
objectFitContainAmbientBrightness: -0.1,
|
|
61
71
|
objectFitContainAmbientSaturation: 0.7,
|
|
62
72
|
objectFitContainPillarboxColor: '#000000',
|
|
73
|
+
objectFitKenBurns: 'zoom-in' as const,
|
|
74
|
+
objectFitKenBurnsZoom: 30,
|
|
75
|
+
objectFitKenBurnsEffectDuration: 0,
|
|
76
|
+
objectFitKenBurnsEasing: 'linear' as const,
|
|
77
|
+
objectFitKenBurnsFocalX: 50,
|
|
78
|
+
objectFitKenBurnsFocalY: 50,
|
|
79
|
+
objectFitKenBurnsPanStartX: 0,
|
|
80
|
+
objectFitKenBurnsPanStartY: 0,
|
|
81
|
+
objectFitKenBurnsPanEndX: 100,
|
|
82
|
+
objectFitKenBurnsPanEndY: 100,
|
|
63
83
|
chromakey: false,
|
|
64
84
|
chromakeyBlend: 0.1,
|
|
65
85
|
sound: 'on' as const,
|
|
@@ -84,6 +104,16 @@ export const getSampleSequences = (
|
|
|
84
104
|
objectFitContainAmbientBrightness: -0.1,
|
|
85
105
|
objectFitContainAmbientSaturation: 0.7,
|
|
86
106
|
objectFitContainPillarboxColor: '#000000',
|
|
107
|
+
objectFitKenBurns: 'zoom-in' as const,
|
|
108
|
+
objectFitKenBurnsZoom: 30,
|
|
109
|
+
objectFitKenBurnsEffectDuration: 0,
|
|
110
|
+
objectFitKenBurnsEasing: 'linear' as const,
|
|
111
|
+
objectFitKenBurnsFocalX: 50,
|
|
112
|
+
objectFitKenBurnsFocalY: 50,
|
|
113
|
+
objectFitKenBurnsPanStartX: 0,
|
|
114
|
+
objectFitKenBurnsPanStartY: 0,
|
|
115
|
+
objectFitKenBurnsPanEndX: 100,
|
|
116
|
+
objectFitKenBurnsPanEndY: 100,
|
|
87
117
|
chromakey: true,
|
|
88
118
|
chromakeyBlend: 0.1,
|
|
89
119
|
chromakeySimilarity: 0.1,
|
|
@@ -108,6 +138,16 @@ export const getSampleSequences = (
|
|
|
108
138
|
objectFitContainAmbientBrightness: -0.1,
|
|
109
139
|
objectFitContainAmbientSaturation: 0.7,
|
|
110
140
|
objectFitContainPillarboxColor: '#000000',
|
|
141
|
+
objectFitKenBurns: 'zoom-in' as const,
|
|
142
|
+
objectFitKenBurnsZoom: 30,
|
|
143
|
+
objectFitKenBurnsEffectDuration: 0,
|
|
144
|
+
objectFitKenBurnsEasing: 'linear' as const,
|
|
145
|
+
objectFitKenBurnsFocalX: 50,
|
|
146
|
+
objectFitKenBurnsFocalY: 50,
|
|
147
|
+
objectFitKenBurnsPanStartX: 0,
|
|
148
|
+
objectFitKenBurnsPanStartY: 0,
|
|
149
|
+
objectFitKenBurnsPanEndX: 100,
|
|
150
|
+
objectFitKenBurnsPanEndY: 100,
|
|
111
151
|
chromakey: false,
|
|
112
152
|
chromakeyBlend: 0.1,
|
|
113
153
|
sound: 'on' as const,
|
|
@@ -132,6 +172,16 @@ export const getSampleSequences = (
|
|
|
132
172
|
objectFitContainAmbientBrightness: -0.1,
|
|
133
173
|
objectFitContainAmbientSaturation: 0.7,
|
|
134
174
|
objectFitContainPillarboxColor: '#000000',
|
|
175
|
+
objectFitKenBurns: 'zoom-in' as const,
|
|
176
|
+
objectFitKenBurnsZoom: 30,
|
|
177
|
+
objectFitKenBurnsEffectDuration: 0,
|
|
178
|
+
objectFitKenBurnsEasing: 'linear' as const,
|
|
179
|
+
objectFitKenBurnsFocalX: 50,
|
|
180
|
+
objectFitKenBurnsFocalY: 50,
|
|
181
|
+
objectFitKenBurnsPanStartX: 0,
|
|
182
|
+
objectFitKenBurnsPanStartY: 0,
|
|
183
|
+
objectFitKenBurnsPanEndX: 100,
|
|
184
|
+
objectFitKenBurnsPanEndY: 100,
|
|
135
185
|
chromakey: false,
|
|
136
186
|
chromakeyBlend: 0.1,
|
|
137
187
|
sound: 'on' as const,
|
|
@@ -168,6 +218,16 @@ export const getSampleSequences = (
|
|
|
168
218
|
objectFitContainAmbientBrightness: -0.1,
|
|
169
219
|
objectFitContainAmbientSaturation: 0.7,
|
|
170
220
|
objectFitContainPillarboxColor: '#000000',
|
|
221
|
+
objectFitKenBurns: 'zoom-in' as const,
|
|
222
|
+
objectFitKenBurnsZoom: 30,
|
|
223
|
+
objectFitKenBurnsEffectDuration: 0,
|
|
224
|
+
objectFitKenBurnsEasing: 'linear' as const,
|
|
225
|
+
objectFitKenBurnsFocalX: 50,
|
|
226
|
+
objectFitKenBurnsFocalY: 50,
|
|
227
|
+
objectFitKenBurnsPanStartX: 0,
|
|
228
|
+
objectFitKenBurnsPanStartY: 0,
|
|
229
|
+
objectFitKenBurnsPanEndX: 100,
|
|
230
|
+
objectFitKenBurnsPanEndY: 100,
|
|
171
231
|
chromakey: false,
|
|
172
232
|
chromakeyBlend: 0.1,
|
|
173
233
|
sound: 'on' as const,
|
|
@@ -204,6 +264,16 @@ export const getSampleSequences = (
|
|
|
204
264
|
objectFitContainAmbientBrightness: -0.1,
|
|
205
265
|
objectFitContainAmbientSaturation: 0.7,
|
|
206
266
|
objectFitContainPillarboxColor: '#000000',
|
|
267
|
+
objectFitKenBurns: 'zoom-in' as const,
|
|
268
|
+
objectFitKenBurnsZoom: 30,
|
|
269
|
+
objectFitKenBurnsEffectDuration: 0,
|
|
270
|
+
objectFitKenBurnsEasing: 'linear' as const,
|
|
271
|
+
objectFitKenBurnsFocalX: 50,
|
|
272
|
+
objectFitKenBurnsFocalY: 50,
|
|
273
|
+
objectFitKenBurnsPanStartX: 0,
|
|
274
|
+
objectFitKenBurnsPanStartY: 0,
|
|
275
|
+
objectFitKenBurnsPanEndX: 100,
|
|
276
|
+
objectFitKenBurnsPanEndY: 100,
|
|
207
277
|
chromakey: false,
|
|
208
278
|
chromakeyBlend: 0.1,
|
|
209
279
|
sound: 'on' as const,
|
|
@@ -218,6 +288,229 @@ export const getSampleSequences = (
|
|
|
218
288
|
);
|
|
219
289
|
seq3.build();
|
|
220
290
|
|
|
291
|
+
// Ken Burns effect test sequence - using intro_image for all effect types
|
|
292
|
+
const seq4 = new Sequence(
|
|
293
|
+
buf,
|
|
294
|
+
{
|
|
295
|
+
fragments: [
|
|
296
|
+
// zoom-in effect with custom focal point
|
|
297
|
+
{
|
|
298
|
+
id: 'kb_zoom_in',
|
|
299
|
+
enabled: true,
|
|
300
|
+
assetName: 'intro_image',
|
|
301
|
+
duration: 3000,
|
|
302
|
+
trimLeft: 0,
|
|
303
|
+
overlayLeft: 0,
|
|
304
|
+
overlayZIndex: 1,
|
|
305
|
+
transitionIn: '',
|
|
306
|
+
transitionInDuration: 0,
|
|
307
|
+
transitionOut: '',
|
|
308
|
+
transitionOutDuration: 0,
|
|
309
|
+
objectFit: 'ken-burns',
|
|
310
|
+
objectFitContain: 'ambient',
|
|
311
|
+
objectFitContainAmbientBlurStrength: 25,
|
|
312
|
+
objectFitContainAmbientBrightness: -0.1,
|
|
313
|
+
objectFitContainAmbientSaturation: 0.7,
|
|
314
|
+
objectFitContainPillarboxColor: '#000000',
|
|
315
|
+
objectFitKenBurns: 'zoom-in' as const,
|
|
316
|
+
objectFitKenBurnsZoom: 50,
|
|
317
|
+
objectFitKenBurnsEffectDuration: 1000,
|
|
318
|
+
objectFitKenBurnsEasing: 'ease-in-out' as const,
|
|
319
|
+
objectFitKenBurnsFocalX: 30,
|
|
320
|
+
objectFitKenBurnsFocalY: 40,
|
|
321
|
+
objectFitKenBurnsPanStartX: 0,
|
|
322
|
+
objectFitKenBurnsPanStartY: 0,
|
|
323
|
+
objectFitKenBurnsPanEndX: 100,
|
|
324
|
+
objectFitKenBurnsPanEndY: 100,
|
|
325
|
+
chromakey: false,
|
|
326
|
+
chromakeyBlend: 0.1,
|
|
327
|
+
sound: 'on' as const,
|
|
328
|
+
chromakeySimilarity: 0.1,
|
|
329
|
+
chromakeyColor: '#000000',
|
|
330
|
+
},
|
|
331
|
+
// zoom-out effect with center focal point
|
|
332
|
+
{
|
|
333
|
+
id: 'kb_zoom_out',
|
|
334
|
+
enabled: true,
|
|
335
|
+
assetName: 'intro_image',
|
|
336
|
+
duration: 3000,
|
|
337
|
+
trimLeft: 0,
|
|
338
|
+
overlayLeft: 0,
|
|
339
|
+
overlayZIndex: 1,
|
|
340
|
+
transitionIn: '',
|
|
341
|
+
transitionInDuration: 0,
|
|
342
|
+
transitionOut: '',
|
|
343
|
+
transitionOutDuration: 0,
|
|
344
|
+
objectFit: 'ken-burns',
|
|
345
|
+
objectFitContain: 'ambient',
|
|
346
|
+
objectFitContainAmbientBlurStrength: 25,
|
|
347
|
+
objectFitContainAmbientBrightness: -0.1,
|
|
348
|
+
objectFitContainAmbientSaturation: 0.7,
|
|
349
|
+
objectFitContainPillarboxColor: '#000000',
|
|
350
|
+
objectFitKenBurns: 'zoom-out' as const,
|
|
351
|
+
objectFitKenBurnsZoom: 40,
|
|
352
|
+
objectFitKenBurnsEffectDuration: 2000,
|
|
353
|
+
objectFitKenBurnsEasing: 'ease-in' as const,
|
|
354
|
+
objectFitKenBurnsFocalX: 50,
|
|
355
|
+
objectFitKenBurnsFocalY: 50,
|
|
356
|
+
objectFitKenBurnsPanStartX: 0,
|
|
357
|
+
objectFitKenBurnsPanStartY: 0,
|
|
358
|
+
objectFitKenBurnsPanEndX: 100,
|
|
359
|
+
objectFitKenBurnsPanEndY: 100,
|
|
360
|
+
chromakey: false,
|
|
361
|
+
chromakeyBlend: 0.1,
|
|
362
|
+
sound: 'on' as const,
|
|
363
|
+
chromakeySimilarity: 0.1,
|
|
364
|
+
chromakeyColor: '#000000',
|
|
365
|
+
},
|
|
366
|
+
// pan-left effect
|
|
367
|
+
{
|
|
368
|
+
id: 'kb_pan_left',
|
|
369
|
+
enabled: true,
|
|
370
|
+
assetName: 'intro_image',
|
|
371
|
+
duration: 3000,
|
|
372
|
+
trimLeft: 0,
|
|
373
|
+
overlayLeft: 0,
|
|
374
|
+
overlayZIndex: 1,
|
|
375
|
+
transitionIn: '',
|
|
376
|
+
transitionInDuration: 0,
|
|
377
|
+
transitionOut: '',
|
|
378
|
+
transitionOutDuration: 0,
|
|
379
|
+
objectFit: 'ken-burns',
|
|
380
|
+
objectFitContain: 'ambient',
|
|
381
|
+
objectFitContainAmbientBlurStrength: 25,
|
|
382
|
+
objectFitContainAmbientBrightness: -0.1,
|
|
383
|
+
objectFitContainAmbientSaturation: 0.7,
|
|
384
|
+
objectFitContainPillarboxColor: '#000000',
|
|
385
|
+
objectFitKenBurns: 'pan-left' as const,
|
|
386
|
+
objectFitKenBurnsZoom: 30,
|
|
387
|
+
objectFitKenBurnsEffectDuration: 1500,
|
|
388
|
+
objectFitKenBurnsEasing: 'linear' as const,
|
|
389
|
+
objectFitKenBurnsFocalX: 50,
|
|
390
|
+
objectFitKenBurnsFocalY: 50,
|
|
391
|
+
objectFitKenBurnsPanStartX: 0,
|
|
392
|
+
objectFitKenBurnsPanStartY: 0,
|
|
393
|
+
objectFitKenBurnsPanEndX: 100,
|
|
394
|
+
objectFitKenBurnsPanEndY: 100,
|
|
395
|
+
chromakey: false,
|
|
396
|
+
chromakeyBlend: 0.1,
|
|
397
|
+
sound: 'on' as const,
|
|
398
|
+
chromakeySimilarity: 0.1,
|
|
399
|
+
chromakeyColor: '#000000',
|
|
400
|
+
},
|
|
401
|
+
// pan-right effect
|
|
402
|
+
{
|
|
403
|
+
id: 'kb_pan_right',
|
|
404
|
+
enabled: true,
|
|
405
|
+
assetName: 'intro_image',
|
|
406
|
+
duration: 3000,
|
|
407
|
+
trimLeft: 0,
|
|
408
|
+
overlayLeft: 0,
|
|
409
|
+
overlayZIndex: 1,
|
|
410
|
+
transitionIn: '',
|
|
411
|
+
transitionInDuration: 0,
|
|
412
|
+
transitionOut: '',
|
|
413
|
+
transitionOutDuration: 0,
|
|
414
|
+
objectFit: 'ken-burns',
|
|
415
|
+
objectFitContain: 'ambient',
|
|
416
|
+
objectFitContainAmbientBlurStrength: 25,
|
|
417
|
+
objectFitContainAmbientBrightness: -0.1,
|
|
418
|
+
objectFitContainAmbientSaturation: 0.7,
|
|
419
|
+
objectFitContainPillarboxColor: '#000000',
|
|
420
|
+
objectFitKenBurns: 'pan-right' as const,
|
|
421
|
+
objectFitKenBurnsZoom: 50,
|
|
422
|
+
objectFitKenBurnsEffectDuration: 1500,
|
|
423
|
+
objectFitKenBurnsEasing: 'ease-out' as const,
|
|
424
|
+
objectFitKenBurnsFocalX: 50,
|
|
425
|
+
objectFitKenBurnsFocalY: 50,
|
|
426
|
+
objectFitKenBurnsPanStartX: 0,
|
|
427
|
+
objectFitKenBurnsPanStartY: 0,
|
|
428
|
+
objectFitKenBurnsPanEndX: 100,
|
|
429
|
+
objectFitKenBurnsPanEndY: 100,
|
|
430
|
+
chromakey: false,
|
|
431
|
+
chromakeyBlend: 0.1,
|
|
432
|
+
sound: 'on' as const,
|
|
433
|
+
chromakeySimilarity: 0.1,
|
|
434
|
+
chromakeyColor: '#000000',
|
|
435
|
+
},
|
|
436
|
+
// pan-top effect
|
|
437
|
+
{
|
|
438
|
+
id: 'kb_pan_top',
|
|
439
|
+
enabled: true,
|
|
440
|
+
assetName: 'intro_image',
|
|
441
|
+
duration: 3000,
|
|
442
|
+
trimLeft: 0,
|
|
443
|
+
overlayLeft: 0,
|
|
444
|
+
overlayZIndex: 1,
|
|
445
|
+
transitionIn: '',
|
|
446
|
+
transitionInDuration: 0,
|
|
447
|
+
transitionOut: '',
|
|
448
|
+
transitionOutDuration: 0,
|
|
449
|
+
objectFit: 'ken-burns',
|
|
450
|
+
objectFitContain: 'ambient',
|
|
451
|
+
objectFitContainAmbientBlurStrength: 25,
|
|
452
|
+
objectFitContainAmbientBrightness: -0.1,
|
|
453
|
+
objectFitContainAmbientSaturation: 0.7,
|
|
454
|
+
objectFitContainPillarboxColor: '#000000',
|
|
455
|
+
objectFitKenBurns: 'pan-top' as const,
|
|
456
|
+
objectFitKenBurnsZoom: 30,
|
|
457
|
+
objectFitKenBurnsEffectDuration: 1500,
|
|
458
|
+
objectFitKenBurnsEasing: 'ease-in' as const,
|
|
459
|
+
objectFitKenBurnsFocalX: 50,
|
|
460
|
+
objectFitKenBurnsFocalY: 50,
|
|
461
|
+
objectFitKenBurnsPanStartX: 0,
|
|
462
|
+
objectFitKenBurnsPanStartY: 0,
|
|
463
|
+
objectFitKenBurnsPanEndX: 100,
|
|
464
|
+
objectFitKenBurnsPanEndY: 100,
|
|
465
|
+
chromakey: false,
|
|
466
|
+
chromakeyBlend: 0.1,
|
|
467
|
+
sound: 'on' as const,
|
|
468
|
+
chromakeySimilarity: 0.1,
|
|
469
|
+
chromakeyColor: '#000000',
|
|
470
|
+
},
|
|
471
|
+
// pan-bottom effect
|
|
472
|
+
{
|
|
473
|
+
id: 'kb_pan_bottom',
|
|
474
|
+
enabled: true,
|
|
475
|
+
assetName: 'intro_image',
|
|
476
|
+
duration: 3000,
|
|
477
|
+
trimLeft: 0,
|
|
478
|
+
overlayLeft: 0,
|
|
479
|
+
overlayZIndex: 1,
|
|
480
|
+
transitionIn: '',
|
|
481
|
+
transitionInDuration: 0,
|
|
482
|
+
transitionOut: '',
|
|
483
|
+
transitionOutDuration: 0,
|
|
484
|
+
objectFit: 'ken-burns',
|
|
485
|
+
objectFitContain: 'ambient',
|
|
486
|
+
objectFitContainAmbientBlurStrength: 25,
|
|
487
|
+
objectFitContainAmbientBrightness: -0.1,
|
|
488
|
+
objectFitContainAmbientSaturation: 0.7,
|
|
489
|
+
objectFitContainPillarboxColor: '#000000',
|
|
490
|
+
objectFitKenBurns: 'pan-bottom' as const,
|
|
491
|
+
objectFitKenBurnsZoom: 40,
|
|
492
|
+
objectFitKenBurnsEffectDuration: 1500,
|
|
493
|
+
objectFitKenBurnsEasing: 'ease-in-out' as const,
|
|
494
|
+
objectFitKenBurnsFocalX: 50,
|
|
495
|
+
objectFitKenBurnsFocalY: 50,
|
|
496
|
+
objectFitKenBurnsPanStartX: 0,
|
|
497
|
+
objectFitKenBurnsPanStartY: 0,
|
|
498
|
+
objectFitKenBurnsPanEndX: 100,
|
|
499
|
+
objectFitKenBurnsPanEndY: 100,
|
|
500
|
+
chromakey: false,
|
|
501
|
+
chromakeyBlend: 0.1,
|
|
502
|
+
sound: 'on' as const,
|
|
503
|
+
chromakeySimilarity: 0.1,
|
|
504
|
+
chromakeyColor: '#000000',
|
|
505
|
+
},
|
|
506
|
+
],
|
|
507
|
+
},
|
|
508
|
+
output,
|
|
509
|
+
project.getAssetManager(),
|
|
510
|
+
expressionContext,
|
|
511
|
+
);
|
|
512
|
+
seq4.build();
|
|
513
|
+
|
|
221
514
|
seq1.overlayWith(seq2);
|
|
222
515
|
seq1.overlayWith(seq3);
|
|
223
516
|
|
package/src/sequence.ts
CHANGED
|
@@ -122,6 +122,12 @@ export class Sequence {
|
|
|
122
122
|
}
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
+
// Convert deprecated JPEG pixel format (yuvj420p) to standard yuv420p early
|
|
126
|
+
// This prevents swscaler warnings from appearing in all subsequent filters
|
|
127
|
+
if (asset.hasVideo && asset.type === 'image') {
|
|
128
|
+
currentVideoStream.convertPixelFormat('yuv420p');
|
|
129
|
+
}
|
|
130
|
+
|
|
125
131
|
// Apply visual filter early for static images (before padding/cloning)
|
|
126
132
|
// This is more efficient as ffmpeg processes the filter once, then clones the filtered frame
|
|
127
133
|
if (
|
|
@@ -135,9 +141,11 @@ export class Sequence {
|
|
|
135
141
|
if (
|
|
136
142
|
asset.duration === 0 &&
|
|
137
143
|
calculatedDuration > 0 &&
|
|
138
|
-
asset.type === 'image'
|
|
144
|
+
asset.type === 'image' &&
|
|
145
|
+
fragment.objectFit !== 'ken-burns'
|
|
139
146
|
) {
|
|
140
147
|
// special case for images - extend static image to desired duration
|
|
148
|
+
// Skip tpad for Ken Burns - zoompan will generate the frames
|
|
141
149
|
currentVideoStream.tPad({
|
|
142
150
|
start: calculatedDuration,
|
|
143
151
|
startMode: 'clone',
|
|
@@ -150,7 +158,25 @@ export class Sequence {
|
|
|
150
158
|
currentVideoStream.fps(this.output.fps);
|
|
151
159
|
|
|
152
160
|
// fitting the video stream into the output frame
|
|
153
|
-
if (fragment.objectFit === '
|
|
161
|
+
if (fragment.objectFit === 'ken-burns') {
|
|
162
|
+
// Ken Burns effect (zoom/pan)
|
|
163
|
+
currentVideoStream.kenBurns({
|
|
164
|
+
effect: fragment.objectFitKenBurns,
|
|
165
|
+
zoom: fragment.objectFitKenBurnsZoom,
|
|
166
|
+
effectDuration: fragment.objectFitKenBurnsEffectDuration,
|
|
167
|
+
fragmentDuration: calculatedDuration,
|
|
168
|
+
easing: fragment.objectFitKenBurnsEasing,
|
|
169
|
+
width: this.output.resolution.width,
|
|
170
|
+
height: this.output.resolution.height,
|
|
171
|
+
fps: this.output.fps,
|
|
172
|
+
focalX: fragment.objectFitKenBurnsFocalX,
|
|
173
|
+
focalY: fragment.objectFitKenBurnsFocalY,
|
|
174
|
+
panStartX: fragment.objectFitKenBurnsPanStartX,
|
|
175
|
+
panStartY: fragment.objectFitKenBurnsPanStartY,
|
|
176
|
+
panEndX: fragment.objectFitKenBurnsPanEndX,
|
|
177
|
+
panEndY: fragment.objectFitKenBurnsPanEndY,
|
|
178
|
+
});
|
|
179
|
+
} else if (fragment.objectFit === 'cover') {
|
|
154
180
|
currentVideoStream.fitOutputCover(this.output.resolution);
|
|
155
181
|
} else {
|
|
156
182
|
const options: ObjectFitContainOptions = {};
|
package/src/stream.ts
CHANGED
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
Millisecond,
|
|
5
5
|
makeNull,
|
|
6
6
|
makeFps,
|
|
7
|
+
makeFormat,
|
|
7
8
|
makeTranspose,
|
|
8
9
|
makeTrim,
|
|
9
10
|
makeTPad,
|
|
@@ -17,6 +18,7 @@ import {
|
|
|
17
18
|
makeOverlay,
|
|
18
19
|
makeEq,
|
|
19
20
|
makeChromakey,
|
|
21
|
+
makeKenBurns,
|
|
20
22
|
makeConcat,
|
|
21
23
|
makeFade,
|
|
22
24
|
makeAmix,
|
|
@@ -311,6 +313,45 @@ export class Stream {
|
|
|
311
313
|
return this;
|
|
312
314
|
}
|
|
313
315
|
|
|
316
|
+
public kenBurns(parameters: {
|
|
317
|
+
effect: 'zoom-in' | 'zoom-out' | 'pan-left' | 'pan-right' | 'pan-top' | 'pan-bottom';
|
|
318
|
+
zoom: number;
|
|
319
|
+
effectDuration: number;
|
|
320
|
+
fragmentDuration: number;
|
|
321
|
+
easing: 'linear' | 'ease-in' | 'ease-out' | 'ease-in-out';
|
|
322
|
+
width: number;
|
|
323
|
+
height: number;
|
|
324
|
+
fps: number;
|
|
325
|
+
focalX?: number;
|
|
326
|
+
focalY?: number;
|
|
327
|
+
panStartX?: number;
|
|
328
|
+
panStartY?: number;
|
|
329
|
+
panEndX?: number;
|
|
330
|
+
panEndY?: number;
|
|
331
|
+
}): Stream {
|
|
332
|
+
// Apply Ken Burns effect
|
|
333
|
+
const kenBurnsRes = makeKenBurns([this.looseEnd], {
|
|
334
|
+
effect: parameters.effect,
|
|
335
|
+
zoom: parameters.zoom,
|
|
336
|
+
effectDuration: parameters.effectDuration,
|
|
337
|
+
fragmentDuration: parameters.fragmentDuration,
|
|
338
|
+
easing: parameters.easing,
|
|
339
|
+
width: parameters.width,
|
|
340
|
+
height: parameters.height,
|
|
341
|
+
fps: parameters.fps,
|
|
342
|
+
focalX: parameters.focalX,
|
|
343
|
+
focalY: parameters.focalY,
|
|
344
|
+
panStartX: parameters.panStartX,
|
|
345
|
+
panStartY: parameters.panStartY,
|
|
346
|
+
panEndX: parameters.panEndX,
|
|
347
|
+
panEndY: parameters.panEndY,
|
|
348
|
+
});
|
|
349
|
+
this.looseEnd = kenBurnsRes.outputs[0];
|
|
350
|
+
this.buf.append(kenBurnsRes);
|
|
351
|
+
|
|
352
|
+
return this;
|
|
353
|
+
}
|
|
354
|
+
|
|
314
355
|
public fps(value: number): Stream {
|
|
315
356
|
const res = makeFps([this.looseEnd], value);
|
|
316
357
|
this.looseEnd = res.outputs[0];
|
|
@@ -320,6 +361,15 @@ export class Stream {
|
|
|
320
361
|
return this;
|
|
321
362
|
}
|
|
322
363
|
|
|
364
|
+
public convertPixelFormat(format: string): Stream {
|
|
365
|
+
const res = makeFormat([this.looseEnd], format);
|
|
366
|
+
this.looseEnd = res.outputs[0];
|
|
367
|
+
|
|
368
|
+
this.buf.append(res);
|
|
369
|
+
|
|
370
|
+
return this;
|
|
371
|
+
}
|
|
372
|
+
|
|
323
373
|
public blur(strength: number): Stream {
|
|
324
374
|
const res = makeGblur([this.looseEnd], {
|
|
325
375
|
sigma: strength,
|
package/src/type.ts
CHANGED
|
@@ -55,12 +55,22 @@ export type Fragment = {
|
|
|
55
55
|
transitionInDuration: number; // how long the transition in lasts
|
|
56
56
|
transitionOut: string; // how to transition out of the fragment
|
|
57
57
|
transitionOutDuration: number; // how long the transition out lasts
|
|
58
|
-
objectFit: 'cover' | 'contain';
|
|
58
|
+
objectFit: 'cover' | 'contain' | 'ken-burns';
|
|
59
59
|
objectFitContain: 'ambient' | 'pillarbox';
|
|
60
60
|
objectFitContainAmbientBlurStrength: number;
|
|
61
61
|
objectFitContainAmbientBrightness: number;
|
|
62
62
|
objectFitContainAmbientSaturation: number;
|
|
63
63
|
objectFitContainPillarboxColor: string;
|
|
64
|
+
objectFitKenBurns: 'zoom-in' | 'zoom-out' | 'pan-left' | 'pan-right' | 'pan-top' | 'pan-bottom';
|
|
65
|
+
objectFitKenBurnsZoom: number; // zoom percentage (e.g., 30 = 30% zoom, applies to all effects)
|
|
66
|
+
objectFitKenBurnsEffectDuration: number; // duration of the ken burns effect in milliseconds
|
|
67
|
+
objectFitKenBurnsEasing: 'linear' | 'ease-in' | 'ease-out' | 'ease-in-out';
|
|
68
|
+
objectFitKenBurnsFocalX: number; // focal point X in percent (0-100, for zoom effects)
|
|
69
|
+
objectFitKenBurnsFocalY: number; // focal point Y in percent (0-100, for zoom effects)
|
|
70
|
+
objectFitKenBurnsPanStartX: number; // pan start position X in percent (0-100, for horizontal pan effects)
|
|
71
|
+
objectFitKenBurnsPanStartY: number; // pan start position Y in percent (0-100, for vertical pan effects)
|
|
72
|
+
objectFitKenBurnsPanEndX: number; // pan end position X in percent (0-100, for horizontal pan effects)
|
|
73
|
+
objectFitKenBurnsPanEndY: number; // pan end position Y in percent (0-100, for vertical pan effects)
|
|
64
74
|
chromakey: boolean;
|
|
65
75
|
chromakeyBlend: number;
|
|
66
76
|
chromakeySimilarity: number;
|