@video-editor/shared 0.0.1-beta.9 → 1.0.0-beta.2
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 +131 -2
- package/dist/index.js +110 -25
- package/package.json +3 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,18 +1,33 @@
|
|
|
1
1
|
declare interface AudioSegment<T extends ITrackType> extends ISegment<T> {
|
|
2
2
|
segmentType: T;
|
|
3
3
|
url: string;
|
|
4
|
+
/** Stable library identity; `url` remains the last-known usable location. */
|
|
5
|
+
assetId?: string;
|
|
4
6
|
fromTime?: number;
|
|
5
7
|
volume?: number;
|
|
6
8
|
fadeInDuration?: number;
|
|
7
9
|
fadeOutDuration?: number;
|
|
8
10
|
playRate?: number;
|
|
11
|
+
/**
|
|
12
|
+
* Play the same source window [fromTime, fromTime + (endTime - startTime) * playRate]
|
|
13
|
+
* backwards. `fromTime` still anchors the window start. Default false.
|
|
14
|
+
*/
|
|
15
|
+
reversed?: boolean;
|
|
9
16
|
}
|
|
10
17
|
|
|
18
|
+
/**
|
|
19
|
+
* CSS-style cubic-bezier easing: solve x(t) = progress for t, return y(t).
|
|
20
|
+
* Newton iterations with a bisection fallback; no dependencies.
|
|
21
|
+
*/
|
|
22
|
+
export declare function cubicBezierEase(x1: number, y1: number, x2: number, y2: number, progress: number): number;
|
|
23
|
+
|
|
11
24
|
/**
|
|
12
25
|
* Protocol version constant
|
|
13
26
|
*/
|
|
14
27
|
export declare const CURRENT_PROTOCOL_VERSION: "1.0.0";
|
|
15
28
|
|
|
29
|
+
export declare function easeKeyframeProgress(easing: IKeyframeEasing | undefined, progress: number): number;
|
|
30
|
+
|
|
16
31
|
declare interface EffectSegment<T extends ITrackType> extends ISegment<T> {
|
|
17
32
|
segmentType: T;
|
|
18
33
|
effectId: string;
|
|
@@ -50,6 +65,14 @@ export declare interface IBackground {
|
|
|
50
65
|
opacity?: number;
|
|
51
66
|
}
|
|
52
67
|
|
|
68
|
+
/** Chroma key (green/blue screen) removal for a visual segment. */
|
|
69
|
+
export declare interface IChromaKey {
|
|
70
|
+
color: string;
|
|
71
|
+
similarity: number;
|
|
72
|
+
smoothness?: number;
|
|
73
|
+
spillSuppress?: number;
|
|
74
|
+
}
|
|
75
|
+
|
|
53
76
|
export declare interface IDropShadow {
|
|
54
77
|
color?: string;
|
|
55
78
|
opacity?: number;
|
|
@@ -67,13 +90,15 @@ export declare type IFilterSegment = FilterSegment<'filter'>;
|
|
|
67
90
|
declare interface IFramesSegment extends ISegment<'frames'> {
|
|
68
91
|
type: 'image' | 'video' | '3D';
|
|
69
92
|
url: string;
|
|
93
|
+
/** Stable library identity; `url` remains the last-known usable location. */
|
|
94
|
+
assetId?: string;
|
|
70
95
|
transform?: ITransform;
|
|
71
96
|
opacity?: number;
|
|
72
97
|
fillMode?: IFillMode;
|
|
73
98
|
animation?: IAnimation;
|
|
74
|
-
transitionIn?: ITransition;
|
|
75
|
-
transitionOut?: ITransition;
|
|
76
99
|
palette?: IPalette;
|
|
100
|
+
mask?: IMask;
|
|
101
|
+
chromaKey?: IChromaKey;
|
|
77
102
|
background?: `rgba(${number},${number},${number},${number})`;
|
|
78
103
|
}
|
|
79
104
|
|
|
@@ -84,6 +109,38 @@ export declare interface IImageFramesSegment extends IFramesSegment {
|
|
|
84
109
|
format: 'img' | 'gif';
|
|
85
110
|
}
|
|
86
111
|
|
|
112
|
+
export declare interface IKeyframe {
|
|
113
|
+
/** Timeline time relative to segment.startTime, in ms (not scaled by playRate). */
|
|
114
|
+
timeMs: number;
|
|
115
|
+
value: number;
|
|
116
|
+
/** Easing toward the next keyframe. Defaults to 'linear'. */
|
|
117
|
+
easing?: IKeyframeEasing;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export declare type IKeyframeEasing = 'linear' | 'easeIn' | 'easeOut' | 'easeInOut' | [number, number, number, number];
|
|
121
|
+
|
|
122
|
+
export declare type IKeyframeProperty = 'opacity' | 'position.x' | 'position.y' | 'scale' | 'rotation' | 'volume' | 'intensity';
|
|
123
|
+
|
|
124
|
+
export declare interface IKeyframeTrack {
|
|
125
|
+
property: IKeyframeProperty;
|
|
126
|
+
/** Sorted ascending by timeMs; at least one frame. */
|
|
127
|
+
frames: IKeyframe[];
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Shape mask applied to a visual segment. The mask lives in the segment's own
|
|
132
|
+
* display box: `center` is normalized to [-1, 1] with the origin at the box
|
|
133
|
+
* center (+x right, +y up), `size` is the box-relative full extent in [0, 1].
|
|
134
|
+
*/
|
|
135
|
+
export declare interface IMask {
|
|
136
|
+
shape: 'rect' | 'ellipse';
|
|
137
|
+
center: [number, number];
|
|
138
|
+
size: [number, number];
|
|
139
|
+
feather?: number;
|
|
140
|
+
rotation?: number;
|
|
141
|
+
inverse?: boolean;
|
|
142
|
+
}
|
|
143
|
+
|
|
87
144
|
export declare interface IPalette {
|
|
88
145
|
temperature: number;
|
|
89
146
|
hue: number;
|
|
@@ -115,6 +172,8 @@ export declare interface ISegment<T extends ITrackType = ITrackType> {
|
|
|
115
172
|
endTime: number;
|
|
116
173
|
segmentType: T;
|
|
117
174
|
url?: string;
|
|
175
|
+
/** Optional per-property animation curves; see docs/rfcs/0002-keyframe-curves.md. */
|
|
176
|
+
keyframes?: IKeyframeTrack[];
|
|
118
177
|
extra?: SegmentExtra<T> | null;
|
|
119
178
|
}
|
|
120
179
|
|
|
@@ -183,6 +242,18 @@ export declare type ITrack<T extends ITrackType> = {
|
|
|
183
242
|
trackId: string;
|
|
184
243
|
trackType: T;
|
|
185
244
|
children: TrackTypeMapSegment[T][];
|
|
245
|
+
/**
|
|
246
|
+
* When true, the track's visual output is skipped (renderer draws nothing for
|
|
247
|
+
* its segments). Purely a presentation flag: the segments stay in the protocol
|
|
248
|
+
* and keep participating in timeline layout, duration and export.
|
|
249
|
+
*/
|
|
250
|
+
hidden?: boolean;
|
|
251
|
+
/**
|
|
252
|
+
* When true, the track's audio output is skipped (audio segments and the audio
|
|
253
|
+
* of video segments stay silent). Purely a presentation flag: it never mutates
|
|
254
|
+
* per-segment `volume`.
|
|
255
|
+
*/
|
|
256
|
+
muted?: boolean;
|
|
186
257
|
extra?: TrackExtra<T> | null;
|
|
187
258
|
} & (T extends 'frames' ? {
|
|
188
259
|
isMain?: boolean;
|
|
@@ -202,11 +273,21 @@ export declare interface ITransition {
|
|
|
202
273
|
duration: number;
|
|
203
274
|
}
|
|
204
275
|
|
|
276
|
+
export declare interface ITransitionEdge extends ITransition {
|
|
277
|
+
fromSegmentId: string;
|
|
278
|
+
toSegmentId: string;
|
|
279
|
+
}
|
|
280
|
+
|
|
205
281
|
export declare interface IVideoFramesSegment extends IFramesSegment {
|
|
206
282
|
type: 'video';
|
|
207
283
|
fromTime?: number;
|
|
208
284
|
volume?: number;
|
|
209
285
|
playRate?: number;
|
|
286
|
+
/**
|
|
287
|
+
* Play the same source window [fromTime, fromTime + (endTime - startTime) * playRate]
|
|
288
|
+
* backwards. `fromTime` still anchors the window start. Default false.
|
|
289
|
+
*/
|
|
290
|
+
reversed?: boolean;
|
|
210
291
|
}
|
|
211
292
|
|
|
212
293
|
/**
|
|
@@ -221,14 +302,40 @@ export declare interface IVideoProtocol {
|
|
|
221
302
|
height: number;
|
|
222
303
|
fps: number;
|
|
223
304
|
tracks: TrackUnion[];
|
|
305
|
+
transitions?: ITransitionEdge[];
|
|
224
306
|
extra?: ProtocolExtra | null;
|
|
225
307
|
}
|
|
226
308
|
|
|
309
|
+
/**
|
|
310
|
+
* Map an absolute timeline time (ms) onto the source media time (ms).
|
|
311
|
+
*
|
|
312
|
+
* Forward: `fromTime + relMs * rate`
|
|
313
|
+
* Reversed: `fromTime + (span - relMs * rate)` — the same source window
|
|
314
|
+
* `[fromTime, fromTime + span]` read from its end back to its start.
|
|
315
|
+
*/
|
|
316
|
+
export declare function mapSourceTimeMs(segment: SourceTimedSegment, timelineMs: number): number;
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Shared source-time mapping helpers.
|
|
320
|
+
*
|
|
321
|
+
* A media segment occupies a timeline window `[startTime, endTime]` and reads a
|
|
322
|
+
* source window `[fromTime, fromTime + sourceSpanMs]`. Every consumer (preview
|
|
323
|
+
* evaluator, transition planner, audio manager, compose pipeline) must agree on
|
|
324
|
+
* this mapping, otherwise preview and export drift apart.
|
|
325
|
+
*/
|
|
326
|
+
/**
|
|
327
|
+
* Clamp a play rate into the supported range.
|
|
328
|
+
* Non-finite or missing values fall back to 1.
|
|
329
|
+
*/
|
|
330
|
+
export declare function normalizePlayRate(playRate?: number): number;
|
|
331
|
+
|
|
227
332
|
export declare type ProtocolExtra = ProtocolExtraRegistry extends Record<string, never> ? Record<string, never> : NonNullable<ProtocolExtraRegistry>;
|
|
228
333
|
|
|
229
334
|
export declare interface ProtocolExtraRegistry {
|
|
230
335
|
}
|
|
231
336
|
|
|
337
|
+
export declare function sampleKeyframes(track: IKeyframeTrack, relMs: number): number;
|
|
338
|
+
|
|
232
339
|
export declare type SegmentExtra<T extends ITrackType> = T extends keyof SegmentExtraRegistry ? NonNullable<SegmentExtraRegistry[T]> : Record<string, never>;
|
|
233
340
|
|
|
234
341
|
export declare interface SegmentExtraRegistry {
|
|
@@ -236,14 +343,36 @@ export declare interface SegmentExtraRegistry {
|
|
|
236
343
|
|
|
237
344
|
export declare type SegmentUnion = TrackTypeMapSegment[ITrackType];
|
|
238
345
|
|
|
346
|
+
/**
|
|
347
|
+
* Length of the source window consumed by the segment, in ms.
|
|
348
|
+
* `(endTime - startTime) * playRate`.
|
|
349
|
+
*/
|
|
350
|
+
export declare function sourceSpanMs(segment: SourceTimedSegment): number;
|
|
351
|
+
|
|
352
|
+
/** Minimal shape needed to map a timeline time onto a source time. */
|
|
353
|
+
export declare interface SourceTimedSegment {
|
|
354
|
+
startTime: number;
|
|
355
|
+
endTime: number;
|
|
356
|
+
/** Source window start in ms. Defaults to 0. */
|
|
357
|
+
fromTime?: number;
|
|
358
|
+
/** Playback speed multiplier. Defaults to 1. */
|
|
359
|
+
playRate?: number;
|
|
360
|
+
/** Play the same source window backwards. Defaults to false. */
|
|
361
|
+
reversed?: boolean;
|
|
362
|
+
}
|
|
363
|
+
|
|
239
364
|
declare interface StickerSegment<T extends ITrackType> extends ISegment<T> {
|
|
240
365
|
segmentType: T;
|
|
241
366
|
format: 'img' | 'gif';
|
|
242
367
|
url: string;
|
|
368
|
+
/** Stable library identity; `url` remains the last-known usable location. */
|
|
369
|
+
assetId?: string;
|
|
243
370
|
fillMode?: IFillMode;
|
|
244
371
|
animation?: IAnimation;
|
|
245
372
|
transform?: ITransform;
|
|
246
373
|
palette?: IPalette;
|
|
374
|
+
mask?: IMask;
|
|
375
|
+
chromaKey?: IChromaKey;
|
|
247
376
|
}
|
|
248
377
|
|
|
249
378
|
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.2",
|
|
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
|
}
|