@video-editor/shared 0.0.1-beta.9 → 1.0.0-beta.1
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/index.d.ts +125 -2
- package/dist/index.js +110 -25
- package/package.json +3 -2
package/dist/index.d.ts
CHANGED
|
@@ -6,13 +6,26 @@ declare interface AudioSegment<T extends ITrackType> extends ISegment<T> {
|
|
|
6
6
|
fadeInDuration?: number;
|
|
7
7
|
fadeOutDuration?: number;
|
|
8
8
|
playRate?: number;
|
|
9
|
+
/**
|
|
10
|
+
* Play the same source window [fromTime, fromTime + (endTime - startTime) * playRate]
|
|
11
|
+
* backwards. `fromTime` still anchors the window start. Default false.
|
|
12
|
+
*/
|
|
13
|
+
reversed?: boolean;
|
|
9
14
|
}
|
|
10
15
|
|
|
16
|
+
/**
|
|
17
|
+
* CSS-style cubic-bezier easing: solve x(t) = progress for t, return y(t).
|
|
18
|
+
* Newton iterations with a bisection fallback; no dependencies.
|
|
19
|
+
*/
|
|
20
|
+
export declare function cubicBezierEase(x1: number, y1: number, x2: number, y2: number, progress: number): number;
|
|
21
|
+
|
|
11
22
|
/**
|
|
12
23
|
* Protocol version constant
|
|
13
24
|
*/
|
|
14
25
|
export declare const CURRENT_PROTOCOL_VERSION: "1.0.0";
|
|
15
26
|
|
|
27
|
+
export declare function easeKeyframeProgress(easing: IKeyframeEasing | undefined, progress: number): number;
|
|
28
|
+
|
|
16
29
|
declare interface EffectSegment<T extends ITrackType> extends ISegment<T> {
|
|
17
30
|
segmentType: T;
|
|
18
31
|
effectId: string;
|
|
@@ -50,6 +63,14 @@ export declare interface IBackground {
|
|
|
50
63
|
opacity?: number;
|
|
51
64
|
}
|
|
52
65
|
|
|
66
|
+
/** Chroma key (green/blue screen) removal for a visual segment. */
|
|
67
|
+
export declare interface IChromaKey {
|
|
68
|
+
color: string;
|
|
69
|
+
similarity: number;
|
|
70
|
+
smoothness?: number;
|
|
71
|
+
spillSuppress?: number;
|
|
72
|
+
}
|
|
73
|
+
|
|
53
74
|
export declare interface IDropShadow {
|
|
54
75
|
color?: string;
|
|
55
76
|
opacity?: number;
|
|
@@ -71,9 +92,9 @@ declare interface IFramesSegment extends ISegment<'frames'> {
|
|
|
71
92
|
opacity?: number;
|
|
72
93
|
fillMode?: IFillMode;
|
|
73
94
|
animation?: IAnimation;
|
|
74
|
-
transitionIn?: ITransition;
|
|
75
|
-
transitionOut?: ITransition;
|
|
76
95
|
palette?: IPalette;
|
|
96
|
+
mask?: IMask;
|
|
97
|
+
chromaKey?: IChromaKey;
|
|
77
98
|
background?: `rgba(${number},${number},${number},${number})`;
|
|
78
99
|
}
|
|
79
100
|
|
|
@@ -84,6 +105,38 @@ export declare interface IImageFramesSegment extends IFramesSegment {
|
|
|
84
105
|
format: 'img' | 'gif';
|
|
85
106
|
}
|
|
86
107
|
|
|
108
|
+
export declare interface IKeyframe {
|
|
109
|
+
/** Timeline time relative to segment.startTime, in ms (not scaled by playRate). */
|
|
110
|
+
timeMs: number;
|
|
111
|
+
value: number;
|
|
112
|
+
/** Easing toward the next keyframe. Defaults to 'linear'. */
|
|
113
|
+
easing?: IKeyframeEasing;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export declare type IKeyframeEasing = 'linear' | 'easeIn' | 'easeOut' | 'easeInOut' | [number, number, number, number];
|
|
117
|
+
|
|
118
|
+
export declare type IKeyframeProperty = 'opacity' | 'position.x' | 'position.y' | 'scale' | 'rotation' | 'volume' | 'intensity';
|
|
119
|
+
|
|
120
|
+
export declare interface IKeyframeTrack {
|
|
121
|
+
property: IKeyframeProperty;
|
|
122
|
+
/** Sorted ascending by timeMs; at least one frame. */
|
|
123
|
+
frames: IKeyframe[];
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Shape mask applied to a visual segment. The mask lives in the segment's own
|
|
128
|
+
* display box: `center` is normalized to [-1, 1] with the origin at the box
|
|
129
|
+
* center (+x right, +y up), `size` is the box-relative full extent in [0, 1].
|
|
130
|
+
*/
|
|
131
|
+
export declare interface IMask {
|
|
132
|
+
shape: 'rect' | 'ellipse';
|
|
133
|
+
center: [number, number];
|
|
134
|
+
size: [number, number];
|
|
135
|
+
feather?: number;
|
|
136
|
+
rotation?: number;
|
|
137
|
+
inverse?: boolean;
|
|
138
|
+
}
|
|
139
|
+
|
|
87
140
|
export declare interface IPalette {
|
|
88
141
|
temperature: number;
|
|
89
142
|
hue: number;
|
|
@@ -115,6 +168,8 @@ export declare interface ISegment<T extends ITrackType = ITrackType> {
|
|
|
115
168
|
endTime: number;
|
|
116
169
|
segmentType: T;
|
|
117
170
|
url?: string;
|
|
171
|
+
/** Optional per-property animation curves; see docs/rfcs/0002-keyframe-curves.md. */
|
|
172
|
+
keyframes?: IKeyframeTrack[];
|
|
118
173
|
extra?: SegmentExtra<T> | null;
|
|
119
174
|
}
|
|
120
175
|
|
|
@@ -183,6 +238,18 @@ export declare type ITrack<T extends ITrackType> = {
|
|
|
183
238
|
trackId: string;
|
|
184
239
|
trackType: T;
|
|
185
240
|
children: TrackTypeMapSegment[T][];
|
|
241
|
+
/**
|
|
242
|
+
* When true, the track's visual output is skipped (renderer draws nothing for
|
|
243
|
+
* its segments). Purely a presentation flag: the segments stay in the protocol
|
|
244
|
+
* and keep participating in timeline layout, duration and export.
|
|
245
|
+
*/
|
|
246
|
+
hidden?: boolean;
|
|
247
|
+
/**
|
|
248
|
+
* When true, the track's audio output is skipped (audio segments and the audio
|
|
249
|
+
* of video segments stay silent). Purely a presentation flag: it never mutates
|
|
250
|
+
* per-segment `volume`.
|
|
251
|
+
*/
|
|
252
|
+
muted?: boolean;
|
|
186
253
|
extra?: TrackExtra<T> | null;
|
|
187
254
|
} & (T extends 'frames' ? {
|
|
188
255
|
isMain?: boolean;
|
|
@@ -202,11 +269,21 @@ export declare interface ITransition {
|
|
|
202
269
|
duration: number;
|
|
203
270
|
}
|
|
204
271
|
|
|
272
|
+
export declare interface ITransitionEdge extends ITransition {
|
|
273
|
+
fromSegmentId: string;
|
|
274
|
+
toSegmentId: string;
|
|
275
|
+
}
|
|
276
|
+
|
|
205
277
|
export declare interface IVideoFramesSegment extends IFramesSegment {
|
|
206
278
|
type: 'video';
|
|
207
279
|
fromTime?: number;
|
|
208
280
|
volume?: number;
|
|
209
281
|
playRate?: number;
|
|
282
|
+
/**
|
|
283
|
+
* Play the same source window [fromTime, fromTime + (endTime - startTime) * playRate]
|
|
284
|
+
* backwards. `fromTime` still anchors the window start. Default false.
|
|
285
|
+
*/
|
|
286
|
+
reversed?: boolean;
|
|
210
287
|
}
|
|
211
288
|
|
|
212
289
|
/**
|
|
@@ -221,14 +298,40 @@ export declare interface IVideoProtocol {
|
|
|
221
298
|
height: number;
|
|
222
299
|
fps: number;
|
|
223
300
|
tracks: TrackUnion[];
|
|
301
|
+
transitions?: ITransitionEdge[];
|
|
224
302
|
extra?: ProtocolExtra | null;
|
|
225
303
|
}
|
|
226
304
|
|
|
305
|
+
/**
|
|
306
|
+
* Map an absolute timeline time (ms) onto the source media time (ms).
|
|
307
|
+
*
|
|
308
|
+
* Forward: `fromTime + relMs * rate`
|
|
309
|
+
* Reversed: `fromTime + (span - relMs * rate)` — the same source window
|
|
310
|
+
* `[fromTime, fromTime + span]` read from its end back to its start.
|
|
311
|
+
*/
|
|
312
|
+
export declare function mapSourceTimeMs(segment: SourceTimedSegment, timelineMs: number): number;
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Shared source-time mapping helpers.
|
|
316
|
+
*
|
|
317
|
+
* A media segment occupies a timeline window `[startTime, endTime]` and reads a
|
|
318
|
+
* source window `[fromTime, fromTime + sourceSpanMs]`. Every consumer (preview
|
|
319
|
+
* evaluator, transition planner, audio manager, compose pipeline) must agree on
|
|
320
|
+
* this mapping, otherwise preview and export drift apart.
|
|
321
|
+
*/
|
|
322
|
+
/**
|
|
323
|
+
* Clamp a play rate into the supported range.
|
|
324
|
+
* Non-finite or missing values fall back to 1.
|
|
325
|
+
*/
|
|
326
|
+
export declare function normalizePlayRate(playRate?: number): number;
|
|
327
|
+
|
|
227
328
|
export declare type ProtocolExtra = ProtocolExtraRegistry extends Record<string, never> ? Record<string, never> : NonNullable<ProtocolExtraRegistry>;
|
|
228
329
|
|
|
229
330
|
export declare interface ProtocolExtraRegistry {
|
|
230
331
|
}
|
|
231
332
|
|
|
333
|
+
export declare function sampleKeyframes(track: IKeyframeTrack, relMs: number): number;
|
|
334
|
+
|
|
232
335
|
export declare type SegmentExtra<T extends ITrackType> = T extends keyof SegmentExtraRegistry ? NonNullable<SegmentExtraRegistry[T]> : Record<string, never>;
|
|
233
336
|
|
|
234
337
|
export declare interface SegmentExtraRegistry {
|
|
@@ -236,6 +339,24 @@ export declare interface SegmentExtraRegistry {
|
|
|
236
339
|
|
|
237
340
|
export declare type SegmentUnion = TrackTypeMapSegment[ITrackType];
|
|
238
341
|
|
|
342
|
+
/**
|
|
343
|
+
* Length of the source window consumed by the segment, in ms.
|
|
344
|
+
* `(endTime - startTime) * playRate`.
|
|
345
|
+
*/
|
|
346
|
+
export declare function sourceSpanMs(segment: SourceTimedSegment): number;
|
|
347
|
+
|
|
348
|
+
/** Minimal shape needed to map a timeline time onto a source time. */
|
|
349
|
+
export declare interface SourceTimedSegment {
|
|
350
|
+
startTime: number;
|
|
351
|
+
endTime: number;
|
|
352
|
+
/** Source window start in ms. Defaults to 0. */
|
|
353
|
+
fromTime?: number;
|
|
354
|
+
/** Playback speed multiplier. Defaults to 1. */
|
|
355
|
+
playRate?: number;
|
|
356
|
+
/** Play the same source window backwards. Defaults to false. */
|
|
357
|
+
reversed?: boolean;
|
|
358
|
+
}
|
|
359
|
+
|
|
239
360
|
declare interface StickerSegment<T extends ITrackType> extends ISegment<T> {
|
|
240
361
|
segmentType: T;
|
|
241
362
|
format: 'img' | 'gif';
|
|
@@ -244,6 +365,8 @@ declare interface StickerSegment<T extends ITrackType> extends ISegment<T> {
|
|
|
244
365
|
animation?: IAnimation;
|
|
245
366
|
transform?: ITransform;
|
|
246
367
|
palette?: IPalette;
|
|
368
|
+
mask?: IMask;
|
|
369
|
+
chromaKey?: IChromaKey;
|
|
247
370
|
}
|
|
248
371
|
|
|
249
372
|
declare interface TextSegment<T extends ITrackType> extends ISegment<T> {
|
package/dist/index.js
CHANGED
|
@@ -1,46 +1,131 @@
|
|
|
1
|
-
const
|
|
2
|
-
|
|
1
|
+
const S = {
|
|
2
|
+
easeIn: [0.42, 0, 1, 1],
|
|
3
|
+
easeOut: [0, 0, 0.58, 1],
|
|
4
|
+
easeInOut: [0.42, 0, 0.58, 1]
|
|
5
|
+
};
|
|
6
|
+
function E(e, n) {
|
|
7
|
+
const t = e.frames, i = t[0];
|
|
8
|
+
if (!i)
|
|
9
|
+
return Number.NaN;
|
|
10
|
+
if (t.length === 1 || n <= i.timeMs)
|
|
11
|
+
return i.value;
|
|
12
|
+
const r = t[t.length - 1];
|
|
13
|
+
if (n >= r.timeMs)
|
|
14
|
+
return r.value;
|
|
15
|
+
for (let a = 0; a < t.length - 1; a++) {
|
|
16
|
+
const s = t[a], c = t[a + 1];
|
|
17
|
+
if (n < s.timeMs || n > c.timeMs)
|
|
18
|
+
continue;
|
|
19
|
+
const u = c.timeMs - s.timeMs;
|
|
20
|
+
if (u <= 0)
|
|
21
|
+
return c.value;
|
|
22
|
+
const f = (n - s.timeMs) / u;
|
|
23
|
+
return s.value + (c.value - s.value) * p(s.easing, f);
|
|
24
|
+
}
|
|
25
|
+
return r.value;
|
|
26
|
+
}
|
|
27
|
+
function p(e, n) {
|
|
28
|
+
if (!e || e === "linear")
|
|
29
|
+
return n;
|
|
30
|
+
const t = Array.isArray(e) ? e : S[e];
|
|
31
|
+
return t ? d(t[0], t[1], t[2], t[3], n) : n;
|
|
32
|
+
}
|
|
33
|
+
function d(e, n, t, i, r) {
|
|
34
|
+
if (r <= 0)
|
|
35
|
+
return 0;
|
|
36
|
+
if (r >= 1)
|
|
37
|
+
return 1;
|
|
38
|
+
const a = (o) => y(o, e, t), s = (o) => y(o, n, i), c = (o) => v(o, e, t);
|
|
39
|
+
let u = r;
|
|
40
|
+
for (let o = 0; o < 8; o++) {
|
|
41
|
+
const T = a(u) - r;
|
|
42
|
+
if (Math.abs(T) < 1e-6)
|
|
43
|
+
return s(u);
|
|
44
|
+
const M = c(u);
|
|
45
|
+
if (Math.abs(M) < 1e-6)
|
|
46
|
+
break;
|
|
47
|
+
u -= T / M;
|
|
48
|
+
}
|
|
49
|
+
let f = 0, l = 1;
|
|
50
|
+
for (u = r; l - f > 1e-6; )
|
|
51
|
+
a(u) < r ? f = u : l = u, u = (f + l) / 2;
|
|
52
|
+
return s(u);
|
|
53
|
+
}
|
|
54
|
+
function y(e, n, t) {
|
|
55
|
+
const i = 1 - e;
|
|
56
|
+
return 3 * i * i * e * n + 3 * i * e * e * t + e * e * e;
|
|
57
|
+
}
|
|
58
|
+
function v(e, n, t) {
|
|
59
|
+
const i = 1 - e;
|
|
60
|
+
return 3 * i * i * n + 6 * i * e * (t - n) + 3 * e * e * (1 - t);
|
|
61
|
+
}
|
|
62
|
+
const A = 0.1, x = 100;
|
|
63
|
+
function h(e) {
|
|
64
|
+
return typeof e != "number" || !Number.isFinite(e) ? 1 : Math.max(A, Math.min(x, e));
|
|
65
|
+
}
|
|
66
|
+
function m(e) {
|
|
67
|
+
return typeof e != "number" || !Number.isFinite(e) ? 0 : Math.max(0, e);
|
|
68
|
+
}
|
|
69
|
+
function b(e) {
|
|
70
|
+
return Math.max(0, m(e.endTime) - m(e.startTime)) * h(e.playRate);
|
|
71
|
+
}
|
|
72
|
+
function R(e, n) {
|
|
73
|
+
const t = Math.max(0, m(n) - m(e.startTime)), i = m(e.fromTime), r = h(e.playRate);
|
|
74
|
+
if (e.reversed === !0) {
|
|
75
|
+
const a = b(e);
|
|
76
|
+
return Math.max(i, i + Math.max(0, a - t * r));
|
|
77
|
+
}
|
|
78
|
+
return Math.max(0, i + t * r);
|
|
79
|
+
}
|
|
80
|
+
const _ = "1.0.0";
|
|
81
|
+
function I(e) {
|
|
3
82
|
return e.segmentType === "frames";
|
|
4
83
|
}
|
|
5
|
-
function
|
|
84
|
+
function O(e) {
|
|
6
85
|
return e.segmentType === "frames" && "type" in e && e.type === "video";
|
|
7
86
|
}
|
|
8
|
-
function
|
|
87
|
+
function P(e) {
|
|
9
88
|
return e.segmentType === "text";
|
|
10
89
|
}
|
|
11
|
-
function
|
|
90
|
+
function k(e) {
|
|
12
91
|
return e.segmentType === "sticker";
|
|
13
92
|
}
|
|
14
|
-
function
|
|
93
|
+
function z(e) {
|
|
15
94
|
return e.segmentType === "audio";
|
|
16
95
|
}
|
|
17
|
-
function
|
|
96
|
+
function F(e) {
|
|
18
97
|
return e.segmentType === "effect";
|
|
19
98
|
}
|
|
20
|
-
function
|
|
99
|
+
function D(e) {
|
|
21
100
|
return e.segmentType === "filter";
|
|
22
101
|
}
|
|
23
|
-
function
|
|
102
|
+
function Y(e) {
|
|
24
103
|
return e.endTime - e.startTime;
|
|
25
104
|
}
|
|
26
|
-
function g(e,
|
|
27
|
-
return e >=
|
|
105
|
+
function g(e, n) {
|
|
106
|
+
return e >= n.startTime && e < n.endTime;
|
|
28
107
|
}
|
|
29
|
-
const
|
|
30
|
-
function
|
|
31
|
-
return
|
|
108
|
+
const N = ["frames", "text", "sticker", "audio", "effect", "filter"];
|
|
109
|
+
function C(e) {
|
|
110
|
+
return N.includes(e);
|
|
32
111
|
}
|
|
33
112
|
export {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
113
|
+
_ as CURRENT_PROTOCOL_VERSION,
|
|
114
|
+
N as TRACK_TYPES,
|
|
115
|
+
d as cubicBezierEase,
|
|
116
|
+
p as easeKeyframeProgress,
|
|
117
|
+
Y as getSegmentDuration,
|
|
118
|
+
z as isAudioSegment,
|
|
119
|
+
F as isEffectSegment,
|
|
120
|
+
D as isFilterSegment,
|
|
121
|
+
I as isFramesSegment,
|
|
122
|
+
k as isStickerSegment,
|
|
123
|
+
P as isTextSegment,
|
|
43
124
|
g as isTimeInSegment,
|
|
44
|
-
|
|
45
|
-
|
|
125
|
+
C as isValidTrackType,
|
|
126
|
+
O as isVideoFramesSegment,
|
|
127
|
+
R as mapSourceTimeMs,
|
|
128
|
+
h as normalizePlayRate,
|
|
129
|
+
E as sampleKeyframes,
|
|
130
|
+
b as sourceSpanMs
|
|
46
131
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@video-editor/shared",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0
|
|
4
|
+
"version": "1.0.0-beta.1",
|
|
5
5
|
"description": "video editor shared libs",
|
|
6
6
|
"author": "",
|
|
7
7
|
"license": "ISC",
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"dist"
|
|
21
21
|
],
|
|
22
22
|
"scripts": {
|
|
23
|
-
"build": "vite build --config vite.config.ts"
|
|
23
|
+
"build": "vite build --config vite.config.ts",
|
|
24
|
+
"test": "vitest run --config ./vitest.config.ts"
|
|
24
25
|
}
|
|
25
26
|
}
|