@bendyline/squisq-video-react 2.5.11 → 2.5.13
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.
|
@@ -21,6 +21,38 @@ function formatRealtimeMultiplier(processingFps, outputFps) {
|
|
|
21
21
|
function resolveVideoSaveActionLabel(format, formatter) {
|
|
22
22
|
return formatter?.(format) ?? `Save ${format.toUpperCase()} to Downloads`;
|
|
23
23
|
}
|
|
24
|
+
var VIDEO_PRESETS = [
|
|
25
|
+
{
|
|
26
|
+
id: "presentation",
|
|
27
|
+
label: "Presentation",
|
|
28
|
+
description: "Landscape video with smooth motion for presenting and sharing.",
|
|
29
|
+
quality: "normal",
|
|
30
|
+
fps: 30,
|
|
31
|
+
orientation: "landscape",
|
|
32
|
+
captionMode: "off",
|
|
33
|
+
animationsEnabled: true
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
id: "social",
|
|
37
|
+
label: "Social portrait",
|
|
38
|
+
description: "Vertical video with large captions for phone viewing.",
|
|
39
|
+
quality: "normal",
|
|
40
|
+
fps: 30,
|
|
41
|
+
orientation: "portrait",
|
|
42
|
+
captionMode: "social",
|
|
43
|
+
animationsEnabled: true
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
id: "small",
|
|
47
|
+
label: "Small file",
|
|
48
|
+
description: "Lower quality and less motion for a smaller file and faster export.",
|
|
49
|
+
quality: "draft",
|
|
50
|
+
fps: 15,
|
|
51
|
+
orientation: "landscape",
|
|
52
|
+
captionMode: "off",
|
|
53
|
+
animationsEnabled: false
|
|
54
|
+
}
|
|
55
|
+
];
|
|
24
56
|
var FRAME_PREVIEW_INTERVAL = 15;
|
|
25
57
|
var FRAME_PREVIEW_WIDTH = 480;
|
|
26
58
|
var FRAME_PREVIEW_HEIGHT = 270;
|
|
@@ -85,9 +117,13 @@ var overlayStyle = {
|
|
|
85
117
|
var modalStyle = {
|
|
86
118
|
position: "relative",
|
|
87
119
|
borderRadius: 0,
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
120
|
+
boxSizing: "border-box",
|
|
121
|
+
padding: "20px clamp(12px, 4vw, 28px)",
|
|
122
|
+
width: "min(480px, calc(100vw - 24px))",
|
|
123
|
+
minWidth: 0,
|
|
124
|
+
maxHeight: "calc(100dvh - 24px)",
|
|
125
|
+
overflowY: "auto",
|
|
126
|
+
overscrollBehavior: "contain",
|
|
91
127
|
boxShadow: "0 8px 32px rgba(0,0,0,0.18)",
|
|
92
128
|
fontFamily: "system-ui, -apple-system, sans-serif"
|
|
93
129
|
};
|
|
@@ -118,7 +154,9 @@ var labelStyle = {
|
|
|
118
154
|
marginBottom: 4
|
|
119
155
|
};
|
|
120
156
|
var selectStyle = {
|
|
157
|
+
boxSizing: "border-box",
|
|
121
158
|
width: "100%",
|
|
159
|
+
minWidth: 0,
|
|
122
160
|
padding: "6px 8px",
|
|
123
161
|
fontSize: 13,
|
|
124
162
|
fontFamily: "inherit",
|
|
@@ -150,6 +188,7 @@ var progressBarOuterStyle = {
|
|
|
150
188
|
};
|
|
151
189
|
var footerStyle = {
|
|
152
190
|
display: "flex",
|
|
191
|
+
flexWrap: "wrap",
|
|
153
192
|
justifyContent: "flex-end",
|
|
154
193
|
gap: 8,
|
|
155
194
|
marginTop: 20
|
|
@@ -187,6 +226,18 @@ function VideoExportModal({
|
|
|
187
226
|
defaultConfig?.animationsEnabled ?? initialOutputFormat === "mp4"
|
|
188
227
|
);
|
|
189
228
|
const [includeAudio, setIncludeAudio] = useState(defaultConfig?.audioPolicy !== "omit");
|
|
229
|
+
const preset = VIDEO_PRESETS.find(
|
|
230
|
+
(entry) => entry.quality === quality && entry.fps === fps && entry.orientation === orientation && entry.captionMode === captionMode && entry.animationsEnabled === animationsEnabled
|
|
231
|
+
);
|
|
232
|
+
const applyPreset = (id) => {
|
|
233
|
+
const next = VIDEO_PRESETS.find((entry) => entry.id === id);
|
|
234
|
+
if (!next) return;
|
|
235
|
+
setQuality(next.quality);
|
|
236
|
+
setFps(next.fps);
|
|
237
|
+
setOrientation(next.orientation);
|
|
238
|
+
setCaptionMode(next.captionMode);
|
|
239
|
+
setAnimationsEnabled(next.animationsEnabled);
|
|
240
|
+
};
|
|
190
241
|
const palette = {
|
|
191
242
|
...VIDEO_EXPORT_PALETTES[colorScheme],
|
|
192
243
|
...uiPalette
|
|
@@ -406,127 +457,162 @@ function VideoExportModal({
|
|
|
406
457
|
}
|
|
407
458
|
)
|
|
408
459
|
] }),
|
|
409
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
410
|
-
/* @__PURE__ */ jsx("label", { style: themedLabelStyle, children: "
|
|
411
|
-
/* @__PURE__ */ jsxs(
|
|
412
|
-
"select",
|
|
413
|
-
{
|
|
414
|
-
"aria-label": "Quality",
|
|
415
|
-
style: themedSelectStyle,
|
|
416
|
-
value: quality,
|
|
417
|
-
onChange: (e) => setQuality(e.target.value),
|
|
418
|
-
children: [
|
|
419
|
-
/* @__PURE__ */ jsx("option", { value: "draft", children: "Draft \u2014 fast, lower quality" }),
|
|
420
|
-
/* @__PURE__ */ jsx("option", { value: "normal", children: "Normal \u2014 balanced" }),
|
|
421
|
-
/* @__PURE__ */ jsx("option", { value: "high", children: "High \u2014 best quality, slower" })
|
|
422
|
-
]
|
|
423
|
-
}
|
|
424
|
-
)
|
|
425
|
-
] }),
|
|
426
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
427
|
-
/* @__PURE__ */ jsx("label", { style: themedLabelStyle, children: "Frame Rate" }),
|
|
428
|
-
/* @__PURE__ */ jsxs(
|
|
429
|
-
"select",
|
|
430
|
-
{
|
|
431
|
-
"aria-label": "Frame Rate",
|
|
432
|
-
style: themedSelectStyle,
|
|
433
|
-
value: fps,
|
|
434
|
-
onChange: (e) => setFps(Number(e.target.value)),
|
|
435
|
-
children: [
|
|
436
|
-
/* @__PURE__ */ jsx("option", { value: 10, children: "10 fps \u2014 recommended for GIF" }),
|
|
437
|
-
/* @__PURE__ */ jsx("option", { value: 15, children: "15 fps \u2014 fast export" }),
|
|
438
|
-
/* @__PURE__ */ jsx("option", { value: 24, children: "24 fps \u2014 cinematic" }),
|
|
439
|
-
/* @__PURE__ */ jsx("option", { value: 30, children: "30 fps \u2014 smooth" })
|
|
440
|
-
]
|
|
441
|
-
}
|
|
442
|
-
)
|
|
443
|
-
] }),
|
|
444
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
445
|
-
/* @__PURE__ */ jsx("label", { style: themedLabelStyle, children: "Orientation" }),
|
|
460
|
+
outputFormat === "mp4" && /* @__PURE__ */ jsxs("div", { children: [
|
|
461
|
+
/* @__PURE__ */ jsx("label", { style: themedLabelStyle, children: "Preset" }),
|
|
446
462
|
/* @__PURE__ */ jsxs(
|
|
447
463
|
"select",
|
|
448
464
|
{
|
|
449
|
-
"aria-label": "
|
|
465
|
+
"aria-label": "Preset",
|
|
450
466
|
style: themedSelectStyle,
|
|
451
|
-
value:
|
|
452
|
-
onChange: (
|
|
467
|
+
value: preset?.id ?? "custom",
|
|
468
|
+
onChange: (event) => applyPreset(event.target.value),
|
|
453
469
|
children: [
|
|
454
|
-
/* @__PURE__ */
|
|
455
|
-
|
|
456
|
-
outputFormat === "gif" ? "960 \xD7 540" : "1920 \xD7 1080",
|
|
457
|
-
")"
|
|
458
|
-
] }),
|
|
459
|
-
/* @__PURE__ */ jsxs("option", { value: "portrait", children: [
|
|
460
|
-
"Portrait (",
|
|
461
|
-
outputFormat === "gif" ? "540 \xD7 960" : "1080 \xD7 1920",
|
|
462
|
-
")"
|
|
463
|
-
] })
|
|
470
|
+
VIDEO_PRESETS.map((entry) => /* @__PURE__ */ jsx("option", { value: entry.id, children: entry.label }, entry.id)),
|
|
471
|
+
!preset && /* @__PURE__ */ jsx("option", { value: "custom", disabled: true, children: "Custom settings" })
|
|
464
472
|
]
|
|
465
473
|
}
|
|
466
|
-
)
|
|
474
|
+
),
|
|
475
|
+
/* @__PURE__ */ jsx("p", { style: { fontSize: 13, color: palette.label, margin: "0 0 12px" }, children: preset?.description ?? "Your settings are kept in Advanced options." })
|
|
467
476
|
] }),
|
|
468
|
-
/* @__PURE__ */ jsxs("
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
onChange: (e) => setCaptionMode(e.target.value),
|
|
477
|
-
children: [
|
|
478
|
-
/* @__PURE__ */ jsx("option", { value: "off", children: "None" }),
|
|
479
|
-
/* @__PURE__ */ jsx("option", { value: "standard", children: "Standard (top bar)" }),
|
|
480
|
-
/* @__PURE__ */ jsx("option", { value: "social", children: "Social media (large words)" })
|
|
481
|
-
]
|
|
482
|
-
}
|
|
483
|
-
)
|
|
477
|
+
/* @__PURE__ */ jsxs("p", { style: { fontSize: 13, color: palette.label, margin: "0 0 12px" }, children: [
|
|
478
|
+
formatDuration(Math.ceil(doc.duration)),
|
|
479
|
+
" \xB7",
|
|
480
|
+
" ",
|
|
481
|
+
orientation === "portrait" ? "Portrait" : "Landscape",
|
|
482
|
+
" \xB7",
|
|
483
|
+
" ",
|
|
484
|
+
outputFormat === "gif" || !includeAudio ? "No audio" : "Document audio enabled"
|
|
484
485
|
] }),
|
|
485
|
-
|
|
486
|
-
/* @__PURE__ */ jsx(
|
|
487
|
-
|
|
488
|
-
"label",
|
|
489
|
-
{
|
|
490
|
-
style: {
|
|
491
|
-
display: "flex",
|
|
492
|
-
alignItems: "center",
|
|
493
|
-
gap: 8,
|
|
494
|
-
marginBottom: 12,
|
|
495
|
-
fontSize: 14,
|
|
496
|
-
color: palette.text,
|
|
497
|
-
cursor: "pointer"
|
|
498
|
-
},
|
|
499
|
-
children: [
|
|
500
|
-
/* @__PURE__ */ jsx(
|
|
501
|
-
"input",
|
|
502
|
-
{
|
|
503
|
-
type: "checkbox",
|
|
504
|
-
"aria-label": "Include audio",
|
|
505
|
-
checked: includeAudio,
|
|
506
|
-
onChange: (e) => setIncludeAudio(e.target.checked)
|
|
507
|
-
}
|
|
508
|
-
),
|
|
509
|
-
"Include audio"
|
|
510
|
-
]
|
|
511
|
-
}
|
|
512
|
-
)
|
|
513
|
-
] }),
|
|
514
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
515
|
-
/* @__PURE__ */ jsx("label", { style: themedLabelStyle, children: "Animations & transitions" }),
|
|
516
|
-
/* @__PURE__ */ jsxs(
|
|
517
|
-
"select",
|
|
486
|
+
/* @__PURE__ */ jsxs("details", { children: [
|
|
487
|
+
/* @__PURE__ */ jsx(
|
|
488
|
+
"summary",
|
|
518
489
|
{
|
|
519
|
-
"
|
|
520
|
-
|
|
521
|
-
value: animationsEnabled ? "enabled" : "disabled",
|
|
522
|
-
onChange: (e) => setAnimationsEnabled(e.target.value === "enabled"),
|
|
523
|
-
children: [
|
|
524
|
-
/* @__PURE__ */ jsx("option", { value: "enabled", children: "Enabled" }),
|
|
525
|
-
/* @__PURE__ */ jsx("option", { value: "disabled", children: "Disabled \u2014 smaller files" })
|
|
526
|
-
]
|
|
490
|
+
style: { cursor: "pointer", color: palette.label, fontSize: 14, marginBottom: 12 },
|
|
491
|
+
children: "Advanced options"
|
|
527
492
|
}
|
|
528
493
|
),
|
|
529
|
-
|
|
494
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
495
|
+
/* @__PURE__ */ jsx("label", { style: themedLabelStyle, children: "Quality" }),
|
|
496
|
+
/* @__PURE__ */ jsxs(
|
|
497
|
+
"select",
|
|
498
|
+
{
|
|
499
|
+
"aria-label": "Quality",
|
|
500
|
+
style: themedSelectStyle,
|
|
501
|
+
value: quality,
|
|
502
|
+
onChange: (e) => setQuality(e.target.value),
|
|
503
|
+
children: [
|
|
504
|
+
/* @__PURE__ */ jsx("option", { value: "draft", children: "Draft \u2014 fast, lower quality" }),
|
|
505
|
+
/* @__PURE__ */ jsx("option", { value: "normal", children: "Normal \u2014 balanced" }),
|
|
506
|
+
/* @__PURE__ */ jsx("option", { value: "high", children: "High \u2014 best quality, slower" })
|
|
507
|
+
]
|
|
508
|
+
}
|
|
509
|
+
)
|
|
510
|
+
] }),
|
|
511
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
512
|
+
/* @__PURE__ */ jsx("label", { style: themedLabelStyle, children: "Frame Rate" }),
|
|
513
|
+
/* @__PURE__ */ jsxs(
|
|
514
|
+
"select",
|
|
515
|
+
{
|
|
516
|
+
"aria-label": "Frame Rate",
|
|
517
|
+
style: themedSelectStyle,
|
|
518
|
+
value: fps,
|
|
519
|
+
onChange: (e) => setFps(Number(e.target.value)),
|
|
520
|
+
children: [
|
|
521
|
+
/* @__PURE__ */ jsx("option", { value: 10, children: "10 fps \u2014 recommended for GIF" }),
|
|
522
|
+
/* @__PURE__ */ jsx("option", { value: 15, children: "15 fps \u2014 fast export" }),
|
|
523
|
+
/* @__PURE__ */ jsx("option", { value: 24, children: "24 fps \u2014 cinematic" }),
|
|
524
|
+
/* @__PURE__ */ jsx("option", { value: 30, children: "30 fps \u2014 smooth" })
|
|
525
|
+
]
|
|
526
|
+
}
|
|
527
|
+
)
|
|
528
|
+
] }),
|
|
529
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
530
|
+
/* @__PURE__ */ jsx("label", { style: themedLabelStyle, children: "Orientation" }),
|
|
531
|
+
/* @__PURE__ */ jsxs(
|
|
532
|
+
"select",
|
|
533
|
+
{
|
|
534
|
+
"aria-label": "Orientation",
|
|
535
|
+
style: themedSelectStyle,
|
|
536
|
+
value: orientation,
|
|
537
|
+
onChange: (e) => setOrientation(e.target.value),
|
|
538
|
+
children: [
|
|
539
|
+
/* @__PURE__ */ jsxs("option", { value: "landscape", children: [
|
|
540
|
+
"Landscape (",
|
|
541
|
+
outputFormat === "gif" ? "960 \xD7 540" : "1920 \xD7 1080",
|
|
542
|
+
")"
|
|
543
|
+
] }),
|
|
544
|
+
/* @__PURE__ */ jsxs("option", { value: "portrait", children: [
|
|
545
|
+
"Portrait (",
|
|
546
|
+
outputFormat === "gif" ? "540 \xD7 960" : "1080 \xD7 1920",
|
|
547
|
+
")"
|
|
548
|
+
] })
|
|
549
|
+
]
|
|
550
|
+
}
|
|
551
|
+
)
|
|
552
|
+
] }),
|
|
553
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
554
|
+
/* @__PURE__ */ jsx("label", { style: themedLabelStyle, children: "Captions" }),
|
|
555
|
+
/* @__PURE__ */ jsxs(
|
|
556
|
+
"select",
|
|
557
|
+
{
|
|
558
|
+
"aria-label": "Captions",
|
|
559
|
+
style: themedSelectStyle,
|
|
560
|
+
value: captionMode,
|
|
561
|
+
onChange: (e) => setCaptionMode(e.target.value),
|
|
562
|
+
children: [
|
|
563
|
+
/* @__PURE__ */ jsx("option", { value: "off", children: "None" }),
|
|
564
|
+
/* @__PURE__ */ jsx("option", { value: "standard", children: "Standard (top bar)" }),
|
|
565
|
+
/* @__PURE__ */ jsx("option", { value: "social", children: "Social media (large words)" })
|
|
566
|
+
]
|
|
567
|
+
}
|
|
568
|
+
)
|
|
569
|
+
] }),
|
|
570
|
+
outputFormat === "mp4" && /* @__PURE__ */ jsxs("div", { children: [
|
|
571
|
+
/* @__PURE__ */ jsx("label", { style: themedLabelStyle, children: "Audio" }),
|
|
572
|
+
/* @__PURE__ */ jsxs(
|
|
573
|
+
"label",
|
|
574
|
+
{
|
|
575
|
+
style: {
|
|
576
|
+
display: "flex",
|
|
577
|
+
alignItems: "center",
|
|
578
|
+
gap: 8,
|
|
579
|
+
marginBottom: 12,
|
|
580
|
+
fontSize: 14,
|
|
581
|
+
color: palette.text,
|
|
582
|
+
cursor: "pointer"
|
|
583
|
+
},
|
|
584
|
+
children: [
|
|
585
|
+
/* @__PURE__ */ jsx(
|
|
586
|
+
"input",
|
|
587
|
+
{
|
|
588
|
+
type: "checkbox",
|
|
589
|
+
"aria-label": "Include audio",
|
|
590
|
+
checked: includeAudio,
|
|
591
|
+
onChange: (e) => setIncludeAudio(e.target.checked)
|
|
592
|
+
}
|
|
593
|
+
),
|
|
594
|
+
"Include audio"
|
|
595
|
+
]
|
|
596
|
+
}
|
|
597
|
+
)
|
|
598
|
+
] }),
|
|
599
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
600
|
+
/* @__PURE__ */ jsx("label", { style: themedLabelStyle, children: "Animations & transitions" }),
|
|
601
|
+
/* @__PURE__ */ jsxs(
|
|
602
|
+
"select",
|
|
603
|
+
{
|
|
604
|
+
"aria-label": "Animations and transitions",
|
|
605
|
+
style: themedSelectStyle,
|
|
606
|
+
value: animationsEnabled ? "enabled" : "disabled",
|
|
607
|
+
onChange: (e) => setAnimationsEnabled(e.target.value === "enabled"),
|
|
608
|
+
children: [
|
|
609
|
+
/* @__PURE__ */ jsx("option", { value: "enabled", children: "Enabled" }),
|
|
610
|
+
/* @__PURE__ */ jsx("option", { value: "disabled", children: "Disabled \u2014 smaller files" })
|
|
611
|
+
]
|
|
612
|
+
}
|
|
613
|
+
),
|
|
614
|
+
outputFormat === "gif" && animationsEnabled && /* @__PURE__ */ jsx("p", { style: { fontSize: 12, color: palette.muted, margin: "-6px 0 12px" }, children: "Disabling motion is recommended for much smaller GIFs." })
|
|
615
|
+
] })
|
|
530
616
|
] }),
|
|
531
617
|
preparingEdits && /* @__PURE__ */ jsx(
|
|
532
618
|
"p",
|
|
@@ -650,6 +736,32 @@ function VideoExportModal({
|
|
|
650
736
|
"Video only",
|
|
651
737
|
audioSkippedReason ? ` \u2014 ${audioSkippedReason}` : ""
|
|
652
738
|
] }),
|
|
739
|
+
downloadUrl && /* @__PURE__ */ jsxs("figure", { style: { margin: "12px 0" }, children: [
|
|
740
|
+
completedOutputFormat === "gif" ? /* @__PURE__ */ jsx(
|
|
741
|
+
"img",
|
|
742
|
+
{
|
|
743
|
+
src: downloadUrl,
|
|
744
|
+
alt: "Exported animation preview",
|
|
745
|
+
style: {
|
|
746
|
+
display: "block",
|
|
747
|
+
width: "100%",
|
|
748
|
+
maxHeight: 240,
|
|
749
|
+
objectFit: "contain"
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
) : /* @__PURE__ */ jsx(
|
|
753
|
+
"video",
|
|
754
|
+
{
|
|
755
|
+
src: downloadUrl,
|
|
756
|
+
controls: true,
|
|
757
|
+
playsInline: true,
|
|
758
|
+
preload: "metadata",
|
|
759
|
+
"aria-label": "Exported video preview",
|
|
760
|
+
style: { display: "block", width: "100%", maxHeight: 240 }
|
|
761
|
+
}
|
|
762
|
+
),
|
|
763
|
+
/* @__PURE__ */ jsx("figcaption", { style: { fontSize: 12, color: palette.label, marginTop: 6 }, children: "Preview your export before saving." })
|
|
764
|
+
] }),
|
|
653
765
|
saveOptions && /* @__PURE__ */ jsx("fieldset", { disabled: saving, style: { border: 0, padding: 0, margin: "12px 0 0" }, children: saveOptions }),
|
|
654
766
|
/* @__PURE__ */ jsxs("div", { style: footerStyle, children: [
|
|
655
767
|
/* @__PURE__ */ jsx("button", { style: themedSecondaryButtonStyle, onClick: handleClose, children: "Close" }),
|
package/dist/components/index.js
CHANGED
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bendyline/squisq-video-react",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.13",
|
|
4
4
|
"description": "React components for browser-based MP4 and animated-GIF export of Squisq documents",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Bendyline",
|
|
@@ -77,9 +77,9 @@
|
|
|
77
77
|
"react-dom": "^18.0.0 || ^19.0.0"
|
|
78
78
|
},
|
|
79
79
|
"dependencies": {
|
|
80
|
-
"@bendyline/squisq": "2.13.
|
|
81
|
-
"@bendyline/squisq-video": "2.4.
|
|
82
|
-
"@bendyline/squisq-react": "2.12.
|
|
80
|
+
"@bendyline/squisq": "2.13.3",
|
|
81
|
+
"@bendyline/squisq-video": "2.4.9",
|
|
82
|
+
"@bendyline/squisq-react": "2.12.12",
|
|
83
83
|
"@ffmpeg/core": "0.12.10",
|
|
84
84
|
"@ffmpeg/ffmpeg": "0.12.15",
|
|
85
85
|
"@ffmpeg/util": "0.12.2",
|