cursedbelt 5.112.0 → 5.113.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/react/activity-bar/ActivityBar.d.ts.map +1 -1
- package/dist/react/activity-bar/ActivityBar.js +8 -2
- package/dist/react/activity-bar/ActivityBar.js.map +1 -1
- package/dist/react/activity-bar/activityBar.css +4 -0
- package/dist/react/media/CutTimeline.d.ts +31 -0
- package/dist/react/media/CutTimeline.d.ts.map +1 -0
- package/dist/react/media/CutTimeline.js +197 -0
- package/dist/react/media/CutTimeline.js.map +1 -0
- package/dist/react/media/VideoCutEditor.d.ts +32 -6
- package/dist/react/media/VideoCutEditor.d.ts.map +1 -1
- package/dist/react/media/VideoCutEditor.js +97 -63
- package/dist/react/media/VideoCutEditor.js.map +1 -1
- package/dist/react/media/cutTimelineMath.d.ts +80 -0
- package/dist/react/media/cutTimelineMath.d.ts.map +1 -0
- package/dist/react/media/cutTimelineMath.js +116 -0
- package/dist/react/media/cutTimelineMath.js.map +1 -0
- package/dist/react/media/useFrameRate.d.ts +34 -0
- package/dist/react/media/useFrameRate.d.ts.map +1 -0
- package/dist/react/media/useFrameRate.js +66 -0
- package/dist/react/media/useFrameRate.js.map +1 -0
- package/dist/react/media/videoCutEditor.css +249 -63
- package/dist/react/media-gallery/MediaGallery.d.ts +10 -1
- package/dist/react/media-gallery/MediaGallery.d.ts.map +1 -1
- package/dist/react/media-gallery/MediaGallery.js +29 -7
- package/dist/react/media-gallery/MediaGallery.js.map +1 -1
- package/dist/react/media-gallery/galleryDeepLink.d.ts +14 -0
- package/dist/react/media-gallery/galleryDeepLink.d.ts.map +1 -1
- package/dist/react/media-gallery/galleryDeepLink.js +44 -5
- package/dist/react/media-gallery/galleryDeepLink.js.map +1 -1
- package/dist/react/media-gallery/index.d.ts +1 -1
- package/dist/react/media-gallery/index.d.ts.map +1 -1
- package/dist/react/media-gallery/index.js +1 -1
- package/dist/react/media-gallery/index.js.map +1 -1
- package/dist/react/media-gallery/types.d.ts +5 -0
- package/dist/react/media-gallery/types.d.ts.map +1 -1
- package/dist/testing/designAudit.d.ts +8 -1
- package/dist/testing/designAudit.d.ts.map +1 -1
- package/dist/testing/designAudit.js +21 -0
- package/dist/testing/designAudit.js.map +1 -1
- package/package.json +5 -3
- package/scripts/demoServer.ts +1 -1
- package/scripts/guardrails-baseline.json +1 -1
- package/src/demoFixture.spec.ts +17 -5
- package/src/demoRun.spec.ts +10 -1
- package/src/react/activity-bar/ActivityBar.spec.tsx +15 -0
- package/src/react/activity-bar/ActivityBar.tsx +8 -2
- package/src/react/activity-bar/activityBar.css +4 -0
- package/src/react/media/CutTimeline.tsx +379 -0
- package/src/react/media/VideoCutEditor.spec.tsx +1 -1
- package/src/react/media/VideoCutEditor.tsx +277 -214
- package/src/react/media/cutTimelineMath.spec.ts +90 -0
- package/src/react/media/cutTimelineMath.ts +140 -0
- package/src/react/media/useFrameRate.ts +96 -0
- package/src/react/media/videoCutEditor.css +249 -63
- package/src/react/media-gallery/MediaGallery.tsx +38 -7
- package/src/react/media-gallery/galleryDeepLink.spec.tsx +87 -2
- package/src/react/media-gallery/galleryDeepLink.ts +58 -5
- package/src/react/media-gallery/index.ts +1 -0
- package/src/react/media-gallery/types.ts +5 -0
- package/src/testing/designAudit.ts +22 -1
|
@@ -2,32 +2,44 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
2
2
|
import './videoCutEditor.css';
|
|
3
3
|
import React from 'react';
|
|
4
4
|
import { useEditorVideoSource } from './hlsSource.js';
|
|
5
|
-
import { Scissors,
|
|
5
|
+
import { ArrowLeft, Pause, Play, Scissors, StepBack, StepForward, Undo2 } from 'lucide-react';
|
|
6
6
|
import { ActionBar } from '../components/ActionBar.js';
|
|
7
7
|
import { Button } from '../components/Button.js';
|
|
8
|
+
import { Dialog, DialogContent, DialogTitle, focusPanelOnOpen } from '../components/dialog.js';
|
|
9
|
+
import { IconButton } from '../components/IconButton.js';
|
|
10
|
+
import { useDiscardGuard } from '../hooks/useDiscardGuard.js';
|
|
8
11
|
import { InfoHint } from '../components/InfoHint.js';
|
|
9
12
|
import { Tooltip } from '../components/Tooltip.js';
|
|
10
|
-
import { Modal } from '../components/Modal.js';
|
|
11
13
|
import { addSplit, cutSeconds, cutTimecode, EMPTY_PLAN, keptSeconds, planCuts, planProblem, planSegments, removeSplit, toggleSegment, } from 'cursedbelt-core/media/video-cuts';
|
|
12
14
|
import { cn, RAW_BUTTON } from '../lib/cn.js';
|
|
13
15
|
import { Kbd } from '../palette/Kbd.js';
|
|
14
|
-
|
|
16
|
+
import { CutTimeline } from './CutTimeline.js';
|
|
17
|
+
import { frameAt, frameStart, frameTimecode, snapToFrame } from './cutTimelineMath.js';
|
|
18
|
+
import { useFrameRate } from './useFrameRate.js';
|
|
19
|
+
export function VideoCutEditor({ src, hlsUrl, posterUrl, resolving = false, name, durationSeconds, frameRate, open = true, onClose, onSubmit, submitLabel = 'Send for processing', note, ...passThrough }) {
|
|
15
20
|
const videoRef = React.useRef(null);
|
|
16
21
|
const [duration, setDuration] = React.useState(durationSeconds && Number.isFinite(durationSeconds) ? durationSeconds : 0);
|
|
17
22
|
const [playhead, setPlayhead] = React.useState(0);
|
|
23
|
+
const [playing, setPlaying] = React.useState(false);
|
|
18
24
|
const [plan, setPlan] = React.useState(EMPTY_PLAN);
|
|
19
25
|
const [submitting, setSubmitting] = React.useState(false);
|
|
20
26
|
const [error, setError] = React.useState(null);
|
|
27
|
+
// Marked cuts are minutes of scrubbing: Back, Escape and Cancel ask before dropping them.
|
|
28
|
+
const { guardedClose, discardOverlay, isConfirming, cancelDiscard } = useDiscardGuard({
|
|
29
|
+
onClose,
|
|
30
|
+
isDirty: plan.splits.length > 0,
|
|
31
|
+
open,
|
|
32
|
+
});
|
|
21
33
|
// A source that changes is a fresh attempt: it must not inherit the previous one's failure,
|
|
22
34
|
// the same rule `VideoTurner` and the gallery's own `ThumbImg` keep.
|
|
23
35
|
const [failedSrc, setFailedSrc] = React.useState(null);
|
|
24
36
|
/**
|
|
25
37
|
* Why there is no film to mark up — `null` when there is one.
|
|
26
38
|
*
|
|
27
|
-
* 🔴 The
|
|
39
|
+
* 🔴 The page SAYS it rather than rendering the black rectangle a source-less `<video>`
|
|
28
40
|
* paints. Marking a cut means scrubbing to a moment, so with nothing to play there is
|
|
29
41
|
* genuinely nothing to mark — and the one thing worse than that is a player that looks
|
|
30
|
-
* broken and a Send button whose refusal ("Nothing is marked") reads as the
|
|
42
|
+
* broken and a Send button whose refusal ("Nothing is marked") reads as the page's fault.
|
|
31
43
|
*/
|
|
32
44
|
const cannotShow = resolving
|
|
33
45
|
? 'Finding this film…'
|
|
@@ -37,54 +49,79 @@ export function VideoCutEditor({ src, hlsUrl, posterUrl, resolving = false, name
|
|
|
37
49
|
? 'The film could not be loaded, so there is nothing to mark up. Nothing has been sent.'
|
|
38
50
|
: null;
|
|
39
51
|
const source = useEditorVideoSource(videoRef, { src, hlsUrl }, cannotShow === null);
|
|
52
|
+
const { rate, onLoadedData } = useFrameRate(videoRef, frameRate, source.key);
|
|
53
|
+
const fps = rate.fps;
|
|
40
54
|
const segments = React.useMemo(() => planSegments(plan, duration), [plan, duration]);
|
|
41
55
|
const cuts = React.useMemo(() => planCuts(plan, duration), [plan, duration]);
|
|
42
56
|
const problem = planProblem(plan, duration);
|
|
43
|
-
const pct = React.useCallback((seconds) => (duration > 0 ? Math.min(100, Math.max(0, (seconds / duration) * 100)) : 0), [duration]);
|
|
44
57
|
const seek = React.useCallback((seconds) => {
|
|
45
58
|
const video = videoRef.current;
|
|
46
|
-
if (!
|
|
59
|
+
if (!Number.isFinite(seconds))
|
|
47
60
|
return;
|
|
48
|
-
|
|
49
|
-
|
|
61
|
+
const at = Math.max(0, seconds);
|
|
62
|
+
if (video)
|
|
63
|
+
video.currentTime = at;
|
|
64
|
+
setPlayhead(at);
|
|
50
65
|
}, []);
|
|
51
|
-
/**
|
|
52
|
-
const
|
|
66
|
+
/** Where the playhead really is — the element's own clock, which a `timeupdate` trails. */
|
|
67
|
+
const now = () => videoRef.current?.currentTime ?? playhead;
|
|
68
|
+
/** `,` / `.` — one frame back or forward, pausing first, as YouTube and mpv do. */
|
|
69
|
+
const stepFrame = (direction) => {
|
|
70
|
+
const video = videoRef.current;
|
|
71
|
+
if (video && !video.paused)
|
|
72
|
+
video.pause();
|
|
73
|
+
const last = duration > 0 ? frameAt(duration - 1e-6, fps) : 0;
|
|
74
|
+
const frame = Math.min(last, Math.max(0, frameAt(now(), fps) + direction));
|
|
75
|
+
seek(frameStart(frame, fps));
|
|
76
|
+
};
|
|
77
|
+
const togglePlay = () => {
|
|
78
|
+
const video = videoRef.current;
|
|
79
|
+
if (!video)
|
|
80
|
+
return;
|
|
81
|
+
if (video.paused)
|
|
82
|
+
void video.play().catch(() => undefined);
|
|
83
|
+
else
|
|
84
|
+
video.pause();
|
|
85
|
+
};
|
|
86
|
+
/** ✂ — divide the clip at the start of the frame the playhead is on. */
|
|
87
|
+
const cutHere = () => {
|
|
53
88
|
setError(null);
|
|
89
|
+
const at = snapToFrame(now(), fps);
|
|
54
90
|
setPlan((current) => {
|
|
55
|
-
const next = addSplit(current,
|
|
91
|
+
const next = addSplit(current, at, duration);
|
|
56
92
|
if (next === current)
|
|
57
93
|
setError("There is already a cut there, or the playhead is too close to an end of the clip to cut.");
|
|
58
94
|
return next;
|
|
59
95
|
});
|
|
60
|
-
}
|
|
96
|
+
};
|
|
61
97
|
/** ✗ on a piece — mark it out, or put it back. */
|
|
62
98
|
const toggle = React.useCallback((segment) => {
|
|
63
99
|
setError(null);
|
|
64
100
|
setPlan((current) => toggleSegment(current, segment, duration));
|
|
65
101
|
}, [duration]);
|
|
66
102
|
/** Undo a cut, merging the pieces either side. */
|
|
67
|
-
const uncut =
|
|
103
|
+
const uncut = (at) => {
|
|
68
104
|
setError(null);
|
|
69
105
|
setPlan((current) => removeSplit(current, at, duration));
|
|
70
|
-
}
|
|
106
|
+
};
|
|
71
107
|
/*
|
|
72
|
-
* `C` cuts
|
|
108
|
+
* `C` cuts, `Space` plays, `,` and `.` step a frame — and nothing else is bound, deliberately.
|
|
73
109
|
*
|
|
74
|
-
* 🔴 Removing a piece has NO key. It is the only irreversible-feeling action
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
110
|
+
* 🔴 Removing a piece has NO key. It is the only irreversible-feeling action on the page and
|
|
111
|
+
* the one whose target is ambiguous from the keyboard: with the playhead between two splits,
|
|
112
|
+
* "delete" could mean the piece behind it or the piece ahead. Clicking the piece says which,
|
|
113
|
+
* which is the entire point of the model. Every segment is a real focusable button, so the
|
|
114
|
+
* keyboard route is Tab-then-Enter and it names its target out loud.
|
|
79
115
|
*
|
|
80
|
-
* Bound on the
|
|
81
|
-
* and a global listener would keep firing after this closed.
|
|
82
|
-
* dialog really does have the keystrokes while it is open.
|
|
116
|
+
* Bound on the PAGE, not the window: the gallery has its own ⇧←/⇧→ and Space handling (it
|
|
117
|
+
* stands down while this is open), and a global listener would keep firing after this closed.
|
|
83
118
|
*/
|
|
84
119
|
const onKeyDown = (event) => {
|
|
85
120
|
const target = event.target;
|
|
86
121
|
// Never steal a key from a text field — the app may render one in `note`.
|
|
87
|
-
if (target && (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA'))
|
|
122
|
+
if (target && (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.isContentEditable))
|
|
123
|
+
return;
|
|
124
|
+
if (event.metaKey || event.ctrlKey || event.altKey || isConfirming)
|
|
88
125
|
return;
|
|
89
126
|
if (event.key === 'c' || event.key === 'C') {
|
|
90
127
|
event.preventDefault();
|
|
@@ -92,13 +129,11 @@ export function VideoCutEditor({ src, hlsUrl, posterUrl, resolving = false, name
|
|
|
92
129
|
}
|
|
93
130
|
else if (event.key === ' ') {
|
|
94
131
|
event.preventDefault();
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
else
|
|
101
|
-
video.pause();
|
|
132
|
+
togglePlay();
|
|
133
|
+
}
|
|
134
|
+
else if (event.key === ',' || event.key === '.') {
|
|
135
|
+
event.preventDefault();
|
|
136
|
+
stepFrame(event.key === ',' ? -1 : 1);
|
|
102
137
|
}
|
|
103
138
|
};
|
|
104
139
|
const submit = async () => {
|
|
@@ -121,36 +156,35 @@ export function VideoCutEditor({ src, hlsUrl, posterUrl, resolving = false, name
|
|
|
121
156
|
setSubmitting(false);
|
|
122
157
|
}
|
|
123
158
|
};
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
type: 'button', className: cn(RAW_BUTTON, 'cbvc-row-goto'), onClick: () => seek(segment.start), children: [_jsx(Scissors, { "aria-hidden": 'true', size: 12 }), " Cut at ", cutTimecode(segment.start)] }), _jsx(Button, { size: 'sm', variant: 'ghost', tooltip: 'Undo this cut \u2014 the sections either side become one again', "aria-label": `Undo the cut at ${cutTimecode(segment.start)}`, onClick: () => uncut(segment.start), children: "Undo" })] }, `cut-${segment.key}`))) })) : null, note ? _jsx("div", { className: 'cbvc-note', children: note }) : null, error ? (_jsx("p", { className: 'cbvc-error', role: 'alert', children: error })) : null] }) }));
|
|
159
|
+
const transport = (_jsxs("div", { className: 'cbvc-transport', children: [_jsx(IconButton, { size: 'sm', label: 'Back one frame', tooltip: 'Back one frame (,)', onClick: () => stepFrame(-1), disabled: cannotShow !== null, children: _jsx(StepBack, { "aria-hidden": 'true' }) }), _jsx(IconButton, { size: 'sm', label: playing ? 'Pause' : 'Play', tooltip: playing ? 'Pause (Space)' : 'Play (Space)', onClick: togglePlay, disabled: cannotShow !== null, children: playing ? _jsx(Pause, { "aria-hidden": 'true' }) : _jsx(Play, { "aria-hidden": 'true' }) }), _jsx(IconButton, { size: 'sm', label: 'Forward one frame', tooltip: 'Forward one frame (.)', onClick: () => stepFrame(1), disabled: cannotShow !== null, children: _jsx(StepForward, { "aria-hidden": 'true' }) }), _jsxs("span", { className: 'cbvc-readout', "data-testid": 'trim-readout', children: [_jsx("strong", { children: frameTimecode(playhead, fps) }), _jsxs("span", { className: 'cbvc-readout-of', children: [" / ", frameTimecode(duration, fps)] })] }), _jsx(Tooltip, { content: rate.source === 'probe'
|
|
160
|
+
? 'The frame rate the file was probed at'
|
|
161
|
+
: rate.source === 'measured'
|
|
162
|
+
? 'The frame rate, measured from the clip'
|
|
163
|
+
: 'Assumed — the clip has not said its frame rate, so frame steps may not match its frames', children: _jsx("span", { className: 'cbvc-fps', "data-source": rate.source, tabIndex: 0, children: rate.source === 'assumed' ? `${Math.round(fps)} fps?` : `${Number(fps.toFixed(3))} fps` }) }), _jsxs(Button, { size: 'sm', variant: 'secondary', onClick: cutHere, tooltip: 'Cut the clip at this frame (C)', disabled: cannotShow !== null, children: [_jsx(Scissors, { "aria-hidden": 'true', size: 14 }), " Cut here"] })] }));
|
|
164
|
+
return (_jsx(Dialog, { open: open, onOpenChange: (next) => !next && guardedClose(), children: _jsxs(DialogContent, { ...passThrough, className: 'cbvc-page', overlayClassName: 'cbvc-page-scrim', "aria-describedby": undefined, onOpenAutoFocus: focusPanelOnOpen, onEscapeKeyDown: (event) => {
|
|
165
|
+
event.preventDefault();
|
|
166
|
+
if (isConfirming)
|
|
167
|
+
cancelDiscard();
|
|
168
|
+
else
|
|
169
|
+
guardedClose();
|
|
170
|
+
}, onKeyDown: onKeyDown, children: [_jsxs("header", { className: 'cbvc-bar', children: [_jsx(IconButton, { label: 'Back', tooltip: 'Back to the file, sending nothing (Esc)', onClick: guardedClose, children: _jsx(ArrowLeft, { "aria-hidden": 'true' }) }), _jsx(DialogTitle, { className: 'cbvc-title', children: name ? `Trim ${name}` : 'Trim video' }), _jsxs(InfoHint, { title: 'Marking a video to trim', align: 'right', children: [_jsxs("p", { children: ["Press ", _jsx("strong", { children: "Cut here" }), " (or ", _jsx(Kbd, { children: "C" }), ") to divide the clip at the frame the playhead is on. Every piece between two cuts is a section."] }), _jsxs("p", { children: ["Click ", _jsx("strong", { children: "\u2717" }), " on a section to remove it \u2014 click again to keep it after all.", _jsx(Kbd, { children: "," }), " and ", _jsx(Kbd, { children: "." }), " step one frame, ", _jsx(Kbd, { children: "Space" }), " plays and pauses."] }), _jsx("p", { children: "Zoom the timeline with \u2318 or Ctrl and the wheel, a pinch, or the slider; drag or scroll to move along it, and click the ruler to put the playhead there." }), _jsx("p", { children: "Nothing here changes your video. Sending makes a trimmed COPY beside the original, and you choose which to keep." })] })] }), _jsx("div", { className: cn('cbvc-stage', cannotShow !== null && 'cbvc-stage-empty'), children: cannotShow === null ? (_jsx("video", { ref: videoRef, className: 'cbvc-video', src: source.src, poster: posterUrl, playsInline: true, preload: 'auto', onClick: togglePlay, onLoadedMetadata: (event) => {
|
|
171
|
+
const seen = event.currentTarget.duration;
|
|
172
|
+
// The element's own metadata wins over anything the catalog rounded.
|
|
173
|
+
if (Number.isFinite(seen) && seen > 0)
|
|
174
|
+
setDuration(seen);
|
|
175
|
+
}, onLoadedData: onLoadedData, onPlay: () => setPlaying(true), onPause: () => setPlaying(false), onTimeUpdate: (event) => setPlayhead(event.currentTarget.currentTime), onSeeked: (event) => setPlayhead(event.currentTarget.currentTime), onError: (event) => {
|
|
176
|
+
if (source.exhausted(event.currentTarget))
|
|
177
|
+
setFailedSrc(source.key);
|
|
178
|
+
} }, source.key)) : (_jsx("p", { className: 'cbvc-video cbvc-nofilm', role: 'status', children: cannotShow })) }), _jsxs("div", { className: 'cbvc-deck', children: [duration > 0 ? (_jsx(CutTimeline, { duration: duration, fps: fps, playhead: playhead, segments: segments, onSeek: seek, onToggle: toggle, transport: transport })) : (_jsx("div", { className: 'cbvc-tools', children: transport })), plan.splits.length > 0 ? (_jsx("ul", { className: 'cbvc-list', "aria-label": 'Cuts', children: segments.slice(1).map((segment) => (_jsxs("li", { className: 'cbvc-row', children: [_jsxs("button", {
|
|
179
|
+
// guardrails-ignore no-raw-action-button: a plain-CSS row inside a lazily
|
|
180
|
+
// imported, deliberately Tailwind-free editor — see `pictureEditor.css`.
|
|
181
|
+
type: 'button', className: cn(RAW_BUTTON, 'cbvc-row-goto'), onClick: () => seek(segment.start), children: [_jsx(Scissors, { "aria-hidden": 'true', size: 12 }), " ", frameTimecode(segment.start, fps)] }), _jsx(IconButton, { size: 'sm', label: `Undo the cut at ${frameTimecode(segment.start, fps)}`, tooltip: 'Undo this cut \u2014 the sections either side become one again', onClick: () => uncut(segment.start), children: _jsx(Undo2, { "aria-hidden": 'true' }) })] }, `cut-${segment.key}`))) })) : null, _jsxs("div", { className: 'cbvc-note', children: [_jsx("p", { children: "Each cut lands on the frame you mark: the trimmed copy is re-encoded at every join." }), note ? _jsx("div", { children: note }) : null] }), error ? (_jsx("p", { className: 'cbvc-error', role: 'alert', children: error })) : null] }), _jsx(ActionBar, { className: 'cbvc-foot', secondary: _jsx(Button, { variant: 'secondary', onClick: guardedClose, tooltip: 'Close without sending anything', children: "Cancel" }), primary: _jsx(Button, { onClick: () => void submit(), disabled: submitting || problem !== null, tooltip: problem ?? 'Queue the cuts — the edited copy arrives beside the original', children: submitting ? 'Sending…' : submitLabel }), children: _jsx("p", { className: 'cbvc-summary', children: duration > 0 ? (_jsxs(_Fragment, { children: [_jsx("strong", { children: cutTimecode(keptSeconds(cuts, duration)) }), " kept of ", cutTimecode(duration), cuts.length > 0
|
|
182
|
+
? ` — removing ${cutTimecode(cutSeconds(cuts, duration))} in ${cuts.length === 1 ? '1 section' : `${cuts.length} sections`}`
|
|
183
|
+
: segments.length > 1
|
|
184
|
+
? ' — nothing marked for removal yet'
|
|
185
|
+
: ''] })) : cannotShow === null ? ('Reading the clip…') : (
|
|
186
|
+
// 🔴 Only a mounted film is being read. With none, this said "Reading the clip…"
|
|
187
|
+
// forever beside the reason there was nothing to read (owner, 2026-10-27).
|
|
188
|
+
'Its length is not known.') }) }), discardOverlay] }) }));
|
|
155
189
|
}
|
|
156
190
|
//# sourceMappingURL=VideoCutEditor.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VideoCutEditor.js","sourceRoot":"","sources":["../../../src/react/media/VideoCutEditor.tsx"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"VideoCutEditor.js","sourceRoot":"","sources":["../../../src/react/media/VideoCutEditor.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The arithmetic under the Trim page's timeline: frames, zoom, and the ruler (forge task 4311).
|
|
3
|
+
*
|
|
4
|
+
* Owner, 2026-11-03: *"a full Trim page with a zoomable timeline, down to frame-by-frame
|
|
5
|
+
* selection."* Everything here is a pure function of numbers, so `cutTimelineMath.spec.ts` proves
|
|
6
|
+
* it without a browser; `e2e/trim-page.spec.ts` proves the same numbers on a real clip.
|
|
7
|
+
*
|
|
8
|
+
* Times stay fractional SECONDS, the unit `cursedbelt-core/media/video-cuts` and binary-server's
|
|
9
|
+
* encode share. A frame is the half-open span `[k / fps, (k + 1) / fps)`, which is also how the
|
|
10
|
+
* encode reads a kept span (`trim=start:end` in `cutArgs`), so "the split is on frame k" and
|
|
11
|
+
* "the encode cuts at frame k" are the same number.
|
|
12
|
+
*/
|
|
13
|
+
/** The rate to draw with until the clip says otherwise — the commonest one, and never a claim. */
|
|
14
|
+
export declare const ASSUMED_FPS = 30;
|
|
15
|
+
/** Deepest zoom: adjacent frames this far apart (the task's "one frame per ~12 px"). */
|
|
16
|
+
export declare const FRAME_PX_AT_MAX_ZOOM = 12;
|
|
17
|
+
/** A measured or probed rate, snapped to the known rate within 0.5% of it; `null` if it is not a rate. */
|
|
18
|
+
export declare function snapFrameRate(measured: number | null | undefined): number | null;
|
|
19
|
+
/** The frame that is showing at `seconds` — the one whose span contains it. */
|
|
20
|
+
export declare function frameAt(seconds: number, fps: number): number;
|
|
21
|
+
/** Where frame `k` starts. */
|
|
22
|
+
export declare function frameStart(frame: number, fps: number): number;
|
|
23
|
+
/** `seconds`, moved onto the start of the frame showing there. A split is only ever made here. */
|
|
24
|
+
export declare function snapToFrame(seconds: number, fps: number): number;
|
|
25
|
+
/**
|
|
26
|
+
* `hh:mm:ss:ff` — SMPTE's form, the one Premiere and Resolve print: a COLON before the frame,
|
|
27
|
+
* because `00:01.10` reads as 1.1 s when it means frame 10 of 30 past the second (seen on the
|
|
28
|
+
* page's first collections screenshot). `ff` counts from 00, and for a fractional rate it is the
|
|
29
|
+
* frame since the second's own start, so the readout is clock time and never drifts the way a
|
|
30
|
+
* non-drop-frame count would on 29.97.
|
|
31
|
+
*/
|
|
32
|
+
export declare function frameTimecode(seconds: number, fps: number): string;
|
|
33
|
+
/** The two ends of the zoom, in px per second. `fit` shows the whole clip; `max` is one frame per {@link FRAME_PX_AT_MAX_ZOOM}. */
|
|
34
|
+
export declare function zoomBounds(width: number, duration: number, fps: number): {
|
|
35
|
+
fit: number;
|
|
36
|
+
max: number;
|
|
37
|
+
};
|
|
38
|
+
/** A zoom as a slider position in `[0, 1]`: logarithmic, so every notch is the same ×, from fit to frames. */
|
|
39
|
+
export declare function zoomToSlider(pps: number, bounds: {
|
|
40
|
+
fit: number;
|
|
41
|
+
max: number;
|
|
42
|
+
}): number;
|
|
43
|
+
export declare function sliderToZoom(position: number, bounds: {
|
|
44
|
+
fit: number;
|
|
45
|
+
max: number;
|
|
46
|
+
}): number;
|
|
47
|
+
/** The left edge of the view, kept so the clip never scrolls off either end. */
|
|
48
|
+
export declare function clampViewStart(start: number, pps: number, width: number, duration: number): number;
|
|
49
|
+
/**
|
|
50
|
+
* Zoom to `pps` keeping the moment under `anchorX` (px from the track's left) where it is — the
|
|
51
|
+
* gesture every map and every NLE uses, so the thing you pointed at does not slide away.
|
|
52
|
+
*/
|
|
53
|
+
export declare function zoomAround(view: {
|
|
54
|
+
start: number;
|
|
55
|
+
pps: number;
|
|
56
|
+
}, pps: number, anchorX: number, width: number, duration: number, bounds: {
|
|
57
|
+
fit: number;
|
|
58
|
+
max: number;
|
|
59
|
+
}): {
|
|
60
|
+
start: number;
|
|
61
|
+
pps: number;
|
|
62
|
+
};
|
|
63
|
+
export interface RulerStep {
|
|
64
|
+
/** Seconds between labeled ticks. */
|
|
65
|
+
label: number;
|
|
66
|
+
/** True when a label falls between whole seconds, so it must print its frame. */
|
|
67
|
+
frames: boolean;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* The ruler's labeled step for a zoom. Under a second it counts in FRAMES (1, 2, 5, 10, … of
|
|
71
|
+
* them), so at deep zoom each label names a frame and never a time between two of them.
|
|
72
|
+
*/
|
|
73
|
+
export declare function rulerStep(pps: number, fps: number, minPx?: number): RulerStep;
|
|
74
|
+
/**
|
|
75
|
+
* A ruler label: `mm:ss` for whole seconds (hours only when the clip has them), and the whole
|
|
76
|
+
* `hh:mm:ss:ff` once the step is in frames — the readout's own form, since a trimmed `00:01:10`
|
|
77
|
+
* would read as one minute ten.
|
|
78
|
+
*/
|
|
79
|
+
export declare function rulerLabel(seconds: number, fps: number, frames: boolean, duration: number): string;
|
|
80
|
+
//# sourceMappingURL=cutTimelineMath.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cutTimelineMath.d.ts","sourceRoot":"","sources":["../../../src/react/media/cutTimelineMath.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,kGAAkG;AAClG,eAAO,MAAM,WAAW,KAAK,CAAC;AAE9B,wFAAwF;AACxF,eAAO,MAAM,oBAAoB,KAAK,CAAC;AASvC,0GAA0G;AAC1G,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAIhF;AAED,+EAA+E;AAC/E,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAG5D;AAED,8BAA8B;AAC9B,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED,kGAAkG;AAClG,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAEhE;AAID;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAKlE;AAED,mIAAmI;AACnI,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAGrG;AAED,8GAA8G;AAC9G,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAGtF;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAG3F;AAED,gFAAgF;AAChF,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAGlG;AAED;;;GAGG;AACH,wBAAgB,UAAU,CACxB,IAAI,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,EACpC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GACnC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAIhC;AAKD,MAAM,WAAW,SAAS;IACxB,qCAAqC;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,iFAAiF;IACjF,MAAM,EAAE,OAAO,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,SAAS,CAQzE;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAKlG"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The arithmetic under the Trim page's timeline: frames, zoom, and the ruler (forge task 4311).
|
|
3
|
+
*
|
|
4
|
+
* Owner, 2026-11-03: *"a full Trim page with a zoomable timeline, down to frame-by-frame
|
|
5
|
+
* selection."* Everything here is a pure function of numbers, so `cutTimelineMath.spec.ts` proves
|
|
6
|
+
* it without a browser; `e2e/trim-page.spec.ts` proves the same numbers on a real clip.
|
|
7
|
+
*
|
|
8
|
+
* Times stay fractional SECONDS, the unit `cursedbelt-core/media/video-cuts` and binary-server's
|
|
9
|
+
* encode share. A frame is the half-open span `[k / fps, (k + 1) / fps)`, which is also how the
|
|
10
|
+
* encode reads a kept span (`trim=start:end` in `cutArgs`), so "the split is on frame k" and
|
|
11
|
+
* "the encode cuts at frame k" are the same number.
|
|
12
|
+
*/
|
|
13
|
+
/** The rate to draw with until the clip says otherwise — the commonest one, and never a claim. */
|
|
14
|
+
export const ASSUMED_FPS = 30;
|
|
15
|
+
/** Deepest zoom: adjacent frames this far apart (the task's "one frame per ~12 px"). */
|
|
16
|
+
export const FRAME_PX_AT_MAX_ZOOM = 12;
|
|
17
|
+
/**
|
|
18
|
+
* The rates footage is actually made at. A measured `1 / Δt` lands a hair off its rate (the
|
|
19
|
+
* container's timebase rounds each timestamp), and 29.98 fps would put every split a fraction of
|
|
20
|
+
* a frame out by the end of a long clip. The NTSC rates are written as the fractions they are.
|
|
21
|
+
*/
|
|
22
|
+
const KNOWN_RATES = [10, 12, 15, 20, 24000 / 1001, 24, 25, 30000 / 1001, 30, 48, 50, 60000 / 1001, 60, 90, 100, 120];
|
|
23
|
+
/** A measured or probed rate, snapped to the known rate within 0.5% of it; `null` if it is not a rate. */
|
|
24
|
+
export function snapFrameRate(measured) {
|
|
25
|
+
if (measured == null || !Number.isFinite(measured) || measured < 1 || measured > 1000)
|
|
26
|
+
return null;
|
|
27
|
+
const near = KNOWN_RATES.find((rate) => Math.abs(rate - measured) / rate < 0.005);
|
|
28
|
+
return near ?? Math.round(measured * 1000) / 1000;
|
|
29
|
+
}
|
|
30
|
+
/** The frame that is showing at `seconds` — the one whose span contains it. */
|
|
31
|
+
export function frameAt(seconds, fps) {
|
|
32
|
+
// The epsilon absorbs `k / fps * fps` landing a hair under `k` — 0.3 * 10 is 2.9999999999999996.
|
|
33
|
+
return Math.max(0, Math.floor(seconds * fps + 1e-6));
|
|
34
|
+
}
|
|
35
|
+
/** Where frame `k` starts. */
|
|
36
|
+
export function frameStart(frame, fps) {
|
|
37
|
+
return Math.max(0, frame) / fps;
|
|
38
|
+
}
|
|
39
|
+
/** `seconds`, moved onto the start of the frame showing there. A split is only ever made here. */
|
|
40
|
+
export function snapToFrame(seconds, fps) {
|
|
41
|
+
return frameStart(frameAt(seconds, fps), fps);
|
|
42
|
+
}
|
|
43
|
+
const pad = (n) => String(n).padStart(2, '0');
|
|
44
|
+
/**
|
|
45
|
+
* `hh:mm:ss:ff` — SMPTE's form, the one Premiere and Resolve print: a COLON before the frame,
|
|
46
|
+
* because `00:01.10` reads as 1.1 s when it means frame 10 of 30 past the second (seen on the
|
|
47
|
+
* page's first collections screenshot). `ff` counts from 00, and for a fractional rate it is the
|
|
48
|
+
* frame since the second's own start, so the readout is clock time and never drifts the way a
|
|
49
|
+
* non-drop-frame count would on 29.97.
|
|
50
|
+
*/
|
|
51
|
+
export function frameTimecode(seconds, fps) {
|
|
52
|
+
const safe = Number.isFinite(seconds) && seconds > 0 ? seconds : 0;
|
|
53
|
+
const whole = Math.floor(safe + 1e-6);
|
|
54
|
+
const ff = Math.min(Math.ceil(fps) - 1, Math.max(0, Math.floor((safe - whole) * fps + 1e-6)));
|
|
55
|
+
return `${pad(Math.floor(whole / 3600))}:${pad(Math.floor(whole / 60) % 60)}:${pad(whole % 60)}:${pad(ff)}`;
|
|
56
|
+
}
|
|
57
|
+
/** The two ends of the zoom, in px per second. `fit` shows the whole clip; `max` is one frame per {@link FRAME_PX_AT_MAX_ZOOM}. */
|
|
58
|
+
export function zoomBounds(width, duration, fps) {
|
|
59
|
+
const fit = width > 0 && duration > 0 ? width / duration : 0;
|
|
60
|
+
return { fit, max: Math.max(fit, FRAME_PX_AT_MAX_ZOOM * fps) };
|
|
61
|
+
}
|
|
62
|
+
/** A zoom as a slider position in `[0, 1]`: logarithmic, so every notch is the same ×, from fit to frames. */
|
|
63
|
+
export function zoomToSlider(pps, bounds) {
|
|
64
|
+
if (!(bounds.max > bounds.fit) || bounds.fit <= 0)
|
|
65
|
+
return 0;
|
|
66
|
+
return Math.min(1, Math.max(0, Math.log(pps / bounds.fit) / Math.log(bounds.max / bounds.fit)));
|
|
67
|
+
}
|
|
68
|
+
export function sliderToZoom(position, bounds) {
|
|
69
|
+
if (!(bounds.max > bounds.fit) || bounds.fit <= 0)
|
|
70
|
+
return bounds.fit;
|
|
71
|
+
return bounds.fit * (bounds.max / bounds.fit) ** Math.min(1, Math.max(0, position));
|
|
72
|
+
}
|
|
73
|
+
/** The left edge of the view, kept so the clip never scrolls off either end. */
|
|
74
|
+
export function clampViewStart(start, pps, width, duration) {
|
|
75
|
+
const span = pps > 0 ? width / pps : duration;
|
|
76
|
+
return Math.min(Math.max(0, duration - span), Math.max(0, start));
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Zoom to `pps` keeping the moment under `anchorX` (px from the track's left) where it is — the
|
|
80
|
+
* gesture every map and every NLE uses, so the thing you pointed at does not slide away.
|
|
81
|
+
*/
|
|
82
|
+
export function zoomAround(view, pps, anchorX, width, duration, bounds) {
|
|
83
|
+
const next = Math.min(bounds.max, Math.max(bounds.fit, pps));
|
|
84
|
+
const anchored = view.start + anchorX / view.pps;
|
|
85
|
+
return { pps: next, start: clampViewStart(anchored - anchorX / next, next, width, duration) };
|
|
86
|
+
}
|
|
87
|
+
/** Seconds between labels: the smallest step that leaves at least `minPx` between them. */
|
|
88
|
+
const LABEL_STEPS = [1, 2, 5, 10, 15, 30, 60, 120, 300, 600, 900, 1800, 3600, 7200];
|
|
89
|
+
/**
|
|
90
|
+
* The ruler's labeled step for a zoom. Under a second it counts in FRAMES (1, 2, 5, 10, … of
|
|
91
|
+
* them), so at deep zoom each label names a frame and never a time between two of them.
|
|
92
|
+
*/
|
|
93
|
+
export function rulerStep(pps, fps, minPx = 88) {
|
|
94
|
+
for (const frames of [1, 2, 5, 10, 15, 30]) {
|
|
95
|
+
const seconds = frames / fps;
|
|
96
|
+
if (seconds >= 1)
|
|
97
|
+
break;
|
|
98
|
+
if (seconds * pps >= minPx)
|
|
99
|
+
return { label: seconds, frames: true };
|
|
100
|
+
}
|
|
101
|
+
const step = LABEL_STEPS.find((s) => s * pps >= minPx) ?? LABEL_STEPS.at(-1);
|
|
102
|
+
return { label: step, frames: false };
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* A ruler label: `mm:ss` for whole seconds (hours only when the clip has them), and the whole
|
|
106
|
+
* `hh:mm:ss:ff` once the step is in frames — the readout's own form, since a trimmed `00:01:10`
|
|
107
|
+
* would read as one minute ten.
|
|
108
|
+
*/
|
|
109
|
+
export function rulerLabel(seconds, fps, frames, duration) {
|
|
110
|
+
const full = frameTimecode(seconds, fps);
|
|
111
|
+
if (frames)
|
|
112
|
+
return full;
|
|
113
|
+
const clock = full.slice(0, -3);
|
|
114
|
+
return duration >= 3600 ? clock : clock.slice(3);
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=cutTimelineMath.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cutTimelineMath.js","sourceRoot":"","sources":["../../../src/react/media/cutTimelineMath.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* The clip's frame rate, for stepping and snapping on the Trim page (forge task 4311).
|
|
4
|
+
*
|
|
5
|
+
* `probed` (the catalog's ffprobe figure) wins whenever there is one. Without it the rate is
|
|
6
|
+
* MEASURED from the clip itself, by two seeks the moment it can show a frame:
|
|
7
|
+
*
|
|
8
|
+
* 1. seek a little in; `requestVideoFrameCallback` reports the `mediaTime` of the frame it
|
|
9
|
+
* presented — the START of the frame containing that moment;
|
|
10
|
+
* 2. seek a hair before that start; the frame presented now is the one before it.
|
|
11
|
+
*
|
|
12
|
+
* The difference is one frame's duration, exactly — a container's timestamps, not a stopwatch
|
|
13
|
+
* over playback, so it needs no play, no sound and no luck with the scheduler. Then the clip
|
|
14
|
+
* goes back to where it was.
|
|
15
|
+
*
|
|
16
|
+
* 🔴 Until it knows, it says so (`measured: false`) and draws at {@link ASSUMED_FPS}: a
|
|
17
|
+
* readout that LOOKS frame-exact on a guessed rate is the very dishonesty the editor's header
|
|
18
|
+
* forbids. A browser with no `requestVideoFrameCallback`, or a clip that never presents a frame
|
|
19
|
+
* to it, stays on the assumption and stays labeled as one.
|
|
20
|
+
*/
|
|
21
|
+
export interface FrameRate {
|
|
22
|
+
fps: number;
|
|
23
|
+
/** `probe` from the catalog, `measured` from the clip, `assumed` when neither answered. */
|
|
24
|
+
source: 'probe' | 'measured' | 'assumed';
|
|
25
|
+
}
|
|
26
|
+
/** One frame's duration, by the two-seek reading above; null when the clip would not say. */
|
|
27
|
+
export declare function measureFrameRate(video: HTMLVideoElement): Promise<number | null>;
|
|
28
|
+
export declare function useFrameRate(videoRef: React.RefObject<HTMLVideoElement | null>, probed: number | null | undefined,
|
|
29
|
+
/** Changes when a new clip loads — each source is measured once. */
|
|
30
|
+
sourceKey: string): {
|
|
31
|
+
rate: FrameRate;
|
|
32
|
+
onLoadedData: () => void;
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=useFrameRate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useFrameRate.d.ts","sourceRoot":"","sources":["../../../src/react/media/useFrameRate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,2FAA2F;IAC3F,MAAM,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS,CAAC;CAC1C;AA4BD,6FAA6F;AAC7F,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAetF;AAED,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC,gBAAgB,GAAG,IAAI,CAAC,EAClD,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS;AACjC,oEAAoE;AACpE,SAAS,EAAE,MAAM,GAChB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,YAAY,EAAE,MAAM,IAAI,CAAA;CAAE,CAkB/C"}
|