@pixerate/editor-react 0.53.0 → 0.55.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.
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
|
|
20
30
|
// src/video-editor/index.ts
|
|
@@ -22,6 +32,7 @@ var video_editor_exports = {};
|
|
|
22
32
|
__export(video_editor_exports, {
|
|
23
33
|
ClipInspector: () => ClipInspector,
|
|
24
34
|
MediaBin: () => MediaBin,
|
|
35
|
+
TranscriptPanel: () => TranscriptPanel,
|
|
25
36
|
VideoEditor: () => VideoEditor,
|
|
26
37
|
VideoPreview: () => VideoPreview,
|
|
27
38
|
VideoTimeline: () => VideoTimeline,
|
|
@@ -548,6 +559,62 @@ function ClipInspector({ controller, className = "" }) {
|
|
|
548
559
|
),
|
|
549
560
|
row.keyed && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "shrink-0 text-[10px] tabular-nums text-muted-foreground", "data-keyframe-count": row.property, children: row.keys })
|
|
550
561
|
] }) }, row.property)),
|
|
562
|
+
at.track.kind === "video" && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Row, { label: "Blend", name: "blend", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("select", { className: field, value: clip.blend ?? "normal", disabled, "aria-label": "Blend mode", onChange: (e) => set("blend", e.target.value === "normal" ? void 0 : e.target.value, "Change blend mode"), children: import_video_editor5.VIDEO_BLEND_MODES.map((m) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: m, children: import_video_editor5.VIDEO_BLEND_MODE_LABELS[m] }, m)) }) }),
|
|
563
|
+
at.track.kind === "video" && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
564
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Row, { label: "Look", name: "gradePreset", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
565
|
+
"select",
|
|
566
|
+
{
|
|
567
|
+
className: field,
|
|
568
|
+
value: "",
|
|
569
|
+
disabled,
|
|
570
|
+
"aria-label": "Apply a look",
|
|
571
|
+
onChange: (e) => {
|
|
572
|
+
const grade = (0, import_video_editor5.videoGradePreset)(e.target.value);
|
|
573
|
+
if (grade) controller.apply({ op: "update_clip", clip: clip.id, set: { grade } }, `Apply ${e.target.value} look`);
|
|
574
|
+
},
|
|
575
|
+
children: [
|
|
576
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: "", children: clip.grade ? "Graded" : "None" }),
|
|
577
|
+
import_video_editor5.VIDEO_GRADE_PRESET_NAMES.map((name) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: name, children: name.replace(/-/g, " ") }, name))
|
|
578
|
+
]
|
|
579
|
+
}
|
|
580
|
+
) }),
|
|
581
|
+
import_video_editor5.VIDEO_GRADE_CONTROLS.map((c) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Row, { label: c.label, name: `grade.${c.key}`, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
582
|
+
Commit,
|
|
583
|
+
{
|
|
584
|
+
type: "number",
|
|
585
|
+
min: c.min,
|
|
586
|
+
max: c.max,
|
|
587
|
+
step: c.step,
|
|
588
|
+
value: clip.grade?.[c.key] === void 0 ? "" : String(clip.grade[c.key]),
|
|
589
|
+
placeholder: "0",
|
|
590
|
+
"aria-label": c.label,
|
|
591
|
+
disabled,
|
|
592
|
+
onCommit: (raw) => {
|
|
593
|
+
const n = raw.trim() ? Number(raw) : 0;
|
|
594
|
+
if (!Number.isFinite(n)) return;
|
|
595
|
+
const grade = (0, import_video_editor5.normalizeVideoGrade)({ ...clip.grade, [c.key]: n });
|
|
596
|
+
set("grade", grade, `Change ${c.label.toLowerCase()}`);
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
) }, c.key))
|
|
600
|
+
] }),
|
|
601
|
+
at.track.kind === "video" && ["animateIn", "animateOut"].map((key) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Row, { label: key === "animateIn" ? "Animate in" : "Animate out", name: key, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
602
|
+
"select",
|
|
603
|
+
{
|
|
604
|
+
className: field,
|
|
605
|
+
value: clip[key]?.effect ?? "",
|
|
606
|
+
disabled,
|
|
607
|
+
"aria-label": key === "animateIn" ? "Animate in" : "Animate out",
|
|
608
|
+
onChange: (e) => {
|
|
609
|
+
const effect = e.target.value;
|
|
610
|
+
set(key, effect ? { ...clip[key], effect } : void 0, key === "animateIn" ? "Change entrance" : "Change exit");
|
|
611
|
+
},
|
|
612
|
+
children: [
|
|
613
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: "", children: "None" }),
|
|
614
|
+
import_video_editor5.VIDEO_CLIP_ANIMATION_EFFECTS.map((effect) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: effect, children: import_video_editor5.VIDEO_CLIP_ANIMATION_LABELS[effect] }, effect))
|
|
615
|
+
]
|
|
616
|
+
}
|
|
617
|
+
) }, key)),
|
|
551
618
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Row, { label: "Fade in (ms)", name: "fadeIn", children: number("fadeIn", "Fade in", { min: 0, step: 100 }) }),
|
|
552
619
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Row, { label: "Fade out (ms)", name: "fadeOut", children: number("fadeOut", "Fade out", { min: 0, step: 100 }) }),
|
|
553
620
|
clip.type === "media" && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
@@ -593,7 +660,7 @@ function ClipInspector({ controller, className = "" }) {
|
|
|
593
660
|
},
|
|
594
661
|
children: [
|
|
595
662
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: "", children: "None" }),
|
|
596
|
-
import_video_editor5.VIDEO_TRANSITION_TYPES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: t, children: t
|
|
663
|
+
import_video_editor5.VIDEO_TRANSITION_TYPES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: t, children: import_video_editor5.VIDEO_TRANSITION_LABELS[t] }, t))
|
|
597
664
|
]
|
|
598
665
|
}
|
|
599
666
|
) }),
|
|
@@ -611,6 +678,33 @@ function ClipInspector({ controller, className = "" }) {
|
|
|
611
678
|
if (raw.trim() && Number.isFinite(n) && n > 0) controller.apply({ op: "set_transition", clip: clip.id, transition: { ...transition, duration: n } }, "Change transition length");
|
|
612
679
|
}
|
|
613
680
|
}
|
|
681
|
+
) }),
|
|
682
|
+
transition && (0, import_video_editor5.videoTransitionHasDirection)(transition.type) && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Row, { label: "Direction", name: "transitionDirection", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
683
|
+
"select",
|
|
684
|
+
{
|
|
685
|
+
className: field,
|
|
686
|
+
value: transition.direction ?? "right",
|
|
687
|
+
disabled,
|
|
688
|
+
"aria-label": "Transition direction",
|
|
689
|
+
onChange: (e) => controller.apply({ op: "set_transition", clip: clip.id, transition: { ...transition, direction: e.target.value } }, "Change transition direction"),
|
|
690
|
+
children: import_video_editor5.VIDEO_WIPE_DIRECTIONS.map((d) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: d, children: d }, d))
|
|
691
|
+
}
|
|
692
|
+
) }),
|
|
693
|
+
transition && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Row, { label: "Transition sound", name: "transitionAudioCurve", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
694
|
+
"select",
|
|
695
|
+
{
|
|
696
|
+
className: field,
|
|
697
|
+
value: (0, import_video_editor5.videoTransitionAudioCurve)(transition),
|
|
698
|
+
disabled,
|
|
699
|
+
"aria-label": "Transition sound curve",
|
|
700
|
+
onChange: (e) => {
|
|
701
|
+
const { audioCurve: _, ...rest } = transition;
|
|
702
|
+
const curve = e.target.value;
|
|
703
|
+
const next = curve === (0, import_video_editor5.videoTransitionAudioCurve)(rest) ? rest : { ...rest, audioCurve: curve };
|
|
704
|
+
controller.apply({ op: "set_transition", clip: clip.id, transition: next }, "Change transition sound");
|
|
705
|
+
},
|
|
706
|
+
children: import_video_editor5.VIDEO_FADE_CURVES.map((c) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: c, children: import_video_editor5.VIDEO_FADE_CURVE_LABELS[c] }, c))
|
|
707
|
+
}
|
|
614
708
|
) })
|
|
615
709
|
] });
|
|
616
710
|
}
|
|
@@ -761,29 +855,134 @@ function MediaBin({ controller, editable = true, fileToUrl, probe = import_video
|
|
|
761
855
|
);
|
|
762
856
|
}
|
|
763
857
|
|
|
764
|
-
// src/video-editor/
|
|
765
|
-
var import_react5 = require("react");
|
|
858
|
+
// src/video-editor/TranscriptPanel.tsx
|
|
859
|
+
var import_react5 = __toESM(require("react"), 1);
|
|
860
|
+
var import_video_editor7 = require("@pixerate/editor/video-editor");
|
|
766
861
|
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
767
|
-
|
|
862
|
+
var btn3 = "rounded border border-border px-1.5 py-0.5 text-[11px] disabled:opacity-40";
|
|
863
|
+
function TranscriptPanel({ controller, track, editable = true, className = "" }) {
|
|
864
|
+
const state = useVideoEditorState(controller);
|
|
865
|
+
const { project, time, readOnly } = state;
|
|
866
|
+
const canEdit = editable && !readOnly;
|
|
867
|
+
const [anchor, setAnchor] = (0, import_react5.useState)(null);
|
|
868
|
+
const [focus, setFocus] = (0, import_react5.useState)(null);
|
|
869
|
+
const [message, setMessage] = (0, import_react5.useState)(null);
|
|
870
|
+
const words = (0, import_react5.useMemo)(() => {
|
|
871
|
+
try {
|
|
872
|
+
return (0, import_video_editor7.videoTimelineTranscript)(project, { track });
|
|
873
|
+
} catch {
|
|
874
|
+
return [];
|
|
875
|
+
}
|
|
876
|
+
}, [project, track]);
|
|
877
|
+
const current = (0, import_video_editor7.videoWordAt)(words, time);
|
|
878
|
+
const selected = anchor !== null && focus !== null && anchor < words.length && focus < words.length ? [Math.min(anchor, focus), Math.max(anchor, focus)] : null;
|
|
879
|
+
const sound = project.assets.filter((a) => a.kind !== "image");
|
|
880
|
+
const cut = (ranges, label, none) => {
|
|
881
|
+
if (!ranges.length) return setMessage(none);
|
|
882
|
+
const r = controller.apply((0, import_video_editor7.videoRemoveRangesEdits)(ranges), label);
|
|
883
|
+
setMessage(r.ok ? null : r.error);
|
|
884
|
+
setAnchor(null);
|
|
885
|
+
setFocus(null);
|
|
886
|
+
};
|
|
887
|
+
const load = async (assetId, file) => {
|
|
888
|
+
if (!file) return;
|
|
889
|
+
try {
|
|
890
|
+
const r = controller.apply((0, import_video_editor7.videoTranscriptEdit)(assetId, await file.text()), "Attach transcript");
|
|
891
|
+
setMessage(r.ok ? null : r.error);
|
|
892
|
+
} catch (e) {
|
|
893
|
+
setMessage(e instanceof Error ? e.message : String(e));
|
|
894
|
+
}
|
|
895
|
+
};
|
|
896
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: `flex flex-col gap-2 text-xs ${className}`, "data-transcript-panel": "", children: [
|
|
897
|
+
words.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
898
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
899
|
+
"div",
|
|
900
|
+
{
|
|
901
|
+
className: "max-h-48 overflow-y-auto leading-6",
|
|
902
|
+
role: "listbox",
|
|
903
|
+
"aria-label": "Transcript",
|
|
904
|
+
"aria-multiselectable": "true",
|
|
905
|
+
tabIndex: 0,
|
|
906
|
+
onKeyDown: (e) => {
|
|
907
|
+
if (canEdit && selected && (e.key === "Delete" || e.key === "Backspace")) {
|
|
908
|
+
e.preventDefault();
|
|
909
|
+
cut([(0, import_video_editor7.videoWordsRange)(words, selected[0], selected[1])], "Cut words", "Select words to cut.");
|
|
910
|
+
}
|
|
911
|
+
},
|
|
912
|
+
children: words.map((w, i) => {
|
|
913
|
+
const inSelection = selected !== null && i >= selected[0] && i <= selected[1];
|
|
914
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_react5.default.Fragment, { children: [
|
|
915
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
916
|
+
"span",
|
|
917
|
+
{
|
|
918
|
+
role: "option",
|
|
919
|
+
"aria-selected": inSelection,
|
|
920
|
+
tabIndex: -1,
|
|
921
|
+
className: `cursor-pointer rounded px-0.5 ${inSelection ? "bg-rose-500/30" : i === current ? "bg-amber-400/40" : "hover:bg-muted"}`,
|
|
922
|
+
"data-word": i,
|
|
923
|
+
"data-current": i === current ? "" : void 0,
|
|
924
|
+
"data-selected": inSelection ? "" : void 0,
|
|
925
|
+
onClick: (e) => {
|
|
926
|
+
if (e.shiftKey && anchor !== null) setFocus(i);
|
|
927
|
+
else {
|
|
928
|
+
setAnchor(i);
|
|
929
|
+
setFocus(i);
|
|
930
|
+
controller.seek(w.start);
|
|
931
|
+
}
|
|
932
|
+
},
|
|
933
|
+
children: w.word
|
|
934
|
+
}
|
|
935
|
+
),
|
|
936
|
+
" "
|
|
937
|
+
] }, `${w.clip}:${w.index}`);
|
|
938
|
+
})
|
|
939
|
+
}
|
|
940
|
+
),
|
|
941
|
+
canEdit && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex flex-wrap gap-1", children: [
|
|
942
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: btn3, disabled: !selected, onClick: () => selected && cut([(0, import_video_editor7.videoWordsRange)(words, selected[0], selected[1])], "Cut words", "Select words to cut."), children: "Delete selected words" }),
|
|
943
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: btn3, onClick: () => cut((0, import_video_editor7.findVideoFillers)(words), "Remove fillers", "No filler words found."), children: "Remove fillers" }),
|
|
944
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: btn3, onClick: () => cut((0, import_video_editor7.findVideoTranscriptPauses)(words, { fps: project.fps }), "Tighten pauses", "No long pauses found."), children: "Tighten pauses" })
|
|
945
|
+
] })
|
|
946
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "text-muted-foreground", "data-transcript-empty": "", children: "No transcribed media on the timeline. Load a transcript (Whisper JSON, .srt or .vtt) for a video or audio asset to edit by text." }),
|
|
947
|
+
canEdit && sound.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("details", { children: [
|
|
948
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("summary", { className: "cursor-pointer text-muted-foreground", children: "Transcripts" }),
|
|
949
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("ul", { className: "mt-1 space-y-1", children: sound.map((a) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("li", { className: "flex items-center gap-2", children: [
|
|
950
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "min-w-0 flex-1 truncate", children: [
|
|
951
|
+
a.name ?? a.id,
|
|
952
|
+
" ",
|
|
953
|
+
a.transcript ? `\xB7 ${a.transcript.length} words` : ""
|
|
954
|
+
] }),
|
|
955
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("input", { type: "file", accept: ".json,.srt,.vtt,application/json,text/vtt", "aria-label": `Load a transcript for ${a.name ?? a.id}`, className: "w-40 text-[10px]", onChange: (e) => void load(a.id, e.target.files?.[0]) })
|
|
956
|
+
] }, a.id)) })
|
|
957
|
+
] }),
|
|
958
|
+
message && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "text-red-500", role: "alert", "data-transcript-error": "", children: message })
|
|
959
|
+
] });
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
// src/video-editor/VideoEditor.tsx
|
|
963
|
+
var import_react6 = require("react");
|
|
964
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
965
|
+
function VideoEditor({ controller: given, options, editable = true, pxPerSecond, onPxPerSecondChange, resolution, showIssues = true, showTranscript = true, className = "" }) {
|
|
768
966
|
const { controller, state } = useVideoEditor(given ?? options ?? {});
|
|
769
|
-
(0,
|
|
967
|
+
(0, import_react6.useEffect)(() => {
|
|
770
968
|
if (editable) return;
|
|
771
969
|
const was = controller.getState().readOnly;
|
|
772
970
|
controller.setReadOnly(true);
|
|
773
971
|
return () => controller.setReadOnly(was);
|
|
774
972
|
}, [controller, editable]);
|
|
775
973
|
const { issues } = state;
|
|
776
|
-
const issueList = showIssues && issues.length > 0 && /* @__PURE__ */ (0,
|
|
777
|
-
return /* @__PURE__ */ (0,
|
|
778
|
-
/* @__PURE__ */ (0,
|
|
779
|
-
editable && /* @__PURE__ */ (0,
|
|
780
|
-
/* @__PURE__ */ (0,
|
|
781
|
-
/* @__PURE__ */ (0,
|
|
782
|
-
/* @__PURE__ */ (0,
|
|
974
|
+
const issueList = showIssues && issues.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("ul", { className: "space-y-0.5 text-xs", "aria-label": "Video issues", "data-video-issues": "", children: issues.map((issue, i) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("li", { className: issue.severity === "error" ? "text-red-500" : issue.severity === "warning" ? "text-amber-500" : "text-muted-foreground", "data-issue": issue.code, children: issue.message }, i)) });
|
|
975
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: `flex flex-col gap-3 ${className}`, "data-video-editor": "", children: [
|
|
976
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: `grid gap-3 ${editable ? "lg:grid-cols-[16rem_minmax(0,1fr)_18rem]" : ""}`, children: [
|
|
977
|
+
editable && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MediaBin, { controller, className: "min-w-0" }),
|
|
978
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex min-w-0 flex-col gap-2", children: [
|
|
979
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(VideoPreview, { controller, resolution, className: "rounded-md border border-border" }),
|
|
980
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(VideoTransport, { controller, editable })
|
|
783
981
|
] }),
|
|
784
|
-
editable && /* @__PURE__ */ (0,
|
|
982
|
+
editable && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ClipInspector, { controller, className: "min-w-0" })
|
|
785
983
|
] }),
|
|
786
|
-
/* @__PURE__ */ (0,
|
|
984
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(VideoTimeline, { controller, editable, pxPerSecond, onPxPerSecondChange }),
|
|
985
|
+
showTranscript && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TranscriptPanel, { controller, editable }),
|
|
787
986
|
issueList
|
|
788
987
|
] });
|
|
789
988
|
}
|
|
@@ -791,6 +990,7 @@ function VideoEditor({ controller: given, options, editable = true, pxPerSecond,
|
|
|
791
990
|
0 && (module.exports = {
|
|
792
991
|
ClipInspector,
|
|
793
992
|
MediaBin,
|
|
993
|
+
TranscriptPanel,
|
|
794
994
|
VideoEditor,
|
|
795
995
|
VideoPreview,
|
|
796
996
|
VideoTimeline,
|