@norskvideo/norsk-studio-built-ins 1.27.0-2026-01-10-23683704 → 1.27.0-2026-01-15-ecb87e67
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/client/info.js +1262 -404
- package/lib/input.srt-listener/_gen/types.d.ts +1 -0
- package/lib/input.srt-listener/_gen/yaml-docs.js +3 -0
- package/lib/input.srt-listener/_gen/yaml-docs.js.map +1 -1
- package/lib/input.srt-listener/_gen/zod.js +1 -0
- package/lib/input.srt-listener/_gen/zod.js.map +1 -1
- package/lib/input.srt-listener/info.d.ts +1 -0
- package/lib/input.srt-listener/info.js +9 -0
- package/lib/input.srt-listener/info.js.map +1 -1
- package/lib/input.srt-listener/runtime.d.ts +1 -0
- package/lib/input.srt-listener/runtime.js +7 -0
- package/lib/input.srt-listener/runtime.js.map +1 -1
- package/lib/input.srt-listener/types.yaml +2 -0
- package/lib/processor.browserOverlay/runtime.js +1 -1
- package/lib/processor.browserOverlay/runtime.js.map +1 -1
- package/lib/processor.onscreenGraphic/runtime.js +1 -1
- package/lib/processor.onscreenGraphic/runtime.js.map +1 -1
- package/lib/processor.smartSourceSwitch/inline-view.d.ts +3 -5
- package/lib/processor.smartSourceSwitch/inline-view.js +16 -4
- package/lib/processor.smartSourceSwitch/inline-view.js.map +1 -1
- package/lib/processor.videoCompose/fullscreen.js +28 -10
- package/lib/processor.videoCompose/fullscreen.js.map +1 -1
- package/lib/processor.videoCompose/preset-transition-panel.js +37 -8
- package/lib/processor.videoCompose/preset-transition-panel.js.map +1 -1
- package/lib/processor.videoCompose/presets.d.ts +8 -3
- package/lib/processor.videoCompose/presets.js +1215 -346
- package/lib/processor.videoCompose/presets.js.map +1 -1
- package/lib/processor.videoCompose/runtime.js +58 -44
- package/lib/processor.videoCompose/runtime.js.map +1 -1
- package/lib/processor.videoCompose/visual-preview.js +3 -1
- package/lib/processor.videoCompose/visual-preview.js.map +1 -1
- package/lib/processor.zoomTo/runtime.js +1 -1
- package/lib/processor.zoomTo/runtime.js.map +1 -1
- package/package.json +3 -3
package/client/info.js
CHANGED
|
@@ -25992,7 +25992,7 @@ var require_dist6 = __commonJS({
|
|
|
25992
25992
|
unstable_createCollection: () => createCollection2
|
|
25993
25993
|
});
|
|
25994
25994
|
module.exports = __toCommonJS2(index_exports);
|
|
25995
|
-
var
|
|
25995
|
+
var import_react34 = __toESM2(require_react());
|
|
25996
25996
|
var import_react_context = require_dist3();
|
|
25997
25997
|
var import_react_compose_refs = require_dist4();
|
|
25998
25998
|
var import_react_slot = require_dist5();
|
|
@@ -26006,14 +26006,14 @@ var require_dist6 = __commonJS({
|
|
|
26006
26006
|
);
|
|
26007
26007
|
const CollectionProvider = (props) => {
|
|
26008
26008
|
const { scope, children } = props;
|
|
26009
|
-
const ref =
|
|
26010
|
-
const itemMap =
|
|
26009
|
+
const ref = import_react34.default.useRef(null);
|
|
26010
|
+
const itemMap = import_react34.default.useRef(/* @__PURE__ */ new Map()).current;
|
|
26011
26011
|
return /* @__PURE__ */ (0, import_jsx_runtime75.jsx)(CollectionProviderImpl, { scope, itemMap, collectionRef: ref, children });
|
|
26012
26012
|
};
|
|
26013
26013
|
CollectionProvider.displayName = PROVIDER_NAME;
|
|
26014
26014
|
const COLLECTION_SLOT_NAME = name + "CollectionSlot";
|
|
26015
26015
|
const CollectionSlotImpl = (0, import_react_slot.createSlot)(COLLECTION_SLOT_NAME);
|
|
26016
|
-
const CollectionSlot =
|
|
26016
|
+
const CollectionSlot = import_react34.default.forwardRef(
|
|
26017
26017
|
(props, forwardedRef) => {
|
|
26018
26018
|
const { scope, children } = props;
|
|
26019
26019
|
const context = useCollectionContext(COLLECTION_SLOT_NAME, scope);
|
|
@@ -26025,13 +26025,13 @@ var require_dist6 = __commonJS({
|
|
|
26025
26025
|
const ITEM_SLOT_NAME = name + "CollectionItemSlot";
|
|
26026
26026
|
const ITEM_DATA_ATTR = "data-radix-collection-item";
|
|
26027
26027
|
const CollectionItemSlotImpl = (0, import_react_slot.createSlot)(ITEM_SLOT_NAME);
|
|
26028
|
-
const CollectionItemSlot =
|
|
26028
|
+
const CollectionItemSlot = import_react34.default.forwardRef(
|
|
26029
26029
|
(props, forwardedRef) => {
|
|
26030
26030
|
const { scope, children, ...itemData } = props;
|
|
26031
|
-
const ref =
|
|
26031
|
+
const ref = import_react34.default.useRef(null);
|
|
26032
26032
|
const composedRefs = (0, import_react_compose_refs.useComposedRefs)(forwardedRef, ref);
|
|
26033
26033
|
const context = useCollectionContext(ITEM_SLOT_NAME, scope);
|
|
26034
|
-
|
|
26034
|
+
import_react34.default.useEffect(() => {
|
|
26035
26035
|
context.itemMap.set(ref, { ref, ...itemData });
|
|
26036
26036
|
return () => void context.itemMap.delete(ref);
|
|
26037
26037
|
});
|
|
@@ -26041,7 +26041,7 @@ var require_dist6 = __commonJS({
|
|
|
26041
26041
|
CollectionItemSlot.displayName = ITEM_SLOT_NAME;
|
|
26042
26042
|
function useCollection(scope) {
|
|
26043
26043
|
const context = useCollectionContext(name + "CollectionConsumer", scope);
|
|
26044
|
-
const getItems =
|
|
26044
|
+
const getItems = import_react34.default.useCallback(() => {
|
|
26045
26045
|
const collectionNode = context.collectionRef.current;
|
|
26046
26046
|
if (!collectionNode) return [];
|
|
26047
26047
|
const orderedNodes = Array.from(collectionNode.querySelectorAll(`[${ITEM_DATA_ATTR}]`));
|
|
@@ -62393,6 +62393,15 @@ function info_default6({ defineComponent, mappingsToStreams: mappingsToStreams2,
|
|
|
62393
62393
|
global: unique("sourceName")
|
|
62394
62394
|
}
|
|
62395
62395
|
},
|
|
62396
|
+
burstProtection: {
|
|
62397
|
+
advanced: true,
|
|
62398
|
+
help: "Drop data until input is completely stable",
|
|
62399
|
+
hint: {
|
|
62400
|
+
defaultValue: false,
|
|
62401
|
+
type: "boolean",
|
|
62402
|
+
optional: true
|
|
62403
|
+
}
|
|
62404
|
+
},
|
|
62396
62405
|
decodeOutputs: (0, import_client_types3.DecodeOutputsForm)(),
|
|
62397
62406
|
streamMappings: StreamMappingForm(defaultStreamMapping3, {
|
|
62398
62407
|
sourceNames: (cfg) => cfg.streamIds ?? []
|
|
@@ -73377,13 +73386,17 @@ var import_jsx_runtime55 = __toESM(require_jsx_runtime());
|
|
|
73377
73386
|
var import_FaTimes = __toESM(require_FaTimes());
|
|
73378
73387
|
var import_FaPlay2 = __toESM(require_FaPlay());
|
|
73379
73388
|
var import_FaCircle = __toESM(require_FaCircle());
|
|
73380
|
-
|
|
73389
|
+
var import_react25 = __toESM(require_react());
|
|
73390
|
+
function InlineView18({ state, config, sendCommand }) {
|
|
73381
73391
|
const priorityOrder = state.sourcePriority || config.sources;
|
|
73382
|
-
|
|
73392
|
+
const handlePriorityChange = (0, import_react25.useCallback)((newOrder) => {
|
|
73393
|
+
sendCommand({ type: "set-priority-order", sources: newOrder });
|
|
73394
|
+
}, [sendCommand]);
|
|
73395
|
+
return (0, import_jsx_runtime55.jsxs)(import_jsx_runtime55.Fragment, { children: [(0, import_jsx_runtime55.jsx)("h5", { className: "text-gray-900 dark:text-white font-medium", children: "Sources:" }), (0, import_jsx_runtime55.jsxs)("ul", { className: "space-y-2 mt-2", children: [priorityOrder.map((s, index3) => {
|
|
73383
73396
|
const isActive = state.activeSource === s;
|
|
73384
73397
|
const isAvailable = state.availableSources.includes(s);
|
|
73385
73398
|
const isOffline = !isActive && !isAvailable;
|
|
73386
|
-
const priorityRank =
|
|
73399
|
+
const priorityRank = index3 + 1;
|
|
73387
73400
|
return (0, import_jsx_runtime55.jsxs)("li", { className: "flex items-center gap-2 w-full", children: [(0, import_jsx_runtime55.jsx)("div", { className: "relative w-4 h-4 flex items-center justify-center flex-shrink-0", children: isOffline ? (
|
|
73388
73401
|
// Red X for offline sources
|
|
73389
73402
|
(0, import_jsx_runtime55.jsx)(import_FaTimes.FaTimes, { className: "w-4 h-4 text-red-500" })
|
|
@@ -73393,7 +73406,15 @@ function InlineView18({ state, config }) {
|
|
|
73393
73406
|
) : (
|
|
73394
73407
|
// Green circle for available but not active
|
|
73395
73408
|
(0, import_jsx_runtime55.jsx)(import_FaCircle.FaCircle, { className: "w-2 h-2 text-green-500" })
|
|
73396
|
-
) }), (0, import_jsx_runtime55.jsx)("span", { className: "text-gray-900 dark:text-white flex-1", children: s }), (0, import_jsx_runtime55.
|
|
73409
|
+
) }), (0, import_jsx_runtime55.jsx)("span", { className: "text-gray-900 dark:text-white flex-1", children: s }), (0, import_jsx_runtime55.jsxs)("div", { className: "flex items-center gap-1", children: [index3 > 0 && (0, import_jsx_runtime55.jsx)("button", { onClick: () => {
|
|
73410
|
+
const newOrder = [...priorityOrder];
|
|
73411
|
+
[newOrder[index3], newOrder[index3 - 1]] = [newOrder[index3 - 1], newOrder[index3]];
|
|
73412
|
+
handlePriorityChange(newOrder);
|
|
73413
|
+
}, className: "w-4 h-4 flex items-center justify-center text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200", title: "Move up", children: (0, import_jsx_runtime55.jsx)("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", strokeWidth: 2, stroke: "currentColor", className: "w-3 h-3", children: (0, import_jsx_runtime55.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M4.5 15.75l7.5-7.5 7.5 7.5" }) }) }), index3 < priorityOrder.length - 1 && (0, import_jsx_runtime55.jsx)("button", { onClick: () => {
|
|
73414
|
+
const newOrder = [...priorityOrder];
|
|
73415
|
+
[newOrder[index3], newOrder[index3 + 1]] = [newOrder[index3 + 1], newOrder[index3]];
|
|
73416
|
+
handlePriorityChange(newOrder);
|
|
73417
|
+
}, className: "w-4 h-4 flex items-center justify-center text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200", title: "Move down", children: (0, import_jsx_runtime55.jsx)("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", strokeWidth: 2, stroke: "currentColor", className: "w-3 h-3", children: (0, import_jsx_runtime55.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19.5 8.25l-7.5 7.5-7.5-7.5" }) }) }), (0, import_jsx_runtime55.jsx)("span", { className: "text-gray-500 dark:text-gray-400 text-sm w-4 text-center", children: priorityRank })] })] }, s);
|
|
73397
73418
|
}), (0, import_jsx_runtime55.jsxs)("li", { className: "flex items-center gap-2", children: [(0, import_jsx_runtime55.jsx)("div", { className: "relative w-4 h-4 flex items-center justify-center", children: state.activeSource === "fallback" ? (
|
|
73398
73419
|
// Green play button for active fallback
|
|
73399
73420
|
(0, import_jsx_runtime55.jsxs)(import_jsx_runtime55.Fragment, { children: [(0, import_jsx_runtime55.jsx)(import_FaPlay2.FaPlay, { className: "w-3 h-3 text-green-500" }), (0, import_jsx_runtime55.jsx)("div", { className: "absolute inset-0 flex items-center justify-center opacity-30", children: (0, import_jsx_runtime55.jsx)("div", { className: "w-4 h-4 bg-green-500 animate-ping duration-150" }) })] })
|
|
@@ -73406,12 +73427,12 @@ var inline_view_default18 = InlineView18;
|
|
|
73406
73427
|
|
|
73407
73428
|
// build/client/processor.smartSourceSwitch/fullscreen.js
|
|
73408
73429
|
var import_jsx_runtime56 = __toESM(require_jsx_runtime());
|
|
73409
|
-
var
|
|
73430
|
+
var import_react26 = __toESM(require_react());
|
|
73410
73431
|
function FullscreenView2({ state, config, sendCommand }) {
|
|
73411
|
-
const handleMakeActive = (0,
|
|
73432
|
+
const handleMakeActive = (0, import_react26.useCallback)((source) => {
|
|
73412
73433
|
sendCommand({ type: "make-source-active", source });
|
|
73413
73434
|
}, [sendCommand]);
|
|
73414
|
-
const handlePriorityChange = (0,
|
|
73435
|
+
const handlePriorityChange = (0, import_react26.useCallback)((newOrder) => {
|
|
73415
73436
|
sendCommand({ type: "set-priority-order", sources: newOrder });
|
|
73416
73437
|
}, [sendCommand]);
|
|
73417
73438
|
const displaySources = config.sources;
|
|
@@ -73776,9 +73797,9 @@ var import_config11 = __toESM(require_config2());
|
|
|
73776
73797
|
|
|
73777
73798
|
// build/client/processor.syncExternalAudio/inline-view.js
|
|
73778
73799
|
var import_jsx_runtime58 = __toESM(require_jsx_runtime());
|
|
73779
|
-
var
|
|
73800
|
+
var import_react27 = __toESM(require_react());
|
|
73780
73801
|
function InlineView19({ state, config, raise }) {
|
|
73781
|
-
(0,
|
|
73802
|
+
(0, import_react27.useEffect)(() => {
|
|
73782
73803
|
if (raise) {
|
|
73783
73804
|
raise();
|
|
73784
73805
|
}
|
|
@@ -73790,19 +73811,19 @@ var inline_view_default19 = InlineView19;
|
|
|
73790
73811
|
|
|
73791
73812
|
// build/client/processor.syncExternalAudio/fullscreen-view.js
|
|
73792
73813
|
var import_jsx_runtime59 = __toESM(require_jsx_runtime());
|
|
73793
|
-
var
|
|
73814
|
+
var import_react28 = __toESM(require_react());
|
|
73794
73815
|
function SyncExternalAudioFullscreenView({ state, config, sendCommand }) {
|
|
73795
|
-
const videoContainerRef = (0,
|
|
73796
|
-
const whepClientRef = (0,
|
|
73816
|
+
const videoContainerRef = (0, import_react28.useRef)(null);
|
|
73817
|
+
const whepClientRef = (0, import_react28.useRef)(null);
|
|
73797
73818
|
const commentaries = Object.entries(state.commentaries || {});
|
|
73798
|
-
const [selectedCommentary, setSelectedCommentary] = (0,
|
|
73799
|
-
(0,
|
|
73819
|
+
const [selectedCommentary, setSelectedCommentary] = (0, import_react28.useState)(commentaries[0]?.[0] || "");
|
|
73820
|
+
(0, import_react28.useEffect)(() => {
|
|
73800
73821
|
if (commentaries.length > 0 && !state.commentaries[selectedCommentary]) {
|
|
73801
73822
|
setSelectedCommentary(commentaries[0][0]);
|
|
73802
73823
|
}
|
|
73803
73824
|
}, [commentaries, selectedCommentary, state.commentaries]);
|
|
73804
73825
|
const commentary = state.commentaries[selectedCommentary];
|
|
73805
|
-
(0,
|
|
73826
|
+
(0, import_react28.useEffect)(() => {
|
|
73806
73827
|
if (commentary?.whepUrl && videoContainerRef.current) {
|
|
73807
73828
|
if (whepClientRef.current) {
|
|
73808
73829
|
whepClientRef.current = null;
|
|
@@ -74038,11 +74059,11 @@ var summary_view_default11 = SummaryView11;
|
|
|
74038
74059
|
|
|
74039
74060
|
// build/client/processor.videoCompose/fullscreen.js
|
|
74040
74061
|
var import_jsx_runtime66 = __toESM(require_jsx_runtime());
|
|
74041
|
-
var
|
|
74062
|
+
var import_react31 = __toESM(require_react());
|
|
74042
74063
|
|
|
74043
74064
|
// build/client/processor.videoCompose/preset-transition-panel.js
|
|
74044
74065
|
var import_jsx_runtime63 = __toESM(require_jsx_runtime());
|
|
74045
|
-
var
|
|
74066
|
+
var import_react29 = __toESM(require_react());
|
|
74046
74067
|
|
|
74047
74068
|
// build/client/processor.videoCompose/presets-metadata.js
|
|
74048
74069
|
var PRESET_METADATA = {
|
|
@@ -74482,7 +74503,7 @@ var PRESETS = {
|
|
|
74482
74503
|
}))
|
|
74483
74504
|
}
|
|
74484
74505
|
}),
|
|
74485
|
-
quarters: (sources, _config, res) => {
|
|
74506
|
+
quarters: (sources, _config, res, transitionContext) => {
|
|
74486
74507
|
const half_w = res.width / 2;
|
|
74487
74508
|
const half_h = res.height / 2;
|
|
74488
74509
|
const quarters = sources.slice(0, 4);
|
|
@@ -74542,22 +74563,78 @@ var PRESETS = {
|
|
|
74542
74563
|
]
|
|
74543
74564
|
},
|
|
74544
74565
|
to: {
|
|
74545
|
-
fullscreen:
|
|
74546
|
-
|
|
74547
|
-
|
|
74548
|
-
|
|
74549
|
-
|
|
74550
|
-
|
|
74551
|
-
|
|
74552
|
-
|
|
74553
|
-
|
|
74554
|
-
|
|
74555
|
-
|
|
74556
|
-
|
|
74557
|
-
|
|
74558
|
-
|
|
74566
|
+
fullscreen: (() => {
|
|
74567
|
+
const targetSources = transitionContext?.targetSources ?? [];
|
|
74568
|
+
const targetSource = targetSources[0];
|
|
74569
|
+
const targetInQuarters = targetSource && quarters.includes(targetSource);
|
|
74570
|
+
if (targetInQuarters) {
|
|
74571
|
+
return [
|
|
74572
|
+
{
|
|
74573
|
+
durationMs: 500,
|
|
74574
|
+
layout: {
|
|
74575
|
+
layers: quarters.map((s, i) => ({
|
|
74576
|
+
sourceName: s,
|
|
74577
|
+
zIndex: i,
|
|
74578
|
+
opacity: s === targetSource ? 1 : 0,
|
|
74579
|
+
id: s,
|
|
74580
|
+
sourceRect: void 0,
|
|
74581
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
74582
|
+
}))
|
|
74583
|
+
}
|
|
74584
|
+
},
|
|
74585
|
+
// Final step: target source only
|
|
74586
|
+
{
|
|
74587
|
+
durationMs: 0,
|
|
74588
|
+
layout: {
|
|
74589
|
+
layers: [{
|
|
74590
|
+
sourceName: targetSource,
|
|
74591
|
+
zIndex: 0,
|
|
74592
|
+
opacity: 1,
|
|
74593
|
+
id: targetSource,
|
|
74594
|
+
sourceRect: void 0,
|
|
74595
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
74596
|
+
}]
|
|
74597
|
+
}
|
|
74598
|
+
}
|
|
74599
|
+
];
|
|
74600
|
+
} else {
|
|
74601
|
+
return [
|
|
74602
|
+
// Step 1: Fade out all quarters
|
|
74603
|
+
{
|
|
74604
|
+
durationMs: 250,
|
|
74605
|
+
layout: {
|
|
74606
|
+
layers: quarters.map((s, i) => ({
|
|
74607
|
+
sourceName: s,
|
|
74608
|
+
zIndex: i,
|
|
74609
|
+
opacity: 0,
|
|
74610
|
+
id: s,
|
|
74611
|
+
sourceRect: void 0,
|
|
74612
|
+
destRect: {
|
|
74613
|
+
x: i % 2 * half_w,
|
|
74614
|
+
y: Math.floor(i / 2) * half_h,
|
|
74615
|
+
width: half_w,
|
|
74616
|
+
height: half_h
|
|
74617
|
+
}
|
|
74618
|
+
}))
|
|
74619
|
+
}
|
|
74620
|
+
},
|
|
74621
|
+
// Step 2: Show target source (if available)
|
|
74622
|
+
...targetSource ? [{
|
|
74623
|
+
durationMs: 250,
|
|
74624
|
+
layout: {
|
|
74625
|
+
layers: [{
|
|
74626
|
+
sourceName: targetSource,
|
|
74627
|
+
zIndex: 0,
|
|
74628
|
+
opacity: 1,
|
|
74629
|
+
id: targetSource,
|
|
74630
|
+
sourceRect: void 0,
|
|
74631
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
74632
|
+
}]
|
|
74633
|
+
}
|
|
74634
|
+
}] : []
|
|
74635
|
+
];
|
|
74559
74636
|
}
|
|
74560
|
-
|
|
74637
|
+
})(),
|
|
74561
74638
|
"mosaic-9": [
|
|
74562
74639
|
// Quarters → Mosaic-9: move 4 sources to their 3×3 grid positions
|
|
74563
74640
|
{
|
|
@@ -74670,8 +74747,9 @@ var PRESETS = {
|
|
|
74670
74747
|
} : void 0
|
|
74671
74748
|
};
|
|
74672
74749
|
},
|
|
74673
|
-
pip: (sources, config, res) => {
|
|
74750
|
+
pip: (sources, config, res, transitionContext) => {
|
|
74674
74751
|
const [mainSource, pipSource] = sources;
|
|
74752
|
+
const pipSources = [mainSource, pipSource].filter(Boolean);
|
|
74675
74753
|
const pipConfig = config;
|
|
74676
74754
|
const corner = pipConfig?.corner ?? "bottom-right";
|
|
74677
74755
|
const pipWidth = pipConfig?.width ?? Math.round(res.width * 0.2);
|
|
@@ -74805,37 +74883,91 @@ var PRESETS = {
|
|
|
74805
74883
|
]
|
|
74806
74884
|
},
|
|
74807
74885
|
to: {
|
|
74808
|
-
fullscreen:
|
|
74809
|
-
|
|
74810
|
-
|
|
74811
|
-
|
|
74812
|
-
|
|
74813
|
-
|
|
74814
|
-
|
|
74815
|
-
|
|
74816
|
-
|
|
74817
|
-
|
|
74818
|
-
|
|
74819
|
-
|
|
74820
|
-
|
|
74821
|
-
|
|
74822
|
-
|
|
74823
|
-
|
|
74824
|
-
|
|
74825
|
-
|
|
74826
|
-
|
|
74827
|
-
|
|
74828
|
-
|
|
74829
|
-
|
|
74830
|
-
|
|
74831
|
-
|
|
74832
|
-
|
|
74833
|
-
|
|
74886
|
+
fullscreen: (() => {
|
|
74887
|
+
const targetSources = transitionContext?.targetSources ?? [];
|
|
74888
|
+
const targetSource = targetSources[0];
|
|
74889
|
+
const targetInPip = targetSource && pipSources.includes(targetSource);
|
|
74890
|
+
if (targetInPip) {
|
|
74891
|
+
return [
|
|
74892
|
+
{
|
|
74893
|
+
durationMs: 500,
|
|
74894
|
+
layout: {
|
|
74895
|
+
layers: [
|
|
74896
|
+
{
|
|
74897
|
+
sourceName: mainSource,
|
|
74898
|
+
zIndex: 0,
|
|
74899
|
+
opacity: mainSource === targetSource ? 1 : 0,
|
|
74900
|
+
id: mainSource,
|
|
74901
|
+
sourceRect: void 0,
|
|
74902
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
74903
|
+
},
|
|
74904
|
+
...pipSource ? [{
|
|
74905
|
+
sourceName: pipSource,
|
|
74906
|
+
zIndex: 1,
|
|
74907
|
+
opacity: pipSource === targetSource ? 1 : 0,
|
|
74908
|
+
id: pipSource,
|
|
74909
|
+
sourceRect: void 0,
|
|
74910
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
74911
|
+
}] : []
|
|
74912
|
+
]
|
|
74834
74913
|
}
|
|
74835
|
-
|
|
74836
|
-
|
|
74914
|
+
},
|
|
74915
|
+
// Final step: target source only
|
|
74916
|
+
{
|
|
74917
|
+
durationMs: 0,
|
|
74918
|
+
layout: {
|
|
74919
|
+
layers: [{
|
|
74920
|
+
sourceName: targetSource,
|
|
74921
|
+
zIndex: 0,
|
|
74922
|
+
opacity: 1,
|
|
74923
|
+
id: targetSource,
|
|
74924
|
+
sourceRect: void 0,
|
|
74925
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
74926
|
+
}]
|
|
74927
|
+
}
|
|
74928
|
+
}
|
|
74929
|
+
];
|
|
74930
|
+
} else {
|
|
74931
|
+
return [
|
|
74932
|
+
{
|
|
74933
|
+
durationMs: 250,
|
|
74934
|
+
layout: {
|
|
74935
|
+
layers: [
|
|
74936
|
+
{
|
|
74937
|
+
sourceName: mainSource,
|
|
74938
|
+
zIndex: 0,
|
|
74939
|
+
opacity: 0,
|
|
74940
|
+
id: mainSource,
|
|
74941
|
+
sourceRect: void 0,
|
|
74942
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
74943
|
+
},
|
|
74944
|
+
...pipSource ? [{
|
|
74945
|
+
sourceName: pipSource,
|
|
74946
|
+
zIndex: 1,
|
|
74947
|
+
opacity: 0,
|
|
74948
|
+
id: pipSource,
|
|
74949
|
+
sourceRect: void 0,
|
|
74950
|
+
destRect: { x: pipX, y: pipY, width: pipWidth, height: pipHeight }
|
|
74951
|
+
}] : []
|
|
74952
|
+
]
|
|
74953
|
+
}
|
|
74954
|
+
},
|
|
74955
|
+
...targetSource ? [{
|
|
74956
|
+
durationMs: 250,
|
|
74957
|
+
layout: {
|
|
74958
|
+
layers: [{
|
|
74959
|
+
sourceName: targetSource,
|
|
74960
|
+
zIndex: 0,
|
|
74961
|
+
opacity: 1,
|
|
74962
|
+
id: targetSource,
|
|
74963
|
+
sourceRect: void 0,
|
|
74964
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
74965
|
+
}]
|
|
74966
|
+
}
|
|
74967
|
+
}] : []
|
|
74968
|
+
];
|
|
74837
74969
|
}
|
|
74838
|
-
|
|
74970
|
+
})(),
|
|
74839
74971
|
"side-by-side": [
|
|
74840
74972
|
// PiP → Side-by-side: background compresses to left, overlay expands to right
|
|
74841
74973
|
{
|
|
@@ -74923,8 +75055,9 @@ var PRESETS = {
|
|
|
74923
75055
|
} : void 0
|
|
74924
75056
|
};
|
|
74925
75057
|
},
|
|
74926
|
-
"lower-third": (sources, config, res) => {
|
|
75058
|
+
"lower-third": (sources, config, res, transitionContext) => {
|
|
74927
75059
|
const [mainSource, lowerThirdSource] = sources;
|
|
75060
|
+
const lowerThirdSources = [mainSource, lowerThirdSource].filter(Boolean);
|
|
74928
75061
|
const lowerThirdConfig = config;
|
|
74929
75062
|
const alignment = lowerThirdConfig?.alignment ?? "left";
|
|
74930
75063
|
const lowerThirdWidth = lowerThirdConfig?.width ?? Math.round(res.width * 0.3);
|
|
@@ -75018,32 +75151,91 @@ var PRESETS = {
|
|
|
75018
75151
|
]
|
|
75019
75152
|
},
|
|
75020
75153
|
to: {
|
|
75021
|
-
fullscreen:
|
|
75022
|
-
|
|
75023
|
-
|
|
75024
|
-
|
|
75025
|
-
|
|
75026
|
-
|
|
75027
|
-
|
|
75028
|
-
|
|
75029
|
-
|
|
75030
|
-
|
|
75031
|
-
|
|
75032
|
-
|
|
75033
|
-
|
|
75034
|
-
|
|
75035
|
-
|
|
75036
|
-
|
|
75037
|
-
|
|
75038
|
-
|
|
75039
|
-
|
|
75040
|
-
|
|
75041
|
-
|
|
75154
|
+
fullscreen: (() => {
|
|
75155
|
+
const targetSources = transitionContext?.targetSources ?? [];
|
|
75156
|
+
const targetSource = targetSources[0];
|
|
75157
|
+
const targetInLowerThird = targetSource && lowerThirdSources.includes(targetSource);
|
|
75158
|
+
if (targetInLowerThird) {
|
|
75159
|
+
return [
|
|
75160
|
+
{
|
|
75161
|
+
durationMs: 500,
|
|
75162
|
+
layout: {
|
|
75163
|
+
layers: [
|
|
75164
|
+
{
|
|
75165
|
+
sourceName: mainSource,
|
|
75166
|
+
zIndex: 0,
|
|
75167
|
+
opacity: mainSource === targetSource ? 1 : 0,
|
|
75168
|
+
id: mainSource,
|
|
75169
|
+
sourceRect: void 0,
|
|
75170
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
75171
|
+
},
|
|
75172
|
+
{
|
|
75173
|
+
sourceName: lowerThirdSource,
|
|
75174
|
+
zIndex: 1,
|
|
75175
|
+
opacity: lowerThirdSource === targetSource ? 1 : 0,
|
|
75176
|
+
id: lowerThirdSource,
|
|
75177
|
+
sourceRect: void 0,
|
|
75178
|
+
destRect: lowerThirdSource === targetSource ? { x: 0, y: 0, width: res.width, height: res.height } : { x: lowerThirdX, y: res.height, width: lowerThirdWidth, height: lowerThirdHeight }
|
|
75179
|
+
}
|
|
75180
|
+
]
|
|
75042
75181
|
}
|
|
75043
|
-
|
|
75044
|
-
|
|
75182
|
+
},
|
|
75183
|
+
// Final step: target source only
|
|
75184
|
+
{
|
|
75185
|
+
durationMs: 0,
|
|
75186
|
+
layout: {
|
|
75187
|
+
layers: [{
|
|
75188
|
+
sourceName: targetSource,
|
|
75189
|
+
zIndex: 0,
|
|
75190
|
+
opacity: 1,
|
|
75191
|
+
id: targetSource,
|
|
75192
|
+
sourceRect: void 0,
|
|
75193
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
75194
|
+
}]
|
|
75195
|
+
}
|
|
75196
|
+
}
|
|
75197
|
+
];
|
|
75198
|
+
} else {
|
|
75199
|
+
return [
|
|
75200
|
+
{
|
|
75201
|
+
durationMs: 250,
|
|
75202
|
+
layout: {
|
|
75203
|
+
layers: [
|
|
75204
|
+
{
|
|
75205
|
+
sourceName: mainSource,
|
|
75206
|
+
zIndex: 0,
|
|
75207
|
+
opacity: 0,
|
|
75208
|
+
id: mainSource,
|
|
75209
|
+
sourceRect: void 0,
|
|
75210
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
75211
|
+
},
|
|
75212
|
+
{
|
|
75213
|
+
sourceName: lowerThirdSource,
|
|
75214
|
+
zIndex: 1,
|
|
75215
|
+
opacity: 0,
|
|
75216
|
+
id: lowerThirdSource,
|
|
75217
|
+
sourceRect: void 0,
|
|
75218
|
+
destRect: { x: lowerThirdX, y: res.height, width: lowerThirdWidth, height: lowerThirdHeight }
|
|
75219
|
+
}
|
|
75220
|
+
]
|
|
75221
|
+
}
|
|
75222
|
+
},
|
|
75223
|
+
...targetSource ? [{
|
|
75224
|
+
durationMs: 250,
|
|
75225
|
+
layout: {
|
|
75226
|
+
layers: [{
|
|
75227
|
+
sourceName: targetSource,
|
|
75228
|
+
zIndex: 0,
|
|
75229
|
+
opacity: 1,
|
|
75230
|
+
id: targetSource,
|
|
75231
|
+
sourceRect: void 0,
|
|
75232
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
75233
|
+
}]
|
|
75234
|
+
}
|
|
75235
|
+
}] : []
|
|
75236
|
+
];
|
|
75045
75237
|
}
|
|
75046
|
-
|
|
75238
|
+
})(),
|
|
75047
75239
|
pip: [
|
|
75048
75240
|
// Lower-third → PiP: move overlay from bottom to corner, resize
|
|
75049
75241
|
{
|
|
@@ -75079,9 +75271,10 @@ var PRESETS = {
|
|
|
75079
75271
|
} : void 0
|
|
75080
75272
|
};
|
|
75081
75273
|
},
|
|
75082
|
-
"side-by-side": (sources, _config, res) => {
|
|
75274
|
+
"side-by-side": (sources, _config, res, transitionContext) => {
|
|
75083
75275
|
const [source1, source2] = sources.slice(0, 2);
|
|
75084
75276
|
const halfWidth = res.width / 2;
|
|
75277
|
+
const sideBySideSources = [source1, source2].filter(Boolean);
|
|
75085
75278
|
return {
|
|
75086
75279
|
name: "side-by-side",
|
|
75087
75280
|
finalConfig: {
|
|
@@ -75184,32 +75377,91 @@ var PRESETS = {
|
|
|
75184
75377
|
]
|
|
75185
75378
|
},
|
|
75186
75379
|
to: {
|
|
75187
|
-
fullscreen:
|
|
75188
|
-
|
|
75189
|
-
|
|
75190
|
-
|
|
75191
|
-
|
|
75192
|
-
|
|
75193
|
-
|
|
75194
|
-
|
|
75195
|
-
|
|
75196
|
-
|
|
75197
|
-
|
|
75198
|
-
|
|
75199
|
-
|
|
75200
|
-
|
|
75201
|
-
|
|
75202
|
-
|
|
75203
|
-
|
|
75204
|
-
|
|
75205
|
-
|
|
75206
|
-
|
|
75207
|
-
|
|
75380
|
+
fullscreen: (() => {
|
|
75381
|
+
const targetSources = transitionContext?.targetSources ?? [];
|
|
75382
|
+
const targetSource = targetSources[0];
|
|
75383
|
+
const targetInSideBySide = targetSource && sideBySideSources.includes(targetSource);
|
|
75384
|
+
if (targetInSideBySide) {
|
|
75385
|
+
return [
|
|
75386
|
+
{
|
|
75387
|
+
durationMs: 500,
|
|
75388
|
+
layout: {
|
|
75389
|
+
layers: [
|
|
75390
|
+
{
|
|
75391
|
+
sourceName: source1,
|
|
75392
|
+
zIndex: 0,
|
|
75393
|
+
opacity: 1,
|
|
75394
|
+
id: source1,
|
|
75395
|
+
sourceRect: void 0,
|
|
75396
|
+
destRect: source1 === targetSource ? { x: 0, y: 0, width: res.width, height: res.height } : { x: -halfWidth, y: 0, width: halfWidth, height: res.height }
|
|
75397
|
+
},
|
|
75398
|
+
...source2 ? [{
|
|
75399
|
+
sourceName: source2,
|
|
75400
|
+
zIndex: 1,
|
|
75401
|
+
opacity: 1,
|
|
75402
|
+
id: source2,
|
|
75403
|
+
sourceRect: void 0,
|
|
75404
|
+
destRect: source2 === targetSource ? { x: 0, y: 0, width: res.width, height: res.height } : { x: res.width, y: 0, width: halfWidth, height: res.height }
|
|
75405
|
+
}] : []
|
|
75406
|
+
]
|
|
75208
75407
|
}
|
|
75209
|
-
|
|
75210
|
-
|
|
75408
|
+
},
|
|
75409
|
+
// Final step: target source only
|
|
75410
|
+
{
|
|
75411
|
+
durationMs: 0,
|
|
75412
|
+
layout: {
|
|
75413
|
+
layers: [{
|
|
75414
|
+
sourceName: targetSource,
|
|
75415
|
+
zIndex: 0,
|
|
75416
|
+
opacity: 1,
|
|
75417
|
+
id: targetSource,
|
|
75418
|
+
sourceRect: void 0,
|
|
75419
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
75420
|
+
}]
|
|
75421
|
+
}
|
|
75422
|
+
}
|
|
75423
|
+
];
|
|
75424
|
+
} else {
|
|
75425
|
+
return [
|
|
75426
|
+
{
|
|
75427
|
+
durationMs: 250,
|
|
75428
|
+
layout: {
|
|
75429
|
+
layers: [
|
|
75430
|
+
{
|
|
75431
|
+
sourceName: source1,
|
|
75432
|
+
zIndex: 0,
|
|
75433
|
+
opacity: 0,
|
|
75434
|
+
id: source1,
|
|
75435
|
+
sourceRect: void 0,
|
|
75436
|
+
destRect: { x: 0, y: 0, width: halfWidth, height: res.height }
|
|
75437
|
+
},
|
|
75438
|
+
...source2 ? [{
|
|
75439
|
+
sourceName: source2,
|
|
75440
|
+
zIndex: 1,
|
|
75441
|
+
opacity: 0,
|
|
75442
|
+
id: source2,
|
|
75443
|
+
sourceRect: void 0,
|
|
75444
|
+
destRect: { x: halfWidth, y: 0, width: halfWidth, height: res.height }
|
|
75445
|
+
}] : []
|
|
75446
|
+
]
|
|
75447
|
+
}
|
|
75448
|
+
},
|
|
75449
|
+
...targetSource ? [{
|
|
75450
|
+
durationMs: 250,
|
|
75451
|
+
layout: {
|
|
75452
|
+
layers: [{
|
|
75453
|
+
sourceName: targetSource,
|
|
75454
|
+
zIndex: 0,
|
|
75455
|
+
opacity: 1,
|
|
75456
|
+
id: targetSource,
|
|
75457
|
+
sourceRect: void 0,
|
|
75458
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
75459
|
+
}]
|
|
75460
|
+
}
|
|
75461
|
+
}] : []
|
|
75462
|
+
];
|
|
75211
75463
|
}
|
|
75212
|
-
|
|
75464
|
+
})(),
|
|
75213
75465
|
pip: [
|
|
75214
75466
|
// Side-by-side → PiP: left expands to fullscreen, right shrinks to corner
|
|
75215
75467
|
{
|
|
@@ -75297,13 +75549,14 @@ var PRESETS = {
|
|
|
75297
75549
|
} : void 0
|
|
75298
75550
|
};
|
|
75299
75551
|
},
|
|
75300
|
-
"lbar": (sources, config, res) => {
|
|
75552
|
+
"lbar": (sources, config, res, transitionContext) => {
|
|
75301
75553
|
const [videoSource, overlaySource] = sources;
|
|
75302
75554
|
const { videoWidth, videoHeight, videoX = 50, videoY = 50 } = config;
|
|
75303
|
-
return createLBarPresetDefinition([videoSource, overlaySource], { videoWidth, videoHeight, videoX, videoY }, res);
|
|
75555
|
+
return createLBarPresetDefinition([videoSource, overlaySource], { videoWidth, videoHeight, videoX, videoY }, res, transitionContext);
|
|
75304
75556
|
},
|
|
75305
|
-
"qr-lbar": (sources, config, res) => {
|
|
75557
|
+
"qr-lbar": (sources, config, res, transitionContext) => {
|
|
75306
75558
|
const [videoSource, qrSource, overlaySource] = sources;
|
|
75559
|
+
const qrLbarSources = [videoSource, qrSource, overlaySource].filter(Boolean);
|
|
75307
75560
|
const { qrDurationMs, qrCorner, qrWidth, qrHeight, qrPadding = 20, videoWidth, videoHeight, videoX = 0, videoY = 0 } = config;
|
|
75308
75561
|
const qrPosition = (() => {
|
|
75309
75562
|
switch (qrCorner) {
|
|
@@ -75423,45 +75676,112 @@ var PRESETS = {
|
|
|
75423
75676
|
]
|
|
75424
75677
|
},
|
|
75425
75678
|
to: {
|
|
75426
|
-
fullscreen:
|
|
75427
|
-
|
|
75428
|
-
|
|
75429
|
-
|
|
75430
|
-
|
|
75431
|
-
|
|
75432
|
-
|
|
75433
|
-
|
|
75434
|
-
|
|
75435
|
-
|
|
75436
|
-
|
|
75437
|
-
|
|
75438
|
-
|
|
75439
|
-
|
|
75440
|
-
|
|
75441
|
-
|
|
75442
|
-
|
|
75443
|
-
|
|
75444
|
-
|
|
75445
|
-
|
|
75446
|
-
|
|
75447
|
-
|
|
75448
|
-
|
|
75449
|
-
|
|
75450
|
-
|
|
75451
|
-
|
|
75452
|
-
|
|
75453
|
-
|
|
75454
|
-
|
|
75679
|
+
fullscreen: (() => {
|
|
75680
|
+
const targetSources = transitionContext?.targetSources ?? [];
|
|
75681
|
+
const targetSource = targetSources[0];
|
|
75682
|
+
const targetInQrLbar = targetSource && qrLbarSources.includes(targetSource);
|
|
75683
|
+
if (targetInQrLbar) {
|
|
75684
|
+
return [
|
|
75685
|
+
{
|
|
75686
|
+
durationMs: 500,
|
|
75687
|
+
layout: {
|
|
75688
|
+
layers: [
|
|
75689
|
+
{
|
|
75690
|
+
sourceName: overlaySource,
|
|
75691
|
+
id: "overlay",
|
|
75692
|
+
zIndex: 0,
|
|
75693
|
+
opacity: overlaySource === targetSource ? 1 : 0,
|
|
75694
|
+
sourceRect: void 0,
|
|
75695
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
75696
|
+
},
|
|
75697
|
+
{
|
|
75698
|
+
sourceName: videoSource,
|
|
75699
|
+
id: "video",
|
|
75700
|
+
zIndex: 1,
|
|
75701
|
+
opacity: videoSource === targetSource ? 1 : 0,
|
|
75702
|
+
sourceRect: void 0,
|
|
75703
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
75704
|
+
},
|
|
75705
|
+
{
|
|
75706
|
+
sourceName: qrSource,
|
|
75707
|
+
id: "qr",
|
|
75708
|
+
zIndex: 2,
|
|
75709
|
+
opacity: qrSource === targetSource ? 1 : 0,
|
|
75710
|
+
sourceRect: void 0,
|
|
75711
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
75712
|
+
}
|
|
75713
|
+
]
|
|
75455
75714
|
}
|
|
75456
|
-
|
|
75457
|
-
|
|
75715
|
+
},
|
|
75716
|
+
// Final step: target source only
|
|
75717
|
+
{
|
|
75718
|
+
durationMs: 0,
|
|
75719
|
+
layout: {
|
|
75720
|
+
layers: [{
|
|
75721
|
+
sourceName: targetSource,
|
|
75722
|
+
zIndex: 0,
|
|
75723
|
+
opacity: 1,
|
|
75724
|
+
id: targetSource,
|
|
75725
|
+
sourceRect: void 0,
|
|
75726
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
75727
|
+
}]
|
|
75728
|
+
}
|
|
75729
|
+
}
|
|
75730
|
+
];
|
|
75731
|
+
} else {
|
|
75732
|
+
return [
|
|
75733
|
+
{
|
|
75734
|
+
durationMs: 250,
|
|
75735
|
+
layout: {
|
|
75736
|
+
layers: [
|
|
75737
|
+
{
|
|
75738
|
+
sourceName: overlaySource,
|
|
75739
|
+
id: "overlay",
|
|
75740
|
+
zIndex: 0,
|
|
75741
|
+
opacity: 0,
|
|
75742
|
+
sourceRect: void 0,
|
|
75743
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
75744
|
+
},
|
|
75745
|
+
{
|
|
75746
|
+
sourceName: videoSource,
|
|
75747
|
+
id: "video",
|
|
75748
|
+
zIndex: 1,
|
|
75749
|
+
opacity: 0,
|
|
75750
|
+
sourceRect: void 0,
|
|
75751
|
+
destRect: { x: videoX, y: videoY, width: videoWidth, height: videoHeight }
|
|
75752
|
+
},
|
|
75753
|
+
{
|
|
75754
|
+
sourceName: qrSource,
|
|
75755
|
+
id: "qr",
|
|
75756
|
+
zIndex: 2,
|
|
75757
|
+
opacity: 0,
|
|
75758
|
+
sourceRect: void 0,
|
|
75759
|
+
destRect: { x: qrPosition.x, y: qrPosition.y, width: qrWidth, height: qrHeight }
|
|
75760
|
+
}
|
|
75761
|
+
]
|
|
75762
|
+
}
|
|
75763
|
+
},
|
|
75764
|
+
...targetSource ? [{
|
|
75765
|
+
durationMs: 250,
|
|
75766
|
+
layout: {
|
|
75767
|
+
layers: [{
|
|
75768
|
+
sourceName: targetSource,
|
|
75769
|
+
zIndex: 0,
|
|
75770
|
+
opacity: 1,
|
|
75771
|
+
id: targetSource,
|
|
75772
|
+
sourceRect: void 0,
|
|
75773
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
75774
|
+
}]
|
|
75775
|
+
}
|
|
75776
|
+
}] : []
|
|
75777
|
+
];
|
|
75458
75778
|
}
|
|
75459
|
-
|
|
75779
|
+
})()
|
|
75460
75780
|
}
|
|
75461
75781
|
}
|
|
75462
75782
|
};
|
|
75463
75783
|
},
|
|
75464
|
-
"3-split": (sources, _config, res) => {
|
|
75784
|
+
"3-split": (sources, _config, res, transitionContext) => {
|
|
75465
75785
|
const third_w = res.width / 3;
|
|
75466
75786
|
const splits = sources.slice(0, 3);
|
|
75467
75787
|
return {
|
|
@@ -75561,21 +75881,76 @@ var PRESETS = {
|
|
|
75561
75881
|
]
|
|
75562
75882
|
},
|
|
75563
75883
|
to: {
|
|
75564
|
-
fullscreen:
|
|
75565
|
-
|
|
75566
|
-
|
|
75567
|
-
|
|
75568
|
-
|
|
75569
|
-
|
|
75570
|
-
|
|
75571
|
-
|
|
75572
|
-
|
|
75573
|
-
|
|
75574
|
-
|
|
75575
|
-
|
|
75576
|
-
|
|
75884
|
+
fullscreen: (() => {
|
|
75885
|
+
const targetSources = transitionContext?.targetSources ?? [];
|
|
75886
|
+
const targetSource = targetSources[0];
|
|
75887
|
+
const targetInSplits = targetSource && splits.includes(targetSource);
|
|
75888
|
+
if (targetInSplits) {
|
|
75889
|
+
return [
|
|
75890
|
+
{
|
|
75891
|
+
durationMs: 500,
|
|
75892
|
+
layout: {
|
|
75893
|
+
layers: splits.map((s, i) => ({
|
|
75894
|
+
sourceName: s,
|
|
75895
|
+
zIndex: i,
|
|
75896
|
+
opacity: s === targetSource ? 1 : 0,
|
|
75897
|
+
id: s,
|
|
75898
|
+
sourceRect: void 0,
|
|
75899
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
75900
|
+
}))
|
|
75901
|
+
}
|
|
75902
|
+
},
|
|
75903
|
+
// Final step: target source only
|
|
75904
|
+
{
|
|
75905
|
+
durationMs: 0,
|
|
75906
|
+
layout: {
|
|
75907
|
+
layers: [{
|
|
75908
|
+
sourceName: targetSource,
|
|
75909
|
+
zIndex: 0,
|
|
75910
|
+
opacity: 1,
|
|
75911
|
+
id: targetSource,
|
|
75912
|
+
sourceRect: void 0,
|
|
75913
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
75914
|
+
}]
|
|
75915
|
+
}
|
|
75916
|
+
}
|
|
75917
|
+
];
|
|
75918
|
+
} else {
|
|
75919
|
+
return [
|
|
75920
|
+
{
|
|
75921
|
+
durationMs: 250,
|
|
75922
|
+
layout: {
|
|
75923
|
+
layers: splits.map((s, i) => ({
|
|
75924
|
+
sourceName: s,
|
|
75925
|
+
zIndex: i,
|
|
75926
|
+
opacity: 0,
|
|
75927
|
+
id: s,
|
|
75928
|
+
sourceRect: void 0,
|
|
75929
|
+
destRect: {
|
|
75930
|
+
x: i * third_w,
|
|
75931
|
+
y: 0,
|
|
75932
|
+
width: third_w,
|
|
75933
|
+
height: res.height
|
|
75934
|
+
}
|
|
75935
|
+
}))
|
|
75936
|
+
}
|
|
75937
|
+
},
|
|
75938
|
+
...targetSource ? [{
|
|
75939
|
+
durationMs: 250,
|
|
75940
|
+
layout: {
|
|
75941
|
+
layers: [{
|
|
75942
|
+
sourceName: targetSource,
|
|
75943
|
+
zIndex: 0,
|
|
75944
|
+
opacity: 1,
|
|
75945
|
+
id: targetSource,
|
|
75946
|
+
sourceRect: void 0,
|
|
75947
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
75948
|
+
}]
|
|
75949
|
+
}
|
|
75950
|
+
}] : []
|
|
75951
|
+
];
|
|
75577
75952
|
}
|
|
75578
|
-
|
|
75953
|
+
})(),
|
|
75579
75954
|
"side-by-side": [
|
|
75580
75955
|
// 3-split → Side-by-side: expand first 2 from 33.33% to 50%, fade out third
|
|
75581
75956
|
{
|
|
@@ -75644,9 +76019,10 @@ var PRESETS = {
|
|
|
75644
76019
|
} : void 0
|
|
75645
76020
|
};
|
|
75646
76021
|
},
|
|
75647
|
-
"2-crop": (sources, config, res) => {
|
|
76022
|
+
"2-crop": (sources, config, res, transitionContext) => {
|
|
75648
76023
|
const [left, right] = sources.slice(0, 2);
|
|
75649
76024
|
const half_w = res.width / 2;
|
|
76025
|
+
const cropSources = [left, right].filter(Boolean);
|
|
75650
76026
|
const crops = config.crops || {};
|
|
75651
76027
|
return {
|
|
75652
76028
|
name: "2-crop",
|
|
@@ -75722,31 +76098,91 @@ var PRESETS = {
|
|
|
75722
76098
|
]
|
|
75723
76099
|
},
|
|
75724
76100
|
to: {
|
|
75725
|
-
fullscreen:
|
|
75726
|
-
|
|
75727
|
-
|
|
75728
|
-
|
|
75729
|
-
|
|
75730
|
-
|
|
75731
|
-
|
|
75732
|
-
|
|
75733
|
-
|
|
75734
|
-
|
|
75735
|
-
|
|
75736
|
-
|
|
75737
|
-
|
|
75738
|
-
|
|
75739
|
-
|
|
75740
|
-
|
|
75741
|
-
|
|
75742
|
-
|
|
75743
|
-
|
|
75744
|
-
|
|
76101
|
+
fullscreen: (() => {
|
|
76102
|
+
const targetSources = transitionContext?.targetSources ?? [];
|
|
76103
|
+
const targetSource = targetSources[0];
|
|
76104
|
+
const targetInCrops = targetSource && cropSources.includes(targetSource);
|
|
76105
|
+
if (targetInCrops) {
|
|
76106
|
+
return [
|
|
76107
|
+
{
|
|
76108
|
+
durationMs: 500,
|
|
76109
|
+
layout: {
|
|
76110
|
+
layers: [
|
|
76111
|
+
{
|
|
76112
|
+
sourceName: left,
|
|
76113
|
+
zIndex: 0,
|
|
76114
|
+
opacity: left === targetSource ? 1 : 0,
|
|
76115
|
+
id: left,
|
|
76116
|
+
sourceRect: void 0,
|
|
76117
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
76118
|
+
},
|
|
76119
|
+
{
|
|
76120
|
+
sourceName: right,
|
|
76121
|
+
zIndex: 1,
|
|
76122
|
+
opacity: right === targetSource ? 1 : 0,
|
|
76123
|
+
id: right,
|
|
76124
|
+
sourceRect: void 0,
|
|
76125
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
76126
|
+
}
|
|
76127
|
+
]
|
|
75745
76128
|
}
|
|
75746
|
-
|
|
75747
|
-
|
|
76129
|
+
},
|
|
76130
|
+
// Final step: target source only
|
|
76131
|
+
{
|
|
76132
|
+
durationMs: 0,
|
|
76133
|
+
layout: {
|
|
76134
|
+
layers: [{
|
|
76135
|
+
sourceName: targetSource,
|
|
76136
|
+
zIndex: 0,
|
|
76137
|
+
opacity: 1,
|
|
76138
|
+
id: targetSource,
|
|
76139
|
+
sourceRect: void 0,
|
|
76140
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
76141
|
+
}]
|
|
76142
|
+
}
|
|
76143
|
+
}
|
|
76144
|
+
];
|
|
76145
|
+
} else {
|
|
76146
|
+
return [
|
|
76147
|
+
{
|
|
76148
|
+
durationMs: 250,
|
|
76149
|
+
layout: {
|
|
76150
|
+
layers: [
|
|
76151
|
+
{
|
|
76152
|
+
sourceName: left,
|
|
76153
|
+
zIndex: 0,
|
|
76154
|
+
opacity: 0,
|
|
76155
|
+
id: left,
|
|
76156
|
+
sourceRect: crops[left] || void 0,
|
|
76157
|
+
destRect: { x: 0, y: 0, width: half_w, height: res.height }
|
|
76158
|
+
},
|
|
76159
|
+
{
|
|
76160
|
+
sourceName: right,
|
|
76161
|
+
zIndex: 1,
|
|
76162
|
+
opacity: 0,
|
|
76163
|
+
id: right,
|
|
76164
|
+
sourceRect: crops[right] || void 0,
|
|
76165
|
+
destRect: { x: half_w, y: 0, width: half_w, height: res.height }
|
|
76166
|
+
}
|
|
76167
|
+
]
|
|
76168
|
+
}
|
|
76169
|
+
},
|
|
76170
|
+
...targetSource ? [{
|
|
76171
|
+
durationMs: 250,
|
|
76172
|
+
layout: {
|
|
76173
|
+
layers: [{
|
|
76174
|
+
sourceName: targetSource,
|
|
76175
|
+
zIndex: 0,
|
|
76176
|
+
opacity: 1,
|
|
76177
|
+
id: targetSource,
|
|
76178
|
+
sourceRect: void 0,
|
|
76179
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
76180
|
+
}]
|
|
76181
|
+
}
|
|
76182
|
+
}] : []
|
|
76183
|
+
];
|
|
75748
76184
|
}
|
|
75749
|
-
|
|
76185
|
+
})(),
|
|
75750
76186
|
"3-crop": [
|
|
75751
76187
|
// 2-crop → 3-crop: compress both from 50% to 33.33% width, adjust crop
|
|
75752
76188
|
{
|
|
@@ -75803,7 +76239,7 @@ var PRESETS = {
|
|
|
75803
76239
|
} : void 0
|
|
75804
76240
|
};
|
|
75805
76241
|
},
|
|
75806
|
-
"3-crop": (sources, config, res) => {
|
|
76242
|
+
"3-crop": (sources, config, res, transitionContext) => {
|
|
75807
76243
|
const third_w = res.width / 3;
|
|
75808
76244
|
const cropSources = sources.slice(0, 3);
|
|
75809
76245
|
const cropConfig = config.crops || {};
|
|
@@ -75861,21 +76297,76 @@ var PRESETS = {
|
|
|
75861
76297
|
]
|
|
75862
76298
|
},
|
|
75863
76299
|
to: {
|
|
75864
|
-
fullscreen:
|
|
75865
|
-
|
|
75866
|
-
|
|
75867
|
-
|
|
75868
|
-
|
|
75869
|
-
|
|
75870
|
-
|
|
75871
|
-
|
|
75872
|
-
|
|
75873
|
-
|
|
75874
|
-
|
|
75875
|
-
|
|
75876
|
-
|
|
76300
|
+
fullscreen: (() => {
|
|
76301
|
+
const targetSources = transitionContext?.targetSources ?? [];
|
|
76302
|
+
const targetSource = targetSources[0];
|
|
76303
|
+
const targetInCrops = targetSource && cropSources.includes(targetSource);
|
|
76304
|
+
if (targetInCrops) {
|
|
76305
|
+
return [
|
|
76306
|
+
{
|
|
76307
|
+
durationMs: 500,
|
|
76308
|
+
layout: {
|
|
76309
|
+
layers: cropSources.map((s, i) => ({
|
|
76310
|
+
sourceName: s,
|
|
76311
|
+
zIndex: i,
|
|
76312
|
+
opacity: s === targetSource ? 1 : 0,
|
|
76313
|
+
id: s,
|
|
76314
|
+
sourceRect: void 0,
|
|
76315
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
76316
|
+
}))
|
|
76317
|
+
}
|
|
76318
|
+
},
|
|
76319
|
+
// Final step: target source only
|
|
76320
|
+
{
|
|
76321
|
+
durationMs: 0,
|
|
76322
|
+
layout: {
|
|
76323
|
+
layers: [{
|
|
76324
|
+
sourceName: targetSource,
|
|
76325
|
+
zIndex: 0,
|
|
76326
|
+
opacity: 1,
|
|
76327
|
+
id: targetSource,
|
|
76328
|
+
sourceRect: void 0,
|
|
76329
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
76330
|
+
}]
|
|
76331
|
+
}
|
|
76332
|
+
}
|
|
76333
|
+
];
|
|
76334
|
+
} else {
|
|
76335
|
+
return [
|
|
76336
|
+
{
|
|
76337
|
+
durationMs: 250,
|
|
76338
|
+
layout: {
|
|
76339
|
+
layers: cropSources.map((s, i) => ({
|
|
76340
|
+
sourceName: s,
|
|
76341
|
+
zIndex: i,
|
|
76342
|
+
opacity: 0,
|
|
76343
|
+
id: s,
|
|
76344
|
+
sourceRect: cropConfig[s] || void 0,
|
|
76345
|
+
destRect: {
|
|
76346
|
+
x: i * third_w,
|
|
76347
|
+
y: 0,
|
|
76348
|
+
width: third_w,
|
|
76349
|
+
height: res.height
|
|
76350
|
+
}
|
|
76351
|
+
}))
|
|
76352
|
+
}
|
|
76353
|
+
},
|
|
76354
|
+
...targetSource ? [{
|
|
76355
|
+
durationMs: 250,
|
|
76356
|
+
layout: {
|
|
76357
|
+
layers: [{
|
|
76358
|
+
sourceName: targetSource,
|
|
76359
|
+
zIndex: 0,
|
|
76360
|
+
opacity: 1,
|
|
76361
|
+
id: targetSource,
|
|
76362
|
+
sourceRect: void 0,
|
|
76363
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
76364
|
+
}]
|
|
76365
|
+
}
|
|
76366
|
+
}] : []
|
|
76367
|
+
];
|
|
75877
76368
|
}
|
|
75878
|
-
|
|
76369
|
+
})(),
|
|
75879
76370
|
"2-crop": [
|
|
75880
76371
|
// 3-crop → 2-crop: expand first 2 from 33.33% to 50%, adjust crop, fade out 3rd
|
|
75881
76372
|
{
|
|
@@ -75909,8 +76400,9 @@ var PRESETS = {
|
|
|
75909
76400
|
} : void 0
|
|
75910
76401
|
};
|
|
75911
76402
|
},
|
|
75912
|
-
"2-crop-left": (sources, config, res) => {
|
|
76403
|
+
"2-crop-left": (sources, config, res, transitionContext) => {
|
|
75913
76404
|
const [background, left, right] = sources.slice(0, 3);
|
|
76405
|
+
const cropLeftSources = [background, left, right].filter(Boolean);
|
|
75914
76406
|
const cropConfig = config.crops || {};
|
|
75915
76407
|
const leftW = res.width * 0.34;
|
|
75916
76408
|
const rightW = res.width * 0.66666;
|
|
@@ -76015,39 +76507,107 @@ var PRESETS = {
|
|
|
76015
76507
|
]
|
|
76016
76508
|
},
|
|
76017
76509
|
to: {
|
|
76018
|
-
fullscreen:
|
|
76019
|
-
|
|
76020
|
-
|
|
76021
|
-
|
|
76022
|
-
|
|
76023
|
-
|
|
76024
|
-
|
|
76025
|
-
|
|
76026
|
-
|
|
76027
|
-
|
|
76028
|
-
|
|
76029
|
-
|
|
76030
|
-
|
|
76031
|
-
|
|
76032
|
-
|
|
76033
|
-
|
|
76034
|
-
|
|
76035
|
-
|
|
76036
|
-
|
|
76037
|
-
|
|
76038
|
-
|
|
76039
|
-
|
|
76040
|
-
|
|
76041
|
-
|
|
76042
|
-
|
|
76043
|
-
|
|
76044
|
-
|
|
76045
|
-
|
|
76510
|
+
fullscreen: (() => {
|
|
76511
|
+
const targetSources = transitionContext?.targetSources ?? [];
|
|
76512
|
+
const targetSource = targetSources[0];
|
|
76513
|
+
const targetInCrops = targetSource && cropLeftSources.includes(targetSource);
|
|
76514
|
+
if (targetInCrops) {
|
|
76515
|
+
return [
|
|
76516
|
+
{
|
|
76517
|
+
durationMs: 500,
|
|
76518
|
+
layout: {
|
|
76519
|
+
layers: [
|
|
76520
|
+
{
|
|
76521
|
+
sourceName: background,
|
|
76522
|
+
zIndex: 0,
|
|
76523
|
+
opacity: background === targetSource ? 1 : 0,
|
|
76524
|
+
id: background,
|
|
76525
|
+
sourceRect: void 0,
|
|
76526
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
76527
|
+
},
|
|
76528
|
+
{
|
|
76529
|
+
sourceName: left,
|
|
76530
|
+
zIndex: 1,
|
|
76531
|
+
opacity: left === targetSource ? 1 : 0,
|
|
76532
|
+
id: left,
|
|
76533
|
+
sourceRect: void 0,
|
|
76534
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
76535
|
+
},
|
|
76536
|
+
{
|
|
76537
|
+
sourceName: right,
|
|
76538
|
+
zIndex: 2,
|
|
76539
|
+
opacity: right === targetSource ? 1 : 0,
|
|
76540
|
+
id: right,
|
|
76541
|
+
sourceRect: void 0,
|
|
76542
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
76543
|
+
}
|
|
76544
|
+
]
|
|
76046
76545
|
}
|
|
76047
|
-
|
|
76048
|
-
|
|
76546
|
+
},
|
|
76547
|
+
// Final step: target source only
|
|
76548
|
+
{
|
|
76549
|
+
durationMs: 0,
|
|
76550
|
+
layout: {
|
|
76551
|
+
layers: [{
|
|
76552
|
+
sourceName: targetSource,
|
|
76553
|
+
zIndex: 0,
|
|
76554
|
+
opacity: 1,
|
|
76555
|
+
id: targetSource,
|
|
76556
|
+
sourceRect: void 0,
|
|
76557
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
76558
|
+
}]
|
|
76559
|
+
}
|
|
76560
|
+
}
|
|
76561
|
+
];
|
|
76562
|
+
} else {
|
|
76563
|
+
return [
|
|
76564
|
+
{
|
|
76565
|
+
durationMs: 250,
|
|
76566
|
+
layout: {
|
|
76567
|
+
layers: [
|
|
76568
|
+
{
|
|
76569
|
+
sourceName: background,
|
|
76570
|
+
zIndex: 0,
|
|
76571
|
+
opacity: 0,
|
|
76572
|
+
id: background,
|
|
76573
|
+
sourceRect: void 0,
|
|
76574
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
76575
|
+
},
|
|
76576
|
+
{
|
|
76577
|
+
sourceName: left,
|
|
76578
|
+
zIndex: 1,
|
|
76579
|
+
opacity: 0,
|
|
76580
|
+
id: left,
|
|
76581
|
+
sourceRect: cropConfig[left] || void 0,
|
|
76582
|
+
destRect: { x: 0, y: yPos, width: leftW, height: boxH }
|
|
76583
|
+
},
|
|
76584
|
+
{
|
|
76585
|
+
sourceName: right,
|
|
76586
|
+
zIndex: 2,
|
|
76587
|
+
opacity: 0,
|
|
76588
|
+
id: right,
|
|
76589
|
+
sourceRect: void 0,
|
|
76590
|
+
destRect: { x: rightX, y: yPos, width: rightW, height: boxH }
|
|
76591
|
+
}
|
|
76592
|
+
]
|
|
76593
|
+
}
|
|
76594
|
+
},
|
|
76595
|
+
...targetSource ? [{
|
|
76596
|
+
durationMs: 250,
|
|
76597
|
+
layout: {
|
|
76598
|
+
layers: [{
|
|
76599
|
+
sourceName: targetSource,
|
|
76600
|
+
zIndex: 0,
|
|
76601
|
+
opacity: 1,
|
|
76602
|
+
id: targetSource,
|
|
76603
|
+
sourceRect: void 0,
|
|
76604
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
76605
|
+
}]
|
|
76606
|
+
}
|
|
76607
|
+
}] : []
|
|
76608
|
+
];
|
|
76049
76609
|
}
|
|
76050
|
-
|
|
76610
|
+
})(),
|
|
76051
76611
|
"2-crop-right": [
|
|
76052
76612
|
// 2-crop-left → 2-crop-right: swap positions and crop states
|
|
76053
76613
|
{
|
|
@@ -76088,8 +76648,9 @@ var PRESETS = {
|
|
|
76088
76648
|
} : void 0
|
|
76089
76649
|
};
|
|
76090
76650
|
},
|
|
76091
|
-
"2-crop-right": (sources, config, res) => {
|
|
76651
|
+
"2-crop-right": (sources, config, res, transitionContext) => {
|
|
76092
76652
|
const [background, left, right] = sources.slice(0, 3);
|
|
76653
|
+
const cropRightSources = [background, left, right].filter(Boolean);
|
|
76093
76654
|
const cropConfig = config.crops || {};
|
|
76094
76655
|
const leftW = res.width * 0.67;
|
|
76095
76656
|
const rightW = res.width * 0.33333;
|
|
@@ -76194,39 +76755,107 @@ var PRESETS = {
|
|
|
76194
76755
|
]
|
|
76195
76756
|
},
|
|
76196
76757
|
to: {
|
|
76197
|
-
fullscreen:
|
|
76198
|
-
|
|
76199
|
-
|
|
76200
|
-
|
|
76201
|
-
|
|
76202
|
-
|
|
76203
|
-
|
|
76204
|
-
|
|
76205
|
-
|
|
76206
|
-
|
|
76207
|
-
|
|
76208
|
-
|
|
76209
|
-
|
|
76210
|
-
|
|
76211
|
-
|
|
76212
|
-
|
|
76213
|
-
|
|
76214
|
-
|
|
76215
|
-
|
|
76216
|
-
|
|
76217
|
-
|
|
76218
|
-
|
|
76219
|
-
|
|
76220
|
-
|
|
76221
|
-
|
|
76222
|
-
|
|
76223
|
-
|
|
76224
|
-
|
|
76758
|
+
fullscreen: (() => {
|
|
76759
|
+
const targetSources = transitionContext?.targetSources ?? [];
|
|
76760
|
+
const targetSource = targetSources[0];
|
|
76761
|
+
const targetInCrops = targetSource && cropRightSources.includes(targetSource);
|
|
76762
|
+
if (targetInCrops) {
|
|
76763
|
+
return [
|
|
76764
|
+
{
|
|
76765
|
+
durationMs: 500,
|
|
76766
|
+
layout: {
|
|
76767
|
+
layers: [
|
|
76768
|
+
{
|
|
76769
|
+
sourceName: background,
|
|
76770
|
+
zIndex: 0,
|
|
76771
|
+
opacity: background === targetSource ? 1 : 0,
|
|
76772
|
+
id: background,
|
|
76773
|
+
sourceRect: void 0,
|
|
76774
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
76775
|
+
},
|
|
76776
|
+
{
|
|
76777
|
+
sourceName: left,
|
|
76778
|
+
zIndex: 1,
|
|
76779
|
+
opacity: left === targetSource ? 1 : 0,
|
|
76780
|
+
id: left,
|
|
76781
|
+
sourceRect: void 0,
|
|
76782
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
76783
|
+
},
|
|
76784
|
+
{
|
|
76785
|
+
sourceName: right,
|
|
76786
|
+
zIndex: 2,
|
|
76787
|
+
opacity: right === targetSource ? 1 : 0,
|
|
76788
|
+
id: right,
|
|
76789
|
+
sourceRect: void 0,
|
|
76790
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
76791
|
+
}
|
|
76792
|
+
]
|
|
76225
76793
|
}
|
|
76226
|
-
|
|
76227
|
-
|
|
76794
|
+
},
|
|
76795
|
+
// Final step: target source only
|
|
76796
|
+
{
|
|
76797
|
+
durationMs: 0,
|
|
76798
|
+
layout: {
|
|
76799
|
+
layers: [{
|
|
76800
|
+
sourceName: targetSource,
|
|
76801
|
+
zIndex: 0,
|
|
76802
|
+
opacity: 1,
|
|
76803
|
+
id: targetSource,
|
|
76804
|
+
sourceRect: void 0,
|
|
76805
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
76806
|
+
}]
|
|
76807
|
+
}
|
|
76808
|
+
}
|
|
76809
|
+
];
|
|
76810
|
+
} else {
|
|
76811
|
+
return [
|
|
76812
|
+
{
|
|
76813
|
+
durationMs: 250,
|
|
76814
|
+
layout: {
|
|
76815
|
+
layers: [
|
|
76816
|
+
{
|
|
76817
|
+
sourceName: background,
|
|
76818
|
+
zIndex: 0,
|
|
76819
|
+
opacity: 0,
|
|
76820
|
+
id: background,
|
|
76821
|
+
sourceRect: void 0,
|
|
76822
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
76823
|
+
},
|
|
76824
|
+
{
|
|
76825
|
+
sourceName: left,
|
|
76826
|
+
zIndex: 1,
|
|
76827
|
+
opacity: 0,
|
|
76828
|
+
id: left,
|
|
76829
|
+
sourceRect: void 0,
|
|
76830
|
+
destRect: { x: 0, y: yPos, width: leftW, height: boxH }
|
|
76831
|
+
},
|
|
76832
|
+
{
|
|
76833
|
+
sourceName: right,
|
|
76834
|
+
zIndex: 2,
|
|
76835
|
+
opacity: 0,
|
|
76836
|
+
id: right,
|
|
76837
|
+
sourceRect: cropConfig[right] || void 0,
|
|
76838
|
+
destRect: { x: rightX, y: yPos, width: rightW, height: boxH }
|
|
76839
|
+
}
|
|
76840
|
+
]
|
|
76841
|
+
}
|
|
76842
|
+
},
|
|
76843
|
+
...targetSource ? [{
|
|
76844
|
+
durationMs: 250,
|
|
76845
|
+
layout: {
|
|
76846
|
+
layers: [{
|
|
76847
|
+
sourceName: targetSource,
|
|
76848
|
+
zIndex: 0,
|
|
76849
|
+
opacity: 1,
|
|
76850
|
+
id: targetSource,
|
|
76851
|
+
sourceRect: void 0,
|
|
76852
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
76853
|
+
}]
|
|
76854
|
+
}
|
|
76855
|
+
}] : []
|
|
76856
|
+
];
|
|
76228
76857
|
}
|
|
76229
|
-
|
|
76858
|
+
})(),
|
|
76230
76859
|
"2-crop-left": [
|
|
76231
76860
|
// 2-crop-right → 2-crop-left: swap positions and crop states
|
|
76232
76861
|
{
|
|
@@ -76267,9 +76896,10 @@ var PRESETS = {
|
|
|
76267
76896
|
} : void 0
|
|
76268
76897
|
};
|
|
76269
76898
|
},
|
|
76270
|
-
"5-split": (sources, config, res) => {
|
|
76899
|
+
"5-split": (sources, config, res, transitionContext) => {
|
|
76271
76900
|
const [background, ...vidSources] = sources.slice(0, 6);
|
|
76272
76901
|
const fiveSources = vidSources.slice(0, 5);
|
|
76902
|
+
const allSplitSources = [background, ...fiveSources].filter(Boolean);
|
|
76273
76903
|
const cropConfig = config.crops || {};
|
|
76274
76904
|
const boxW = res.width * 0.34;
|
|
76275
76905
|
const boxH = res.height * 0.5;
|
|
@@ -76361,36 +76991,101 @@ var PRESETS = {
|
|
|
76361
76991
|
]
|
|
76362
76992
|
},
|
|
76363
76993
|
to: {
|
|
76364
|
-
fullscreen:
|
|
76365
|
-
|
|
76366
|
-
|
|
76367
|
-
|
|
76368
|
-
|
|
76369
|
-
|
|
76370
|
-
|
|
76371
|
-
|
|
76372
|
-
|
|
76373
|
-
|
|
76374
|
-
|
|
76375
|
-
|
|
76376
|
-
|
|
76377
|
-
|
|
76378
|
-
|
|
76379
|
-
|
|
76380
|
-
|
|
76381
|
-
|
|
76382
|
-
|
|
76383
|
-
|
|
76384
|
-
|
|
76385
|
-
|
|
76386
|
-
|
|
76994
|
+
fullscreen: (() => {
|
|
76995
|
+
const targetSources = transitionContext?.targetSources ?? [];
|
|
76996
|
+
const targetSource = targetSources[0];
|
|
76997
|
+
const targetInSplit = targetSource && allSplitSources.includes(targetSource);
|
|
76998
|
+
if (targetInSplit) {
|
|
76999
|
+
return [
|
|
77000
|
+
{
|
|
77001
|
+
durationMs: 500,
|
|
77002
|
+
layout: {
|
|
77003
|
+
layers: [
|
|
77004
|
+
{
|
|
77005
|
+
sourceName: background,
|
|
77006
|
+
zIndex: 0,
|
|
77007
|
+
opacity: background === targetSource ? 1 : 0,
|
|
77008
|
+
id: background,
|
|
77009
|
+
sourceRect: void 0,
|
|
77010
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
77011
|
+
},
|
|
77012
|
+
...fiveSources.map((s, i) => ({
|
|
77013
|
+
sourceName: s,
|
|
77014
|
+
zIndex: i + 1,
|
|
77015
|
+
opacity: s === targetSource ? 1 : 0,
|
|
77016
|
+
id: s,
|
|
77017
|
+
sourceRect: void 0,
|
|
77018
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
77019
|
+
}))
|
|
77020
|
+
]
|
|
77021
|
+
}
|
|
77022
|
+
},
|
|
77023
|
+
// Final step: target source only
|
|
77024
|
+
{
|
|
77025
|
+
durationMs: 0,
|
|
77026
|
+
layout: {
|
|
77027
|
+
layers: [{
|
|
77028
|
+
sourceName: targetSource,
|
|
77029
|
+
zIndex: 0,
|
|
77030
|
+
opacity: 1,
|
|
77031
|
+
id: targetSource,
|
|
77032
|
+
sourceRect: void 0,
|
|
77033
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
77034
|
+
}]
|
|
77035
|
+
}
|
|
77036
|
+
}
|
|
77037
|
+
];
|
|
77038
|
+
} else {
|
|
77039
|
+
return [
|
|
77040
|
+
{
|
|
77041
|
+
durationMs: 250,
|
|
77042
|
+
layout: {
|
|
77043
|
+
layers: [
|
|
77044
|
+
{
|
|
77045
|
+
sourceName: background,
|
|
77046
|
+
zIndex: 0,
|
|
77047
|
+
opacity: 0,
|
|
77048
|
+
id: background,
|
|
77049
|
+
sourceRect: void 0,
|
|
77050
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
77051
|
+
},
|
|
77052
|
+
...fiveSources.map((s, i) => {
|
|
77053
|
+
const isTopRow = i < 2;
|
|
77054
|
+
const xPos = isTopRow ? topPositions[i] : bottomPositions[i - 2];
|
|
77055
|
+
const yPosCalc = isTopRow ? topY : bottomY;
|
|
77056
|
+
return {
|
|
77057
|
+
sourceName: s,
|
|
77058
|
+
zIndex: i + 1,
|
|
77059
|
+
opacity: 0,
|
|
77060
|
+
id: s,
|
|
77061
|
+
sourceRect: cropConfig[s] || void 0,
|
|
77062
|
+
destRect: { x: xPos - boxW / 2, y: yPosCalc - boxH / 2, width: boxW, height: boxH }
|
|
77063
|
+
};
|
|
77064
|
+
})
|
|
77065
|
+
]
|
|
77066
|
+
}
|
|
77067
|
+
},
|
|
77068
|
+
...targetSource ? [{
|
|
77069
|
+
durationMs: 250,
|
|
77070
|
+
layout: {
|
|
77071
|
+
layers: [{
|
|
77072
|
+
sourceName: targetSource,
|
|
77073
|
+
zIndex: 0,
|
|
77074
|
+
opacity: 1,
|
|
77075
|
+
id: targetSource,
|
|
77076
|
+
sourceRect: void 0,
|
|
77077
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
77078
|
+
}]
|
|
77079
|
+
}
|
|
77080
|
+
}] : []
|
|
77081
|
+
];
|
|
76387
77082
|
}
|
|
76388
|
-
|
|
77083
|
+
})()
|
|
76389
77084
|
}
|
|
76390
77085
|
} : void 0
|
|
76391
77086
|
};
|
|
76392
77087
|
},
|
|
76393
|
-
"6-split": (sources, config, res) => {
|
|
77088
|
+
"6-split": (sources, config, res, transitionContext) => {
|
|
76394
77089
|
const sixSources = sources.slice(0, 6);
|
|
76395
77090
|
const cropConfig = config.crops || {};
|
|
76396
77091
|
const boxW = res.width * 0.34;
|
|
@@ -76454,21 +77149,77 @@ var PRESETS = {
|
|
|
76454
77149
|
]
|
|
76455
77150
|
},
|
|
76456
77151
|
to: {
|
|
76457
|
-
fullscreen:
|
|
76458
|
-
|
|
76459
|
-
|
|
76460
|
-
|
|
76461
|
-
|
|
76462
|
-
|
|
76463
|
-
|
|
76464
|
-
|
|
76465
|
-
|
|
76466
|
-
|
|
76467
|
-
|
|
76468
|
-
|
|
76469
|
-
|
|
77152
|
+
fullscreen: (() => {
|
|
77153
|
+
const targetSources = transitionContext?.targetSources ?? [];
|
|
77154
|
+
const targetSource = targetSources[0];
|
|
77155
|
+
const targetInSplit = targetSource && sixSources.includes(targetSource);
|
|
77156
|
+
if (targetInSplit) {
|
|
77157
|
+
return [
|
|
77158
|
+
{
|
|
77159
|
+
durationMs: 500,
|
|
77160
|
+
layout: {
|
|
77161
|
+
layers: sixSources.map((s, i) => ({
|
|
77162
|
+
sourceName: s,
|
|
77163
|
+
zIndex: i,
|
|
77164
|
+
opacity: s === targetSource ? 1 : 0,
|
|
77165
|
+
id: s,
|
|
77166
|
+
sourceRect: void 0,
|
|
77167
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
77168
|
+
}))
|
|
77169
|
+
}
|
|
77170
|
+
},
|
|
77171
|
+
// Final step: target source only
|
|
77172
|
+
{
|
|
77173
|
+
durationMs: 0,
|
|
77174
|
+
layout: {
|
|
77175
|
+
layers: [{
|
|
77176
|
+
sourceName: targetSource,
|
|
77177
|
+
zIndex: 0,
|
|
77178
|
+
opacity: 1,
|
|
77179
|
+
id: targetSource,
|
|
77180
|
+
sourceRect: void 0,
|
|
77181
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
77182
|
+
}]
|
|
77183
|
+
}
|
|
77184
|
+
}
|
|
77185
|
+
];
|
|
77186
|
+
} else {
|
|
77187
|
+
return [
|
|
77188
|
+
{
|
|
77189
|
+
durationMs: 250,
|
|
77190
|
+
layout: {
|
|
77191
|
+
layers: sixSources.map((s, i) => {
|
|
77192
|
+
const row = Math.floor(i / 3);
|
|
77193
|
+
const col = i % 3;
|
|
77194
|
+
const yPos = row === 0 ? topY : bottomY;
|
|
77195
|
+
const xPos = xPositions[col];
|
|
77196
|
+
return {
|
|
77197
|
+
sourceName: s,
|
|
77198
|
+
zIndex: i,
|
|
77199
|
+
opacity: 0,
|
|
77200
|
+
id: s,
|
|
77201
|
+
sourceRect: cropConfig[s] || void 0,
|
|
77202
|
+
destRect: { x: xPos - boxW / 2, y: yPos - boxH / 2, width: boxW, height: boxH }
|
|
77203
|
+
};
|
|
77204
|
+
})
|
|
77205
|
+
}
|
|
77206
|
+
},
|
|
77207
|
+
...targetSource ? [{
|
|
77208
|
+
durationMs: 250,
|
|
77209
|
+
layout: {
|
|
77210
|
+
layers: [{
|
|
77211
|
+
sourceName: targetSource,
|
|
77212
|
+
zIndex: 0,
|
|
77213
|
+
opacity: 1,
|
|
77214
|
+
id: targetSource,
|
|
77215
|
+
sourceRect: void 0,
|
|
77216
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
77217
|
+
}]
|
|
77218
|
+
}
|
|
77219
|
+
}] : []
|
|
77220
|
+
];
|
|
76470
77221
|
}
|
|
76471
|
-
|
|
77222
|
+
})(),
|
|
76472
77223
|
"mosaic-9": [
|
|
76473
77224
|
// 6-split → mosaic-9: move to grid positions, fade to no crop
|
|
76474
77225
|
{
|
|
@@ -76503,8 +77254,9 @@ var PRESETS = {
|
|
|
76503
77254
|
};
|
|
76504
77255
|
}
|
|
76505
77256
|
};
|
|
76506
|
-
function createLBarPresetDefinition(sources, config, res) {
|
|
77257
|
+
function createLBarPresetDefinition(sources, config, res, transitionContext) {
|
|
76507
77258
|
const [videoSource, overlaySource] = sources;
|
|
77259
|
+
const lbarSources = [videoSource, overlaySource].filter(Boolean);
|
|
76508
77260
|
const { videoWidth, videoHeight, videoX = 0, videoY = 0 } = config;
|
|
76509
77261
|
return {
|
|
76510
77262
|
name: "lbar",
|
|
@@ -76584,32 +77336,91 @@ function createLBarPresetDefinition(sources, config, res) {
|
|
|
76584
77336
|
},
|
|
76585
77337
|
// Transition from L-bar to fullscreen (reverse)
|
|
76586
77338
|
to: {
|
|
76587
|
-
fullscreen:
|
|
76588
|
-
|
|
76589
|
-
|
|
76590
|
-
|
|
76591
|
-
|
|
76592
|
-
|
|
76593
|
-
|
|
76594
|
-
|
|
76595
|
-
|
|
76596
|
-
|
|
76597
|
-
|
|
76598
|
-
|
|
76599
|
-
|
|
76600
|
-
|
|
76601
|
-
|
|
76602
|
-
|
|
76603
|
-
|
|
76604
|
-
|
|
76605
|
-
|
|
76606
|
-
|
|
76607
|
-
|
|
77339
|
+
fullscreen: (() => {
|
|
77340
|
+
const targetSources = transitionContext?.targetSources ?? [];
|
|
77341
|
+
const targetSource = targetSources[0];
|
|
77342
|
+
const targetInLbar = targetSource && lbarSources.includes(targetSource);
|
|
77343
|
+
if (targetInLbar) {
|
|
77344
|
+
return [
|
|
77345
|
+
{
|
|
77346
|
+
durationMs: 500,
|
|
77347
|
+
layout: {
|
|
77348
|
+
layers: [
|
|
77349
|
+
{
|
|
77350
|
+
sourceName: overlaySource,
|
|
77351
|
+
id: "overlay",
|
|
77352
|
+
zIndex: 0,
|
|
77353
|
+
opacity: overlaySource === targetSource ? 1 : 0,
|
|
77354
|
+
sourceRect: void 0,
|
|
77355
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
77356
|
+
},
|
|
77357
|
+
{
|
|
77358
|
+
sourceName: videoSource,
|
|
77359
|
+
id: "video",
|
|
77360
|
+
zIndex: 1,
|
|
77361
|
+
opacity: videoSource === targetSource ? 1 : 0,
|
|
77362
|
+
sourceRect: void 0,
|
|
77363
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
77364
|
+
}
|
|
77365
|
+
]
|
|
76608
77366
|
}
|
|
76609
|
-
|
|
76610
|
-
|
|
77367
|
+
},
|
|
77368
|
+
// Final step: target source only
|
|
77369
|
+
{
|
|
77370
|
+
durationMs: 0,
|
|
77371
|
+
layout: {
|
|
77372
|
+
layers: [{
|
|
77373
|
+
sourceName: targetSource,
|
|
77374
|
+
zIndex: 0,
|
|
77375
|
+
opacity: 1,
|
|
77376
|
+
id: targetSource,
|
|
77377
|
+
sourceRect: void 0,
|
|
77378
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
77379
|
+
}]
|
|
77380
|
+
}
|
|
77381
|
+
}
|
|
77382
|
+
];
|
|
77383
|
+
} else {
|
|
77384
|
+
return [
|
|
77385
|
+
{
|
|
77386
|
+
durationMs: 250,
|
|
77387
|
+
layout: {
|
|
77388
|
+
layers: [
|
|
77389
|
+
{
|
|
77390
|
+
sourceName: overlaySource,
|
|
77391
|
+
id: "overlay",
|
|
77392
|
+
zIndex: 0,
|
|
77393
|
+
opacity: 0,
|
|
77394
|
+
sourceRect: void 0,
|
|
77395
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
77396
|
+
},
|
|
77397
|
+
{
|
|
77398
|
+
sourceName: videoSource,
|
|
77399
|
+
id: "video",
|
|
77400
|
+
zIndex: 1,
|
|
77401
|
+
opacity: 0,
|
|
77402
|
+
sourceRect: void 0,
|
|
77403
|
+
destRect: { x: videoX, y: videoY, width: videoWidth, height: videoHeight }
|
|
77404
|
+
}
|
|
77405
|
+
]
|
|
77406
|
+
}
|
|
77407
|
+
},
|
|
77408
|
+
...targetSource ? [{
|
|
77409
|
+
durationMs: 250,
|
|
77410
|
+
layout: {
|
|
77411
|
+
layers: [{
|
|
77412
|
+
sourceName: targetSource,
|
|
77413
|
+
zIndex: 0,
|
|
77414
|
+
opacity: 1,
|
|
77415
|
+
id: targetSource,
|
|
77416
|
+
sourceRect: void 0,
|
|
77417
|
+
destRect: { x: 0, y: 0, width: res.width, height: res.height }
|
|
77418
|
+
}]
|
|
77419
|
+
}
|
|
77420
|
+
}] : []
|
|
77421
|
+
];
|
|
76611
77422
|
}
|
|
76612
|
-
|
|
77423
|
+
})()
|
|
76613
77424
|
}
|
|
76614
77425
|
}
|
|
76615
77426
|
};
|
|
@@ -76651,16 +77462,16 @@ function PresetVisualPreview({ layers, size: size4 = "small", referenceResolutio
|
|
|
76651
77462
|
|
|
76652
77463
|
// build/client/processor.videoCompose/preset-transition-panel.js
|
|
76653
77464
|
function PresetTransitionPanel({ state, sendCommand, selectedPreset, onSelectPreset, sourceSelection, onSourceSelectionChange, presetConfig, onPresetConfigChange }) {
|
|
76654
|
-
const [transition, setTransition] = (0,
|
|
77465
|
+
const [transition, setTransition] = (0, import_react29.useState)({
|
|
76655
77466
|
durationMs: 1e3,
|
|
76656
77467
|
easing: "ease_in_out"
|
|
76657
77468
|
});
|
|
76658
|
-
const lastPresetRef = (0,
|
|
76659
|
-
const loadingSceneRef = (0,
|
|
77469
|
+
const lastPresetRef = (0, import_react29.useRef)(null);
|
|
77470
|
+
const loadingSceneRef = (0, import_react29.useRef)(false);
|
|
76660
77471
|
const metadata = selectedPreset ? PRESET_METADATA[selectedPreset] : null;
|
|
76661
77472
|
const reference = state.sources.find((s) => s.sourceName === state.reference);
|
|
76662
|
-
const onlineSourceNames = (0,
|
|
76663
|
-
(0,
|
|
77473
|
+
const onlineSourceNames = (0, import_react29.useMemo)(() => state.sources.filter((s) => s.status === "online").map((s) => s.sourceName).join(","), [state.sources]);
|
|
77474
|
+
(0, import_react29.useEffect)(() => {
|
|
76664
77475
|
if (!selectedPreset || !metadata)
|
|
76665
77476
|
return;
|
|
76666
77477
|
if (lastPresetRef.current === selectedPreset)
|
|
@@ -76693,13 +77504,13 @@ function PresetTransitionPanel({ state, sendCommand, selectedPreset, onSelectPre
|
|
|
76693
77504
|
onPresetConfigChange(defaults2);
|
|
76694
77505
|
}
|
|
76695
77506
|
}, [metadata, onPresetConfigChange, onSourceSelectionChange, onlineSourceNames, reference?.resolution, selectedPreset, state.sources]);
|
|
76696
|
-
(0,
|
|
77507
|
+
(0, import_react29.useEffect)(() => {
|
|
76697
77508
|
if (!selectedPreset || sourceSelection.length === 0)
|
|
76698
77509
|
return;
|
|
76699
77510
|
const storageKey = `videoCompose.preset.${selectedPreset}.sources`;
|
|
76700
77511
|
localStorage.setItem(storageKey, JSON.stringify(sourceSelection));
|
|
76701
77512
|
}, [selectedPreset, sourceSelection]);
|
|
76702
|
-
const handlePreview = (0,
|
|
77513
|
+
const handlePreview = (0, import_react29.useCallback)(() => {
|
|
76703
77514
|
if (!selectedPreset || !metadata)
|
|
76704
77515
|
return;
|
|
76705
77516
|
const layout = {
|
|
@@ -76713,11 +77524,20 @@ function PresetTransitionPanel({ state, sendCommand, selectedPreset, onSelectPre
|
|
|
76713
77524
|
layout
|
|
76714
77525
|
});
|
|
76715
77526
|
}, [selectedPreset, metadata, sourceSelection, presetConfig, sendCommand]);
|
|
76716
|
-
const handleCancelPreview = (0,
|
|
77527
|
+
const handleCancelPreview = (0, import_react29.useCallback)(() => {
|
|
76717
77528
|
sendCommand({ type: "disable-preview" });
|
|
76718
77529
|
}, [sendCommand]);
|
|
76719
|
-
const
|
|
76720
|
-
|
|
77530
|
+
const hasOrchestration = (0, import_react29.useMemo)(() => {
|
|
77531
|
+
if (!selectedPreset)
|
|
77532
|
+
return false;
|
|
77533
|
+
try {
|
|
77534
|
+
const presetDef = PRESETS[selectedPreset]?.(sourceSelection, presetConfig, { width: 1920, height: 1080 });
|
|
77535
|
+
return !!presetDef?.orchestrations;
|
|
77536
|
+
} catch {
|
|
77537
|
+
return false;
|
|
77538
|
+
}
|
|
77539
|
+
}, [selectedPreset, sourceSelection, presetConfig]);
|
|
77540
|
+
const handleApplyPreview = (0, import_react29.useCallback)(() => {
|
|
76721
77541
|
sendCommand({
|
|
76722
77542
|
type: "apply-preview",
|
|
76723
77543
|
// Only pass transition if there's no orchestration
|
|
@@ -76728,8 +77548,8 @@ function PresetTransitionPanel({ state, sendCommand, selectedPreset, onSelectPre
|
|
|
76728
77548
|
}
|
|
76729
77549
|
}
|
|
76730
77550
|
});
|
|
76731
|
-
}, [sendCommand, transition.durationMs, transition.easing,
|
|
76732
|
-
const handleApplyDirect = (0,
|
|
77551
|
+
}, [sendCommand, transition.durationMs, transition.easing, hasOrchestration]);
|
|
77552
|
+
const handleApplyDirect = (0, import_react29.useCallback)(() => {
|
|
76733
77553
|
if (!selectedPreset || !metadata)
|
|
76734
77554
|
return;
|
|
76735
77555
|
const layout = {
|
|
@@ -76738,7 +77558,6 @@ function PresetTransitionPanel({ state, sendCommand, selectedPreset, onSelectPre
|
|
|
76738
77558
|
sourceSelection: sourceSelection.length > 0 ? sourceSelection : void 0,
|
|
76739
77559
|
...metadata.hasConfig ? { config: presetConfig } : {}
|
|
76740
77560
|
};
|
|
76741
|
-
const hasOrchestration = PRESETS[selectedPreset]?.(sourceSelection, presetConfig, { width: 1920, height: 1080 })?.orchestrations;
|
|
76742
77561
|
sendCommand({
|
|
76743
77562
|
type: "update-layout",
|
|
76744
77563
|
layout,
|
|
@@ -76750,8 +77569,8 @@ function PresetTransitionPanel({ state, sendCommand, selectedPreset, onSelectPre
|
|
|
76750
77569
|
}
|
|
76751
77570
|
}
|
|
76752
77571
|
});
|
|
76753
|
-
}, [selectedPreset, metadata, sourceSelection, presetConfig, sendCommand, transition]);
|
|
76754
|
-
const referenceResolution = (0,
|
|
77572
|
+
}, [selectedPreset, metadata, sourceSelection, presetConfig, sendCommand, transition, hasOrchestration]);
|
|
77573
|
+
const referenceResolution = (0, import_react29.useMemo)(() => {
|
|
76755
77574
|
const reference2 = state.sources.find((s) => s.sourceName === state.reference);
|
|
76756
77575
|
return reference2?.resolution;
|
|
76757
77576
|
}, [state.sources, state.reference]);
|
|
@@ -76776,7 +77595,7 @@ function SceneCard({ scene, isActive, onSelect, onDelete }) {
|
|
|
76776
77595
|
}, className: "absolute top-1 right-1 p-1 rounded bg-red-600 text-white hover:bg-red-700\n opacity-0 group-hover:opacity-100 transition-opacity", title: "Delete scene", children: (0, import_jsx_runtime63.jsx)("svg", { className: "w-3 h-3", fill: "currentColor", viewBox: "0 0 20 20", children: (0, import_jsx_runtime63.jsx)("path", { fillRule: "evenodd", d: "M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z", clipRule: "evenodd" }) }) })] });
|
|
76777
77596
|
}
|
|
76778
77597
|
function PresetCard({ presetKey, metadata, onClick, referenceResolution }) {
|
|
76779
|
-
const previewLayout = (0,
|
|
77598
|
+
const previewLayout = (0, import_react29.useMemo)(() => {
|
|
76780
77599
|
if (!referenceResolution)
|
|
76781
77600
|
return null;
|
|
76782
77601
|
const generator = PRESETS[presetKey];
|
|
@@ -76794,7 +77613,7 @@ function PresetCard({ presetKey, metadata, onClick, referenceResolution }) {
|
|
|
76794
77613
|
return (0, import_jsx_runtime63.jsxs)("button", { className: "p-1.5 rounded border border-gray-300 dark:border-gray-600\n hover:border-blue-500 dark:hover:border-blue-400\n hover:bg-blue-50 dark:hover:bg-blue-900/20\n bg-white dark:bg-gray-800\n text-left transition-colors flex flex-col gap-1.5", onClick, children: [(0, import_jsx_runtime63.jsx)("div", { className: "w-full flex justify-center", children: previewLayout && referenceResolution ? (0, import_jsx_runtime63.jsx)(PresetVisualPreview, { layers: previewLayout.layers, size: "small", referenceResolution }) : (0, import_jsx_runtime63.jsx)("div", { className: "w-16 h-9 bg-gray-700 dark:bg-gray-900 rounded flex items-center justify-center", children: (0, import_jsx_runtime63.jsx)("span", { className: "text-xs text-gray-400", children: "?" }) }) }), (0, import_jsx_runtime63.jsxs)("div", { className: "w-full", children: [(0, import_jsx_runtime63.jsx)("h3", { className: "font-medium text-xs text-gray-900 dark:text-white truncate text-center", children: metadata.name }), (0, import_jsx_runtime63.jsxs)("div", { className: "flex items-center justify-center gap-1 mt-0.5", children: [(0, import_jsx_runtime63.jsx)("span", { className: "text-xs text-gray-500 dark:text-gray-400", children: metadata.minSources === metadata.maxSources ? `${metadata.minSources} src${metadata.minSources > 1 ? "s" : ""}` : `${metadata.minSources}-${metadata.maxSources} srcs` }), metadata.hasConfig && (0, import_jsx_runtime63.jsx)("span", { className: "text-xs bg-blue-100 dark:bg-blue-900 text-blue-700 dark:text-blue-300\n px-1 py-0.5 rounded", children: "Config" })] })] })] });
|
|
76795
77614
|
}
|
|
76796
77615
|
function SaveSceneForm({ onSave, onCancel }) {
|
|
76797
|
-
const [name, setName] = (0,
|
|
77616
|
+
const [name, setName] = (0, import_react29.useState)("");
|
|
76798
77617
|
return (0, import_jsx_runtime63.jsxs)("div", { className: "space-y-2 p-3 bg-gray-50 dark:bg-gray-900 rounded", children: [(0, import_jsx_runtime63.jsx)("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300", children: "Scene Name" }), (0, import_jsx_runtime63.jsx)("input", { type: "text", value: name, onChange: (e) => setName(e.target.value), placeholder: "Enter scene name...", className: "w-full px-3 py-2 border border-gray-300 dark:border-gray-600\n rounded bg-white dark:bg-gray-800 text-gray-900 dark:text-white", autoFocus: true }), (0, import_jsx_runtime63.jsxs)("div", { className: "flex gap-2", children: [(0, import_jsx_runtime63.jsx)("button", { onClick: () => {
|
|
76799
77618
|
if (name.trim()) {
|
|
76800
77619
|
onSave(name.trim());
|
|
@@ -76807,9 +77626,29 @@ function SaveSceneForm({ onSave, onCancel }) {
|
|
|
76807
77626
|
}
|
|
76808
77627
|
function PresetConfiguration(props) {
|
|
76809
77628
|
const { metadata, onPreview, onCancelPreview, onApplyPreview, onApplyDirect, onCancel, isTransitioning, isPreviewActive, sourceSelection, state: _state, sendCommand } = props;
|
|
76810
|
-
const [activeTab, setActiveTab] = (0,
|
|
76811
|
-
const [showSaveForm, setShowSaveForm] = (0,
|
|
77629
|
+
const [activeTab, setActiveTab] = (0, import_react29.useState)("sources");
|
|
77630
|
+
const [showSaveForm, setShowSaveForm] = (0, import_react29.useState)(false);
|
|
77631
|
+
const [isPending, setIsPending] = (0, import_react29.useState)(false);
|
|
77632
|
+
(0, import_react29.useEffect)(() => {
|
|
77633
|
+
if (isTransitioning) {
|
|
77634
|
+
setIsPending(false);
|
|
77635
|
+
}
|
|
77636
|
+
}, [isTransitioning]);
|
|
77637
|
+
(0, import_react29.useEffect)(() => {
|
|
77638
|
+
if (isPending) {
|
|
77639
|
+
const timeout = setTimeout(() => setIsPending(false), 1e4);
|
|
77640
|
+
return () => clearTimeout(timeout);
|
|
77641
|
+
}
|
|
77642
|
+
}, [isPending]);
|
|
76812
77643
|
const canPreview = sourceSelection.length >= metadata.minSources;
|
|
77644
|
+
const handleApplyPreviewWithPending = (0, import_react29.useCallback)(() => {
|
|
77645
|
+
setIsPending(true);
|
|
77646
|
+
onApplyPreview();
|
|
77647
|
+
}, [onApplyPreview]);
|
|
77648
|
+
const handleApplyDirectWithPending = (0, import_react29.useCallback)(() => {
|
|
77649
|
+
setIsPending(true);
|
|
77650
|
+
onApplyDirect();
|
|
77651
|
+
}, [onApplyDirect]);
|
|
76813
77652
|
const handleSaveScene = (name) => {
|
|
76814
77653
|
const layout = {
|
|
76815
77654
|
type: "preset",
|
|
@@ -76820,7 +77659,7 @@ function PresetConfiguration(props) {
|
|
|
76820
77659
|
sendCommand({ type: "create-scene", name, layout });
|
|
76821
77660
|
setShowSaveForm(false);
|
|
76822
77661
|
};
|
|
76823
|
-
return (0, import_jsx_runtime63.jsxs)("div", { className: "h-full flex flex-col", children: [(0, import_jsx_runtime63.jsxs)("div", { className: "p-6 border-b border-gray-200 dark:border-gray-700", children: [(0, import_jsx_runtime63.jsx)("button", { onClick: onCancel, className: "text-sm text-blue-600 dark:text-blue-400 hover:text-blue-700\n dark:hover:text-blue-300 mb-2", children: "\u2190 Back to Presets" }), (0, import_jsx_runtime63.jsx)("h2", { className: "text-2xl font-bold text-gray-900 dark:text-white", children: metadata.name }), (0, import_jsx_runtime63.jsx)("p", { className: "text-sm text-gray-600 dark:text-gray-400 mt-1", children: metadata.description })] }), (0, import_jsx_runtime63.jsx)("div", { className: "flex-1 overflow-y-auto", children: metadata.hasConfig ? (0, import_jsx_runtime63.jsxs)("div", { children: [(0, import_jsx_runtime63.jsx)("div", { className: "border-b border-gray-200 dark:border-gray-700 px-6", children: (0, import_jsx_runtime63.jsxs)("div", { className: "flex gap-6", children: [(0, import_jsx_runtime63.jsx)("button", { onClick: () => setActiveTab("sources"), className: `py-3 border-b-2 font-medium text-sm transition-colors ${activeTab === "sources" ? "border-blue-600 text-blue-600 dark:text-blue-400" : "border-transparent text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300"}`, children: "Source Ordering" }), (0, import_jsx_runtime63.jsx)("button", { onClick: () => setActiveTab("config"), className: `py-3 border-b-2 font-medium text-sm transition-colors ${activeTab === "config" ? "border-blue-600 text-blue-600 dark:text-blue-400" : "border-transparent text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300"}`, children: "Configuration" })] }) }), (0, import_jsx_runtime63.jsx)("div", { className: "p-6", children: activeTab === "sources" ? (0, import_jsx_runtime63.jsx)(SourceOrderingPanel, { ...props }) : (0, import_jsx_runtime63.jsx)(ConfigPanel, { presetKey: props.presetKey, config: props.config, onConfigChange: props.onConfigChange }) })] }) : (0, import_jsx_runtime63.jsx)("div", { className: "p-6", children: (0, import_jsx_runtime63.jsx)(SourceOrderingPanel, { ...props }) }) }), (0, import_jsx_runtime63.jsxs)("div", { className: "border-t border-gray-200 dark:border-gray-700 p-6 space-y-4", children: [showSaveForm ? (0, import_jsx_runtime63.jsx)(SaveSceneForm, { onSave: handleSaveScene, onCancel: () => setShowSaveForm(false) }) : (0, import_jsx_runtime63.jsx)("button", { onClick: () => setShowSaveForm(true), disabled: !canPreview, className: "w-full px-4 py-2 text-sm rounded border-2 border-dashed\n border-gray-300 dark:border-gray-600 text-gray-600 dark:text-gray-400\n hover:border-green-500 hover:text-green-600 dark:hover:border-green-400\n dark:hover:text-green-400 transition-colors\n disabled:opacity-50 disabled:cursor-not-allowed", children: "Save as Scene" }), (0, import_jsx_runtime63.jsx)(PreviewControls, { transition: props.transition, onTransitionChange: props.onTransitionChange, onPreview, onCancelPreview, onApplyPreview, onApplyDirect, isTransitioning, isPreviewActive, canPreview, presetKey: props.presetKey, sourceSelection, config: props.config })] })] });
|
|
77662
|
+
return (0, import_jsx_runtime63.jsxs)("div", { className: "h-full flex flex-col", children: [(0, import_jsx_runtime63.jsxs)("div", { className: "p-6 border-b border-gray-200 dark:border-gray-700", children: [(0, import_jsx_runtime63.jsx)("button", { onClick: onCancel, className: "text-sm text-blue-600 dark:text-blue-400 hover:text-blue-700\n dark:hover:text-blue-300 mb-2", children: "\u2190 Back to Presets" }), (0, import_jsx_runtime63.jsx)("h2", { className: "text-2xl font-bold text-gray-900 dark:text-white", children: metadata.name }), (0, import_jsx_runtime63.jsx)("p", { className: "text-sm text-gray-600 dark:text-gray-400 mt-1", children: metadata.description })] }), (0, import_jsx_runtime63.jsx)("div", { className: "flex-1 overflow-y-auto", children: metadata.hasConfig ? (0, import_jsx_runtime63.jsxs)("div", { children: [(0, import_jsx_runtime63.jsx)("div", { className: "border-b border-gray-200 dark:border-gray-700 px-6", children: (0, import_jsx_runtime63.jsxs)("div", { className: "flex gap-6", children: [(0, import_jsx_runtime63.jsx)("button", { onClick: () => setActiveTab("sources"), className: `py-3 border-b-2 font-medium text-sm transition-colors ${activeTab === "sources" ? "border-blue-600 text-blue-600 dark:text-blue-400" : "border-transparent text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300"}`, children: "Source Ordering" }), (0, import_jsx_runtime63.jsx)("button", { onClick: () => setActiveTab("config"), className: `py-3 border-b-2 font-medium text-sm transition-colors ${activeTab === "config" ? "border-blue-600 text-blue-600 dark:text-blue-400" : "border-transparent text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300"}`, children: "Configuration" })] }) }), (0, import_jsx_runtime63.jsx)("div", { className: "p-6", children: activeTab === "sources" ? (0, import_jsx_runtime63.jsx)(SourceOrderingPanel, { ...props }) : (0, import_jsx_runtime63.jsx)(ConfigPanel, { presetKey: props.presetKey, config: props.config, onConfigChange: props.onConfigChange }) })] }) : (0, import_jsx_runtime63.jsx)("div", { className: "p-6", children: (0, import_jsx_runtime63.jsx)(SourceOrderingPanel, { ...props }) }) }), (0, import_jsx_runtime63.jsxs)("div", { className: "border-t border-gray-200 dark:border-gray-700 p-6 space-y-4", children: [showSaveForm ? (0, import_jsx_runtime63.jsx)(SaveSceneForm, { onSave: handleSaveScene, onCancel: () => setShowSaveForm(false) }) : (0, import_jsx_runtime63.jsx)("button", { onClick: () => setShowSaveForm(true), disabled: !canPreview, className: "w-full px-4 py-2 text-sm rounded border-2 border-dashed\n border-gray-300 dark:border-gray-600 text-gray-600 dark:text-gray-400\n hover:border-green-500 hover:text-green-600 dark:hover:border-green-400\n dark:hover:text-green-400 transition-colors\n disabled:opacity-50 disabled:cursor-not-allowed", children: "Save as Scene" }), (0, import_jsx_runtime63.jsx)(PreviewControls, { transition: props.transition, onTransitionChange: props.onTransitionChange, onPreview, onCancelPreview, onApplyPreview: handleApplyPreviewWithPending, onApplyDirect: handleApplyDirectWithPending, isTransitioning, isPreviewActive, canPreview, presetKey: props.presetKey, sourceSelection, config: props.config, isPending })] })] });
|
|
76824
77663
|
}
|
|
76825
77664
|
function SourceOrderingPanel({ metadata, sourceSelection, onSourceSelectionChange, availableSources }) {
|
|
76826
77665
|
const usedSourceNames = new Set(sourceSelection);
|
|
@@ -76878,8 +77717,9 @@ function ConfigPanel({ presetKey, config, onConfigChange }) {
|
|
|
76878
77717
|
}
|
|
76879
77718
|
return null;
|
|
76880
77719
|
}
|
|
76881
|
-
function PreviewControls({ transition, onTransitionChange, onPreview, onCancelPreview, onApplyPreview, onApplyDirect, isTransitioning, isPreviewActive, canPreview, presetKey, sourceSelection, config }) {
|
|
76882
|
-
const
|
|
77720
|
+
function PreviewControls({ transition, onTransitionChange, onPreview, onCancelPreview, onApplyPreview, onApplyDirect, isTransitioning, isPreviewActive, canPreview, presetKey, sourceSelection, config, isPending }) {
|
|
77721
|
+
const isBusy = isPending || isTransitioning;
|
|
77722
|
+
const hasOrchestration = (0, import_react29.useMemo)(() => {
|
|
76883
77723
|
try {
|
|
76884
77724
|
const presetDef = PRESETS[presetKey]?.(sourceSelection, config, { width: 1920, height: 1080 });
|
|
76885
77725
|
return !!presetDef?.orchestrations;
|
|
@@ -76893,22 +77733,22 @@ function PreviewControls({ transition, onTransitionChange, onPreview, onCancelPr
|
|
|
76893
77733
|
}), className: "w-full accent-blue-600" }), (0, import_jsx_runtime63.jsxs)("div", { className: "flex justify-between text-xs text-gray-500", children: [(0, import_jsx_runtime63.jsx)("span", { children: "Instant" }), (0, import_jsx_runtime63.jsx)("span", { children: "3s" })] })] }), (0, import_jsx_runtime63.jsxs)("div", { className: "space-y-2", children: [(0, import_jsx_runtime63.jsx)("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300", children: "Easing" }), (0, import_jsx_runtime63.jsxs)("select", { value: transition.easing, onChange: (e) => onTransitionChange({
|
|
76894
77734
|
...transition,
|
|
76895
77735
|
easing: e.target.value
|
|
76896
|
-
}), className: "w-full px-3 py-2 border border-gray-300 dark:border-gray-600\n rounded bg-white dark:bg-gray-800 text-gray-900 dark:text-white", children: [(0, import_jsx_runtime63.jsx)("option", { value: "linear", children: "Linear" }), (0, import_jsx_runtime63.jsx)("option", { value: "ease_in", children: "Ease In" }), (0, import_jsx_runtime63.jsx)("option", { value: "ease_out", children: "Ease Out" }), (0, import_jsx_runtime63.jsx)("option", { value: "ease_in_out", children: "Ease In Out" })] })] })] }), (0, import_jsx_runtime63.jsxs)("div", { className: "space-y-2", children: [(0, import_jsx_runtime63.jsx)("button", { className: "w-full px-4 py-3 rounded-lg font-medium\n bg-green-600 text-white hover:bg-green-700\n disabled:opacity-50 disabled:cursor-not-allowed\n transition-colors", onClick: isPreviewActive ? onApplyPreview : onApplyDirect, disabled: !canPreview ||
|
|
77736
|
+
}), className: "w-full px-3 py-2 border border-gray-300 dark:border-gray-600\n rounded bg-white dark:bg-gray-800 text-gray-900 dark:text-white", children: [(0, import_jsx_runtime63.jsx)("option", { value: "linear", children: "Linear" }), (0, import_jsx_runtime63.jsx)("option", { value: "ease_in", children: "Ease In" }), (0, import_jsx_runtime63.jsx)("option", { value: "ease_out", children: "Ease Out" }), (0, import_jsx_runtime63.jsx)("option", { value: "ease_in_out", children: "Ease In Out" })] })] })] }), (0, import_jsx_runtime63.jsxs)("div", { className: "space-y-2", children: [(0, import_jsx_runtime63.jsx)("button", { className: "w-full px-4 py-3 rounded-lg font-medium\n bg-green-600 text-white hover:bg-green-700\n disabled:opacity-50 disabled:cursor-not-allowed\n transition-colors", onClick: isPreviewActive ? onApplyPreview : onApplyDirect, disabled: !canPreview || isBusy, children: isBusy ? "Transitioning..." : "Take to Live" }), isPreviewActive ? (0, import_jsx_runtime63.jsx)("button", { className: "w-full px-4 py-2 rounded-lg font-medium\n bg-red-600 text-white hover:bg-red-700\n transition-colors", onClick: onCancelPreview, children: "Cancel Preview" }) : (0, import_jsx_runtime63.jsx)("button", { className: "w-full px-4 py-2 rounded-lg font-medium\n border border-blue-600 text-blue-600 dark:text-blue-400\n hover:bg-blue-50 dark:hover:bg-blue-900/20\n disabled:opacity-50 disabled:cursor-not-allowed\n transition-colors", onClick: onPreview, disabled: !canPreview || isBusy, children: "Preview Video" })] })] });
|
|
76897
77737
|
}
|
|
76898
77738
|
|
|
76899
77739
|
// build/client/processor.videoCompose/webrtc-preview.js
|
|
76900
77740
|
var import_jsx_runtime64 = __toESM(require_jsx_runtime());
|
|
76901
|
-
var
|
|
77741
|
+
var import_react30 = __toESM(require_react());
|
|
76902
77742
|
var import_webrtc_client2 = __toESM(require_webrtc_client());
|
|
76903
77743
|
function WebRTCPreview({ url, id, onPlaying }) {
|
|
76904
|
-
const [_client, setClient] = (0,
|
|
76905
|
-
const [error, setError] = (0,
|
|
76906
|
-
const [connecting, setConnecting] = (0,
|
|
76907
|
-
const onPlayingRef = (0,
|
|
76908
|
-
(0,
|
|
77744
|
+
const [_client, setClient] = (0, import_react30.useState)(null);
|
|
77745
|
+
const [error, setError] = (0, import_react30.useState)(null);
|
|
77746
|
+
const [connecting, setConnecting] = (0, import_react30.useState)(false);
|
|
77747
|
+
const onPlayingRef = (0, import_react30.useRef)(onPlaying);
|
|
77748
|
+
(0, import_react30.useEffect)(() => {
|
|
76909
77749
|
onPlayingRef.current = onPlaying;
|
|
76910
77750
|
}, [onPlaying]);
|
|
76911
|
-
const createClient = (0,
|
|
77751
|
+
const createClient = (0, import_react30.useCallback)((url2) => {
|
|
76912
77752
|
console.log(`[WebRTCPreview ${id}] Creating WHEP client for URL:`, url2);
|
|
76913
77753
|
setConnecting(true);
|
|
76914
77754
|
const client = new import_webrtc_client2.WhepClient({
|
|
@@ -76949,7 +77789,7 @@ function WebRTCPreview({ url, id, onPlaying }) {
|
|
|
76949
77789
|
});
|
|
76950
77790
|
return client;
|
|
76951
77791
|
}, [id]);
|
|
76952
|
-
const cleanupClient = (0,
|
|
77792
|
+
const cleanupClient = (0, import_react30.useCallback)(() => {
|
|
76953
77793
|
setClient((client) => {
|
|
76954
77794
|
if (!client)
|
|
76955
77795
|
return null;
|
|
@@ -76966,7 +77806,7 @@ function WebRTCPreview({ url, id, onPlaying }) {
|
|
|
76966
77806
|
setError(null);
|
|
76967
77807
|
setConnecting(false);
|
|
76968
77808
|
}, []);
|
|
76969
|
-
(0,
|
|
77809
|
+
(0, import_react30.useEffect)(() => {
|
|
76970
77810
|
if (url) {
|
|
76971
77811
|
setError(null);
|
|
76972
77812
|
const client = createClient(url);
|
|
@@ -77012,7 +77852,9 @@ function VisualPreview({ layout, sourceJpegUrls, reference, title }) {
|
|
|
77012
77852
|
height: `${heightPercent}%`,
|
|
77013
77853
|
opacity: layer.opacity,
|
|
77014
77854
|
zIndex: layer.zIndex
|
|
77015
|
-
}, children: [jpegUrl ? (0, import_jsx_runtime65.jsx)("img", { src: jpegUrl, alt: layer.sourceName, className: "w-full h-full object-cover",
|
|
77855
|
+
}, children: [jpegUrl ? (0, import_jsx_runtime65.jsx)("img", { src: jpegUrl, alt: layer.sourceName, className: "w-full h-full object-cover", loading: "lazy", decoding: "async", onLoad: (e) => {
|
|
77856
|
+
e.currentTarget.style.display = "";
|
|
77857
|
+
}, onError: (e) => {
|
|
77016
77858
|
e.currentTarget.style.display = "none";
|
|
77017
77859
|
} }) : (0, import_jsx_runtime65.jsx)("div", { className: "w-full h-full bg-gray-700 flex items-center justify-center", children: (0, import_jsx_runtime65.jsxs)("div", { className: "text-center p-2", children: [(0, import_jsx_runtime65.jsx)("div", { className: "text-xs text-gray-400 truncate", children: layer.sourceName }), (0, import_jsx_runtime65.jsx)("div", { className: "text-xs text-gray-500 mt-1", children: "No preview" })] }) }), (0, import_jsx_runtime65.jsx)("div", { className: "absolute top-1 left-1 px-1.5 py-0.5\n bg-black/60 rounded text-xs text-white\n font-mono", children: layer.sourceName }), (0, import_jsx_runtime65.jsx)("div", { className: "absolute top-1 right-1 w-5 h-5\n bg-blue-600 rounded-full flex items-center justify-center\n text-xs text-white font-semibold", children: layer.zIndex }), layer.opacity < 1 && (0, import_jsx_runtime65.jsxs)("div", { className: "absolute bottom-1 right-1 px-1.5 py-0.5\n bg-black/60 rounded text-xs text-white", children: [(layer.opacity * 100).toFixed(0), "%"] })] }, idx);
|
|
77018
77860
|
}) })] });
|
|
@@ -77020,19 +77862,34 @@ function VisualPreview({ layout, sourceJpegUrls, reference, title }) {
|
|
|
77020
77862
|
|
|
77021
77863
|
// build/client/processor.videoCompose/fullscreen.js
|
|
77022
77864
|
function FullscreenView3({ state, config: _config, sendCommand }) {
|
|
77023
|
-
const [showVideoPreview, setShowVideoPreview] = (0,
|
|
77024
|
-
const [pendingPreviewCommand, setPendingPreviewCommand] = (0,
|
|
77025
|
-
const [selectedPreset, setSelectedPreset] = (0,
|
|
77026
|
-
const [sourceSelection, setSourceSelection] = (0,
|
|
77027
|
-
const [presetConfig, setPresetConfig] = (0,
|
|
77028
|
-
const prevConfigRef = (0,
|
|
77029
|
-
const
|
|
77865
|
+
const [showVideoPreview, setShowVideoPreview] = (0, import_react31.useState)(false);
|
|
77866
|
+
const [pendingPreviewCommand, setPendingPreviewCommand] = (0, import_react31.useState)(null);
|
|
77867
|
+
const [selectedPreset, setSelectedPreset] = (0, import_react31.useState)(null);
|
|
77868
|
+
const [sourceSelection, setSourceSelection] = (0, import_react31.useState)([]);
|
|
77869
|
+
const [presetConfig, setPresetConfig] = (0, import_react31.useState)({});
|
|
77870
|
+
const prevConfigRef = (0, import_react31.useRef)({ selectedPreset, sourceSelection, presetConfig });
|
|
77871
|
+
const [throttledJpegUrls, setThrottledJpegUrls] = (0, import_react31.useState)({});
|
|
77872
|
+
const lastJpegUpdateRef = (0, import_react31.useRef)(0);
|
|
77873
|
+
(0, import_react31.useEffect)(() => {
|
|
77874
|
+
const now = Date.now();
|
|
77875
|
+
if (now - lastJpegUpdateRef.current > 2e3) {
|
|
77876
|
+
lastJpegUpdateRef.current = now;
|
|
77877
|
+
setThrottledJpegUrls(state.sourceJpegUrls ?? {});
|
|
77878
|
+
}
|
|
77879
|
+
}, [state.sourceJpegUrls]);
|
|
77880
|
+
const [imagesReady, setImagesReady] = (0, import_react31.useState)(false);
|
|
77881
|
+
(0, import_react31.useEffect)(() => {
|
|
77882
|
+
const timer = setTimeout(() => setImagesReady(true), 100);
|
|
77883
|
+
return () => clearTimeout(timer);
|
|
77884
|
+
}, []);
|
|
77885
|
+
const onlineSourceCount = (0, import_react31.useMemo)(() => state.sources.filter((s) => s.status === "online").length, [state.sources]);
|
|
77886
|
+
const handleSourceSelectionChange = (0, import_react31.useCallback)((sources) => {
|
|
77030
77887
|
setSourceSelection(sources);
|
|
77031
77888
|
}, []);
|
|
77032
|
-
const handlePresetConfigChange = (0,
|
|
77889
|
+
const handlePresetConfigChange = (0, import_react31.useCallback)((config) => {
|
|
77033
77890
|
setPresetConfig(config);
|
|
77034
77891
|
}, []);
|
|
77035
|
-
(0,
|
|
77892
|
+
(0, import_react31.useEffect)(() => {
|
|
77036
77893
|
const prev = prevConfigRef.current;
|
|
77037
77894
|
const configChanged = prev.selectedPreset !== selectedPreset || JSON.stringify(prev.sourceSelection) !== JSON.stringify(sourceSelection) || JSON.stringify(prev.presetConfig) !== JSON.stringify(presetConfig);
|
|
77038
77895
|
if (configChanged) {
|
|
@@ -77044,23 +77901,20 @@ function FullscreenView3({ state, config: _config, sendCommand }) {
|
|
|
77044
77901
|
prevConfigRef.current = { selectedPreset, sourceSelection, presetConfig };
|
|
77045
77902
|
}
|
|
77046
77903
|
}, [selectedPreset, sourceSelection, presetConfig, state.previewMode, sendCommand]);
|
|
77047
|
-
const handlePreviewPlaying = (0,
|
|
77904
|
+
const handlePreviewPlaying = (0, import_react31.useCallback)(() => {
|
|
77048
77905
|
console.log("[FullscreenView] Preview video started playing, sending pending command");
|
|
77049
77906
|
if (pendingPreviewCommand) {
|
|
77050
77907
|
sendCommand(pendingPreviewCommand);
|
|
77051
77908
|
setPendingPreviewCommand(null);
|
|
77052
77909
|
}
|
|
77053
77910
|
}, [pendingPreviewCommand, sendCommand]);
|
|
77054
|
-
const handleSendCommand = (0,
|
|
77911
|
+
const handleSendCommand = (0, import_react31.useCallback)((cmd) => {
|
|
77055
77912
|
if (cmd.type === "enable-preview") {
|
|
77056
|
-
console.log("[FullscreenView] Deferring enable-preview until video starts playing");
|
|
77057
77913
|
setShowVideoPreview(true);
|
|
77058
77914
|
setPendingPreviewCommand(cmd);
|
|
77059
77915
|
setTimeout(() => {
|
|
77060
|
-
console.log("[FullscreenView] Timeout reached, checking if command still pending");
|
|
77061
77916
|
setPendingPreviewCommand((pending) => {
|
|
77062
77917
|
if (pending) {
|
|
77063
|
-
console.log("[FullscreenView] Sending command due to timeout");
|
|
77064
77918
|
sendCommand(pending);
|
|
77065
77919
|
return null;
|
|
77066
77920
|
}
|
|
@@ -77075,22 +77929,26 @@ function FullscreenView3({ state, config: _config, sendCommand }) {
|
|
|
77075
77929
|
sendCommand(cmd);
|
|
77076
77930
|
}
|
|
77077
77931
|
}, [sendCommand]);
|
|
77078
|
-
const
|
|
77932
|
+
const referenceResolution = (0, import_react31.useMemo)(() => {
|
|
77933
|
+
const ref = state.sources.find((s) => s.sourceName === state.reference);
|
|
77934
|
+
return ref?.resolution;
|
|
77935
|
+
}, [state.sources, state.reference]);
|
|
77936
|
+
const referenceResolutionKey = referenceResolution ? `${referenceResolution.width}x${referenceResolution.height}` : null;
|
|
77937
|
+
const previewLayout = (0, import_react31.useMemo)(() => {
|
|
77079
77938
|
if (!selectedPreset || sourceSelection.length === 0)
|
|
77080
77939
|
return void 0;
|
|
77081
|
-
|
|
77082
|
-
if (!reference?.resolution)
|
|
77940
|
+
if (!referenceResolution)
|
|
77083
77941
|
return void 0;
|
|
77084
77942
|
const generator = PRESETS[selectedPreset];
|
|
77085
77943
|
if (!generator)
|
|
77086
77944
|
return void 0;
|
|
77087
77945
|
try {
|
|
77088
|
-
const presetDef = generator(sourceSelection, presetConfig, { width:
|
|
77946
|
+
const presetDef = generator(sourceSelection, presetConfig, { width: referenceResolution.width, height: referenceResolution.height });
|
|
77089
77947
|
return presetDef.finalConfig;
|
|
77090
77948
|
} catch (_e) {
|
|
77091
77949
|
return void 0;
|
|
77092
77950
|
}
|
|
77093
|
-
})
|
|
77951
|
+
}, [selectedPreset, sourceSelection, presetConfig, referenceResolutionKey]);
|
|
77094
77952
|
if (!state) {
|
|
77095
77953
|
return (0, import_jsx_runtime66.jsx)("div", { className: "flex h-full items-center justify-center bg-gray-50 dark:bg-gray-900", children: (0, import_jsx_runtime66.jsxs)("div", { className: "text-center", children: [(0, import_jsx_runtime66.jsx)("div", { className: "text-xl font-semibold text-gray-900 dark:text-white mb-2", children: "Loading Video Compose..." }), (0, import_jsx_runtime66.jsx)("div", { className: "text-sm text-gray-500 dark:text-gray-400", children: "Connecting to component state..." })] }) });
|
|
77096
77954
|
}
|
|
@@ -77101,7 +77959,7 @@ function FullscreenView3({ state, config: _config, sendCommand }) {
|
|
|
77101
77959
|
}, sendCommand: handleSendCommand, selectedPreset, onSelectPreset: setSelectedPreset, sourceSelection, onSourceSelectionChange: handleSourceSelectionChange, presetConfig, onPresetConfigChange: handlePresetConfigChange }) }), (0, import_jsx_runtime66.jsxs)("div", { className: "flex-1 flex flex-col", children: [(0, import_jsx_runtime66.jsxs)("div", { className: "flex-1 flex gap-6 p-6 min-h-0", children: [(0, import_jsx_runtime66.jsxs)("div", { className: "flex-1 flex flex-col min-w-0", children: [(0, import_jsx_runtime66.jsx)("div", { className: "flex items-center justify-between mb-4", children: (0, import_jsx_runtime66.jsxs)("div", { className: "flex items-center gap-3", children: [(0, import_jsx_runtime66.jsx)("h2", { className: "text-xl font-bold text-gray-900 dark:text-white", children: showVideoPreview ? "Preview Transition" : "Preview Output" }), state.previewTransitioning && (0, import_jsx_runtime66.jsx)("span", { className: "text-sm text-blue-600 dark:text-blue-400 font-medium", children: "Transitioning..." })] }) }), showVideoPreview ? (0, import_jsx_runtime66.jsx)(WebRTCPreview, { url: state.previewPreviewUrl, id: `${_config.id}-preview`, onPlaying: handlePreviewPlaying }, state.previewPreviewUrl) : (0, import_jsx_runtime66.jsx)("div", { className: "flex-1 flex items-center justify-center bg-gray-900 rounded-lg overflow-hidden", children: (0, import_jsx_runtime66.jsx)("div", { className: "w-full h-full flex items-center justify-center p-4", children: (0, import_jsx_runtime66.jsx)("div", { className: "w-full max-w-full max-h-full", children: (0, import_jsx_runtime66.jsx)(VisualPreview, { layout: (
|
|
77102
77960
|
// Show preset being built, or preview composition, or current layout
|
|
77103
77961
|
previewLayout ? previewLayout : state.previewMode && state.previewResolvedLayout ? state.previewResolvedLayout : state.resolvedLayout
|
|
77104
|
-
), sourceJpegUrls:
|
|
77962
|
+
), sourceJpegUrls: imagesReady ? throttledJpegUrls : {}, reference: referenceResolution, title: previewLayout ? "Preset Preview (Building...)" : state.previewMode ? "Preview Composition" : "Current Layout" }) }) }) })] }), (0, import_jsx_runtime66.jsxs)("div", { className: "flex-1 flex flex-col min-w-0", children: [(0, import_jsx_runtime66.jsxs)("div", { className: "flex items-center justify-between mb-4", children: [(0, import_jsx_runtime66.jsx)("h2", { className: "text-xl font-bold text-gray-900 dark:text-white", children: "Live Output" }), state.transitioning && (0, import_jsx_runtime66.jsx)("span", { className: "text-sm text-blue-600 dark:text-blue-400 font-medium", children: "Transitioning..." }), !state.previewUrl && !state.referenceAvailable && (0, import_jsx_runtime66.jsx)("span", { className: "text-xs text-gray-500 dark:text-gray-400", children: "Waiting for reference stream..." })] }), (0, import_jsx_runtime66.jsx)(WebRTCPreview, { url: state.previewUrl, id: `${_config.id}-live` })] })] }), (0, import_jsx_runtime66.jsxs)("div", { className: "border-t border-gray-200 dark:border-gray-700\n bg-white dark:bg-gray-800 h-64 flex flex-col", children: [(0, import_jsx_runtime66.jsx)("div", { className: "p-4 border-b border-gray-200 dark:border-gray-700", children: (0, import_jsx_runtime66.jsx)("h2", { className: "text-lg font-bold text-gray-900 dark:text-white", children: "Status" }) }), (0, import_jsx_runtime66.jsxs)("div", { className: "flex-1 overflow-y-auto p-4 space-y-4", children: [(0, import_jsx_runtime66.jsxs)("div", { className: "space-y-2", children: [(0, import_jsx_runtime66.jsxs)("div", { className: "flex items-center justify-between", children: [(0, import_jsx_runtime66.jsx)("h3", { className: "text-sm font-semibold text-gray-900 dark:text-white", children: "Sources" }), (0, import_jsx_runtime66.jsxs)("span", { className: "text-xs text-gray-500 dark:text-gray-400", children: [onlineSourceCount, " / ", state.sources.length, " online"] })] }), (0, import_jsx_runtime66.jsx)("div", { className: "space-y-1", children: state.sources.map((source, i) => (0, import_jsx_runtime66.jsxs)("div", { className: "flex items-center gap-2 p-1.5 rounded bg-gray-50 dark:bg-gray-900", children: [(0, import_jsx_runtime66.jsx)("div", { className: `w-1.5 h-1.5 rounded-full flex-shrink-0 ${source.status === "online" ? "bg-live" : "bg-offline"}` }), (0, import_jsx_runtime66.jsxs)("div", { className: "flex-1 min-w-0", children: [(0, import_jsx_runtime66.jsxs)("div", { className: `text-xs font-medium ${source.sourceName === state.reference ? "text-blue-600 dark:text-blue-400" : "text-gray-900 dark:text-white"}`, children: [source.sourceName, source.sourceName === state.reference && " (ref)"] }), source.resolution && (0, import_jsx_runtime66.jsxs)("div", { className: "text-xs text-gray-500 dark:text-gray-400", children: [source.resolution.width, "\xD7", source.resolution.height, source.frameRate && ` @ ${source.frameRate.frames}/${source.frameRate.seconds}fps`] })] })] }, i)) })] }), state.resolvedLayout && state.resolvedLayout.layers.length > 0 && (0, import_jsx_runtime66.jsxs)("div", { className: "space-y-2", children: [(0, import_jsx_runtime66.jsxs)("div", { children: [(0, import_jsx_runtime66.jsx)("h3", { className: "text-sm font-semibold text-gray-900 dark:text-white", children: "Active Layout" }), (0, import_jsx_runtime66.jsxs)("div", { className: "text-xs text-gray-600 dark:text-gray-400 mt-0.5", children: [state.layout?.type === "preset" ? state.layout.preset : "Custom", " \u2022 ", state.resolvedLayout.layers.length, " ", state.resolvedLayout.layers.length === 1 ? "layer" : "layers"] })] }), (0, import_jsx_runtime66.jsx)("div", { className: "space-y-1", children: state.resolvedLayout.layers.map((layer, i) => (0, import_jsx_runtime66.jsxs)("div", { className: "text-xs p-1.5 rounded bg-gray-50 dark:bg-gray-900", children: [(0, import_jsx_runtime66.jsxs)("div", { className: "font-medium text-gray-900 dark:text-white", children: ["L", layer.zIndex, ": ", layer.sourceName] }), (0, import_jsx_runtime66.jsxs)("div", { className: "text-xs text-gray-500 dark:text-gray-400", children: [(layer.opacity * 100).toFixed(0), "%", layer.destRect && (0, import_jsx_runtime66.jsxs)(import_jsx_runtime66.Fragment, { children: [" \u2022 (", layer.destRect.x.toFixed(0), ", ", layer.destRect.y.toFixed(0), ")"] })] })] }, i)) })] }), state.transitioning && (0, import_jsx_runtime66.jsxs)("div", { className: "space-y-1", children: [(0, import_jsx_runtime66.jsx)("h3", { className: "text-sm font-semibold text-gray-900 dark:text-white", children: "Transition" }), (0, import_jsx_runtime66.jsx)("div", { className: "text-xs text-gray-600 dark:text-gray-400", children: "In progress..." })] })] })] })] })] });
|
|
77105
77963
|
}
|
|
77106
77964
|
var fullscreen_default2 = FullscreenView3;
|
|
77107
77965
|
|
|
@@ -77733,7 +78591,7 @@ var import_util15 = __toESM(require_util());
|
|
|
77733
78591
|
|
|
77734
78592
|
// build/client/processor.webRtcDuplex/fullscreen.js
|
|
77735
78593
|
var import_jsx_runtime71 = __toESM(require_jsx_runtime());
|
|
77736
|
-
var
|
|
78594
|
+
var import_react32 = __toESM(require_react());
|
|
77737
78595
|
var import_webrtc_client3 = __toESM(require_webrtc_client());
|
|
77738
78596
|
var DuplexWhepClient = class extends NorskWhepClient {
|
|
77739
78597
|
showVideo;
|
|
@@ -77774,11 +78632,11 @@ var DuplexWhipClient = class extends import_webrtc_client3.WhipClient {
|
|
|
77774
78632
|
}
|
|
77775
78633
|
};
|
|
77776
78634
|
function FullscreenView4({ state, config }) {
|
|
77777
|
-
const [client, setClient] = (0,
|
|
77778
|
-
const [sender, setSender] = (0,
|
|
77779
|
-
const container = (0,
|
|
77780
|
-
const button = (0,
|
|
77781
|
-
const go = (0,
|
|
78635
|
+
const [client, setClient] = (0, import_react32.useState)(void 0);
|
|
78636
|
+
const [sender, setSender] = (0, import_react32.useState)(void 0);
|
|
78637
|
+
const container = (0, import_react32.useRef)(null);
|
|
78638
|
+
const button = (0, import_react32.useRef)(null);
|
|
78639
|
+
const go = (0, import_react32.useCallback)(async () => {
|
|
77782
78640
|
if (!state.publishUrl)
|
|
77783
78641
|
return;
|
|
77784
78642
|
if (!client && state.outputUrl && container.current) {
|
|
@@ -78070,7 +78928,7 @@ function assertUnreachable30(_) {
|
|
|
78070
78928
|
|
|
78071
78929
|
// build/client/util.stats.latency/inline-view.js
|
|
78072
78930
|
var import_jsx_runtime73 = __toESM(require_jsx_runtime());
|
|
78073
|
-
var
|
|
78931
|
+
var import_react33 = __toESM(require_react());
|
|
78074
78932
|
|
|
78075
78933
|
// ../../node_modules/chart.js/auto/auto.js
|
|
78076
78934
|
Chart.register(...registerables);
|
|
@@ -78078,8 +78936,8 @@ var auto_default = Chart;
|
|
|
78078
78936
|
|
|
78079
78937
|
// build/client/util.stats.latency/inline-view.js
|
|
78080
78938
|
function InlineView22({ state, config: _2 }) {
|
|
78081
|
-
const chartContainer = (0,
|
|
78082
|
-
const [chartControl, setChartControl] = (0,
|
|
78939
|
+
const chartContainer = (0, import_react33.useRef)(null);
|
|
78940
|
+
const [chartControl, setChartControl] = (0, import_react33.useState)(void 0);
|
|
78083
78941
|
function makeDataSet(key, color2, values) {
|
|
78084
78942
|
return {
|
|
78085
78943
|
label: key,
|
|
@@ -78090,13 +78948,13 @@ function InlineView22({ state, config: _2 }) {
|
|
|
78090
78948
|
data: values
|
|
78091
78949
|
};
|
|
78092
78950
|
}
|
|
78093
|
-
const makeData = (0,
|
|
78951
|
+
const makeData = (0, import_react33.useCallback)((state2) => {
|
|
78094
78952
|
return {
|
|
78095
78953
|
labels: new Array(state2.values.length).fill(0).map((_, i) => i).map((_) => ""),
|
|
78096
78954
|
datasets: [makeDataSet("latency", "rgba(255, 0, 0, 255)", state2.values)]
|
|
78097
78955
|
};
|
|
78098
78956
|
}, []);
|
|
78099
|
-
(0,
|
|
78957
|
+
(0, import_react33.useEffect)(() => {
|
|
78100
78958
|
if (!chartContainer.current)
|
|
78101
78959
|
return;
|
|
78102
78960
|
auto_default.defaults.color = "#FFF";
|
|
@@ -78134,7 +78992,7 @@ function InlineView22({ state, config: _2 }) {
|
|
|
78134
78992
|
chart.update();
|
|
78135
78993
|
}, 100);
|
|
78136
78994
|
}, [chartContainer, makeData, state]);
|
|
78137
|
-
(0,
|
|
78995
|
+
(0, import_react33.useEffect)(() => {
|
|
78138
78996
|
if (!chartControl)
|
|
78139
78997
|
return;
|
|
78140
78998
|
chartControl.data = makeData(state);
|