@bylqwjc/media-editor-server 1.0.22 → 1.0.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,13 +1,5 @@
1
1
  import * as zod from 'zod';
2
- import { V as VideoEditStateT, O as OverlayT } from './state-B85vkf7_.js';
3
-
4
- type TransitionT = {
5
- type: 'none' | 'fade' | 'slide' | 'wipe' | 'flip' | 'clockWipe' | 'star' | 'circle' | 'rectangle';
6
- duration: number;
7
- };
8
- type VideoEditStateWithTransitions = VideoEditStateT & {
9
- transitions?: TransitionT[];
10
- };
2
+ import { V as VideoEditStateT, O as OverlayT } from './state-D7Of7b_y.js';
11
3
 
12
4
  /** 视频源元数据(File/objectURL 是运行时的事,不进引擎;引擎只认 srcIdx + 元数据) */
13
5
  interface VideoSourceMeta {
@@ -24,10 +16,11 @@ interface MutOpts {
24
16
  transient?: boolean;
25
17
  }
26
18
  type FilterKey = 'brightness' | 'contrast' | 'saturation' | 'temperature' | 'tint' | 'vibrance' | 'gamma' | 'highlights' | 'shadows' | 'whites' | 'blacks' | 'lightSense' | 'sharpen' | 'clarity' | 'grain' | 'fade' | 'vignette';
27
- type EngineListener = (state: VideoEditStateWithTransitions) => void;
19
+ type VideoEditStateWithTransitions = VideoEditStateT;
20
+ type EngineListener = (state: VideoEditStateT) => void;
28
21
  /** 导出计划:压缩后的状态 + 上传槽位映射(slot i 对应原 srcIdx = order[i]) */
29
22
  interface ExportPlan {
30
- state: VideoEditStateWithTransitions;
23
+ state: VideoEditStateT;
31
24
  videoSrcOrder: number[];
32
25
  audioSrcOrder: number[];
33
26
  }
@@ -38,11 +31,11 @@ declare class VideoEditorEngine {
38
31
  private listeners;
39
32
  /** 瞬时拖拽序列的起始 base(拖拽前的提交态);null = 不在拖拽中 */
40
33
  private transientBase;
41
- constructor(initial?: VideoEditStateWithTransitions);
34
+ constructor(initial?: VideoEditStateT);
42
35
  /** 当前编辑状态(引用稳定:仅在变更时换新对象,适配 useSyncExternalStore) */
43
- getState(): VideoEditStateWithTransitions;
36
+ getState(): VideoEditStateT;
44
37
  /** useSyncExternalStore 用别名 */
45
- getSnapshot: () => VideoEditStateWithTransitions;
38
+ getSnapshot: () => VideoEditStateT;
46
39
  subscribe: (fn: EngineListener) => (() => void);
47
40
  private emit;
48
41
  canUndo(): boolean;
@@ -61,7 +54,7 @@ declare class VideoEditorEngine {
61
54
  * 后续源:追加整段 clip(pushHistory)。
62
55
  */
63
56
  registerVideoSource(meta: VideoSourceMeta): number;
64
- /** 登记一个音频源并入音轨(整段、volume=1、startAt=0,clamp 后 push) */
57
+ /** 登记一个音频源并入单音轨(整段、volume=1、追加到当前音频末尾,clamp 后 push) */
65
58
  registerAudioSource(meta: AudioSourceMeta): number;
66
59
  getVideoSource(idx: number): VideoSourceMeta | undefined;
67
60
  getAudioSource(idx: number): AudioSourceMeta | undefined;
@@ -79,9 +72,9 @@ declare class VideoEditorEngine {
79
72
  removeAudioClip(idx: number): void;
80
73
  /** 改一条音频片段并 clamp(volume 改动不需 clamp 几何,clampGeom=false 跳过) */
81
74
  private patchAudio;
82
- setCrop(crop: NonNullable<VideoEditStateWithTransitions['crop']>, opts?: MutOpts): void;
75
+ setCrop(crop: NonNullable<VideoEditStateT['crop']>, opts?: MutOpts): void;
83
76
  clearCrop(): void;
84
- setScale(scale: NonNullable<VideoEditStateWithTransitions['scale']>): void;
77
+ setScale(scale: NonNullable<VideoEditStateT['scale']>): void;
85
78
  clearScale(): void;
86
79
  setRotation(deg: number, opts?: MutOpts): void;
87
80
  /** 90° 步进(顺时针正);结果钳到 [-180,180] */
@@ -89,7 +82,7 @@ declare class VideoEditorEngine {
89
82
  flipX(): void;
90
83
  flipY(): void;
91
84
  setFilter(key: FilterKey, value: number, opts?: MutOpts): void;
92
- setFilters(partial: Partial<VideoEditStateWithTransitions['filters']>, opts?: MutOpts): void;
85
+ setFilters(partial: Partial<VideoEditStateT['filters']>, opts?: MutOpts): void;
93
86
  setFilterPreset(id: string | undefined): void;
94
87
  addOverlay(o: OverlayT): void;
95
88
  updateOverlay(idx: number, patch: Partial<OverlayT>, opts?: MutOpts): void;
@@ -99,12 +92,12 @@ declare class VideoEditorEngine {
99
92
  * - `{transient:true}`:拖拽中间帧,基于拖拽前 base 合并、replacePresent,不入栈(= 原 patchLive)。
100
93
  * - 默认:一次性提交(= commit(partial))。
101
94
  */
102
- patch(partial: Partial<VideoEditStateWithTransitions>, opts?: MutOpts): void;
95
+ patch(partial: Partial<VideoEditStateT>, opts?: MutOpts): void;
103
96
  /**
104
97
  * 定格当前态为一步 undo(= 原 commit):保留 present(含拖拽末值),可再合并 partial;
105
98
  * 若处于瞬时序列,先把 past 接到拖拽前 base 上,使整段拖拽只占一步。
106
99
  */
107
- commit(partial?: Partial<VideoEditStateWithTransitions>): void;
100
+ commit(partial?: Partial<VideoEditStateT>): void;
108
101
  setKeepAudio(keep: boolean): void;
109
102
  setPoster(time: number): void;
110
103
  totalDuration(): number;
@@ -126,18 +119,27 @@ declare class VideoEditorEngine {
126
119
  srcIdx: number;
127
120
  in: number;
128
121
  out: number;
122
+ hidden?: boolean | undefined;
123
+ locked?: boolean | undefined;
129
124
  }[];
130
125
  canvas: {
131
126
  w: number;
132
127
  h: number;
133
128
  };
134
129
  rotation?: number | undefined;
130
+ filterPreset?: string | undefined;
135
131
  audioClips?: {
132
+ startAt: number;
136
133
  srcIdx: number;
137
134
  in: number;
138
135
  out: number;
139
- startAt: number;
140
136
  volume: number;
137
+ locked?: boolean | undefined;
138
+ track?: number | undefined;
139
+ speed?: number | undefined;
140
+ muted?: boolean | undefined;
141
+ fadeIn?: number | undefined;
142
+ fadeOut?: number | undefined;
141
143
  }[] | undefined;
142
144
  crop?: {
143
145
  width: number;
@@ -149,13 +151,14 @@ declare class VideoEditorEngine {
149
151
  width: number;
150
152
  height: number;
151
153
  fit: "contain" | "cover" | "force";
154
+ backgroundColor?: string | undefined;
152
155
  } | undefined;
153
156
  flipX?: boolean | undefined;
154
157
  flipY?: boolean | undefined;
155
158
  filters?: {
156
- brightness: number;
157
- contrast: number;
158
- saturation: number;
159
+ brightness?: number | undefined;
160
+ contrast?: number | undefined;
161
+ saturation?: number | undefined;
159
162
  temperature?: number | undefined;
160
163
  tint?: number | undefined;
161
164
  vibrance?: number | undefined;
@@ -171,13 +174,17 @@ declare class VideoEditorEngine {
171
174
  fade?: number | undefined;
172
175
  vignette?: number | undefined;
173
176
  } | undefined;
174
- filterPreset?: string | undefined;
175
177
  overlays?: ({
176
178
  type: "pen";
177
179
  points: number[];
178
180
  color: string;
179
181
  width: number;
180
182
  rotation?: number | undefined;
183
+ startAt?: number | undefined;
184
+ endAt?: number | undefined;
185
+ timelineTrack?: number | undefined;
186
+ hidden?: boolean | undefined;
187
+ locked?: boolean | undefined;
181
188
  } | {
182
189
  type: "line";
183
190
  color: string;
@@ -187,6 +194,11 @@ declare class VideoEditorEngine {
187
194
  x2: number;
188
195
  y2: number;
189
196
  rotation?: number | undefined;
197
+ startAt?: number | undefined;
198
+ endAt?: number | undefined;
199
+ timelineTrack?: number | undefined;
200
+ hidden?: boolean | undefined;
201
+ locked?: boolean | undefined;
190
202
  } | {
191
203
  type: "arrow";
192
204
  color: string;
@@ -196,6 +208,11 @@ declare class VideoEditorEngine {
196
208
  x2: number;
197
209
  y2: number;
198
210
  rotation?: number | undefined;
211
+ startAt?: number | undefined;
212
+ endAt?: number | undefined;
213
+ timelineTrack?: number | undefined;
214
+ hidden?: boolean | undefined;
215
+ locked?: boolean | undefined;
199
216
  } | {
200
217
  type: "rect";
201
218
  color: string;
@@ -205,6 +222,11 @@ declare class VideoEditorEngine {
205
222
  w: number;
206
223
  h: number;
207
224
  rotation?: number | undefined;
225
+ startAt?: number | undefined;
226
+ endAt?: number | undefined;
227
+ timelineTrack?: number | undefined;
228
+ hidden?: boolean | undefined;
229
+ locked?: boolean | undefined;
208
230
  } | {
209
231
  type: "ellipse";
210
232
  color: string;
@@ -214,6 +236,11 @@ declare class VideoEditorEngine {
214
236
  w: number;
215
237
  h: number;
216
238
  rotation?: number | undefined;
239
+ startAt?: number | undefined;
240
+ endAt?: number | undefined;
241
+ timelineTrack?: number | undefined;
242
+ hidden?: boolean | undefined;
243
+ locked?: boolean | undefined;
217
244
  } | {
218
245
  type: "text";
219
246
  color: string;
@@ -222,6 +249,25 @@ declare class VideoEditorEngine {
222
249
  text: string;
223
250
  fontSize: number;
224
251
  rotation?: number | undefined;
252
+ startAt?: number | undefined;
253
+ endAt?: number | undefined;
254
+ timelineTrack?: number | undefined;
255
+ hidden?: boolean | undefined;
256
+ locked?: boolean | undefined;
257
+ width?: number | undefined;
258
+ fontFamily?: string | undefined;
259
+ fontWeight?: string | undefined;
260
+ italic?: boolean | undefined;
261
+ underline?: boolean | undefined;
262
+ strikethrough?: boolean | undefined;
263
+ align?: "left" | "center" | "right" | undefined;
264
+ backgroundColor?: string | undefined;
265
+ strokeColor?: string | undefined;
266
+ borderWidth?: number | undefined;
267
+ paddingX?: number | undefined;
268
+ paddingY?: number | undefined;
269
+ lineHeight?: number | undefined;
270
+ opacity?: number | undefined;
225
271
  } | {
226
272
  type: "sticker";
227
273
  x: number;
@@ -229,12 +275,65 @@ declare class VideoEditorEngine {
229
275
  w: number;
230
276
  h: number;
231
277
  rotation?: number | undefined;
278
+ startAt?: number | undefined;
279
+ endAt?: number | undefined;
280
+ timelineTrack?: number | undefined;
281
+ hidden?: boolean | undefined;
282
+ locked?: boolean | undefined;
232
283
  emoji?: string | undefined;
233
284
  src?: string | undefined;
285
+ } | {
286
+ type: "adjust";
287
+ x: number;
288
+ y: number;
289
+ w: number;
290
+ h: number;
291
+ rotation?: number | undefined;
292
+ startAt?: number | undefined;
293
+ endAt?: number | undefined;
294
+ timelineTrack?: number | undefined;
295
+ hidden?: boolean | undefined;
296
+ locked?: boolean | undefined;
297
+ layerKind?: "filter" | "adjust" | undefined;
298
+ filterPreset?: string | undefined;
299
+ brightness?: number | undefined;
300
+ contrast?: number | undefined;
301
+ saturation?: number | undefined;
302
+ temperature?: number | undefined;
303
+ tint?: number | undefined;
304
+ vibrance?: number | undefined;
305
+ gamma?: number | undefined;
306
+ highlights?: number | undefined;
307
+ shadows?: number | undefined;
308
+ whites?: number | undefined;
309
+ blacks?: number | undefined;
310
+ lightSense?: number | undefined;
311
+ sharpen?: number | undefined;
312
+ clarity?: number | undefined;
313
+ grain?: number | undefined;
314
+ fade?: number | undefined;
315
+ vignette?: number | undefined;
234
316
  })[] | undefined;
317
+ transitions?: {
318
+ type?: "fade" | "none" | "slide" | "wipe" | "flip" | "clockWipe" | "star" | "circle" | "rectangle" | undefined;
319
+ duration?: number | undefined;
320
+ }[] | undefined;
235
321
  keepAudio?: boolean | undefined;
236
322
  poster?: {
237
323
  time: number;
324
+ src?: string | undefined;
325
+ useAsVideoCover?: boolean | undefined;
326
+ preview?: string | undefined;
327
+ } | undefined;
328
+ exportSettings?: {
329
+ width?: number | undefined;
330
+ fileName?: string | undefined;
331
+ format?: "mp4" | "mov" | "mxf" | undefined;
332
+ height?: number | undefined;
333
+ frameRate?: number | undefined;
334
+ videoBitrateKbps?: number | undefined;
335
+ audioBitrateKbps?: number | undefined;
336
+ audioCodec?: "aac" | "mp3" | undefined;
238
337
  } | undefined;
239
338
  }, {
240
339
  rotation: number;
@@ -242,13 +341,21 @@ declare class VideoEditorEngine {
242
341
  srcIdx: number;
243
342
  in: number;
244
343
  out: number;
344
+ hidden?: boolean | undefined;
345
+ locked?: boolean | undefined;
245
346
  }[];
246
347
  audioClips: {
348
+ startAt: number;
247
349
  srcIdx: number;
248
350
  in: number;
249
351
  out: number;
250
- startAt: number;
352
+ track: number;
353
+ speed: number;
251
354
  volume: number;
355
+ fadeIn: number;
356
+ fadeOut: number;
357
+ locked?: boolean | undefined;
358
+ muted?: boolean | undefined;
252
359
  }[];
253
360
  canvas: {
254
361
  w: number;
@@ -275,7 +382,12 @@ declare class VideoEditorEngine {
275
382
  fade: number;
276
383
  vignette: number;
277
384
  };
385
+ transitions: {
386
+ type: "fade" | "none" | "slide" | "wipe" | "flip" | "clockWipe" | "star" | "circle" | "rectangle";
387
+ duration: number;
388
+ }[];
278
389
  keepAudio: boolean;
390
+ filterPreset?: string | undefined;
279
391
  crop?: {
280
392
  width: number;
281
393
  x: number;
@@ -286,14 +398,19 @@ declare class VideoEditorEngine {
286
398
  width: number;
287
399
  height: number;
288
400
  fit: "contain" | "cover" | "force";
401
+ backgroundColor?: string | undefined;
289
402
  } | undefined;
290
- filterPreset?: string | undefined;
291
403
  overlays?: ({
292
404
  type: "pen";
293
405
  points: number[];
294
406
  color: string;
295
407
  width: number;
296
408
  rotation?: number | undefined;
409
+ startAt?: number | undefined;
410
+ endAt?: number | undefined;
411
+ timelineTrack?: number | undefined;
412
+ hidden?: boolean | undefined;
413
+ locked?: boolean | undefined;
297
414
  } | {
298
415
  type: "line";
299
416
  color: string;
@@ -303,6 +420,11 @@ declare class VideoEditorEngine {
303
420
  x2: number;
304
421
  y2: number;
305
422
  rotation?: number | undefined;
423
+ startAt?: number | undefined;
424
+ endAt?: number | undefined;
425
+ timelineTrack?: number | undefined;
426
+ hidden?: boolean | undefined;
427
+ locked?: boolean | undefined;
306
428
  } | {
307
429
  type: "arrow";
308
430
  color: string;
@@ -312,6 +434,11 @@ declare class VideoEditorEngine {
312
434
  x2: number;
313
435
  y2: number;
314
436
  rotation?: number | undefined;
437
+ startAt?: number | undefined;
438
+ endAt?: number | undefined;
439
+ timelineTrack?: number | undefined;
440
+ hidden?: boolean | undefined;
441
+ locked?: boolean | undefined;
315
442
  } | {
316
443
  type: "rect";
317
444
  color: string;
@@ -321,6 +448,11 @@ declare class VideoEditorEngine {
321
448
  w: number;
322
449
  h: number;
323
450
  rotation?: number | undefined;
451
+ startAt?: number | undefined;
452
+ endAt?: number | undefined;
453
+ timelineTrack?: number | undefined;
454
+ hidden?: boolean | undefined;
455
+ locked?: boolean | undefined;
324
456
  } | {
325
457
  type: "ellipse";
326
458
  color: string;
@@ -330,6 +462,11 @@ declare class VideoEditorEngine {
330
462
  w: number;
331
463
  h: number;
332
464
  rotation?: number | undefined;
465
+ startAt?: number | undefined;
466
+ endAt?: number | undefined;
467
+ timelineTrack?: number | undefined;
468
+ hidden?: boolean | undefined;
469
+ locked?: boolean | undefined;
333
470
  } | {
334
471
  type: "text";
335
472
  color: string;
@@ -338,6 +475,25 @@ declare class VideoEditorEngine {
338
475
  text: string;
339
476
  fontSize: number;
340
477
  rotation?: number | undefined;
478
+ startAt?: number | undefined;
479
+ endAt?: number | undefined;
480
+ timelineTrack?: number | undefined;
481
+ hidden?: boolean | undefined;
482
+ locked?: boolean | undefined;
483
+ width?: number | undefined;
484
+ fontFamily?: string | undefined;
485
+ fontWeight?: string | undefined;
486
+ italic?: boolean | undefined;
487
+ underline?: boolean | undefined;
488
+ strikethrough?: boolean | undefined;
489
+ align?: "left" | "center" | "right" | undefined;
490
+ backgroundColor?: string | undefined;
491
+ strokeColor?: string | undefined;
492
+ borderWidth?: number | undefined;
493
+ paddingX?: number | undefined;
494
+ paddingY?: number | undefined;
495
+ lineHeight?: number | undefined;
496
+ opacity?: number | undefined;
341
497
  } | {
342
498
  type: "sticker";
343
499
  x: number;
@@ -345,15 +501,64 @@ declare class VideoEditorEngine {
345
501
  w: number;
346
502
  h: number;
347
503
  rotation?: number | undefined;
504
+ startAt?: number | undefined;
505
+ endAt?: number | undefined;
506
+ timelineTrack?: number | undefined;
507
+ hidden?: boolean | undefined;
508
+ locked?: boolean | undefined;
348
509
  emoji?: string | undefined;
349
510
  src?: string | undefined;
511
+ } | {
512
+ type: "adjust";
513
+ x: number;
514
+ y: number;
515
+ w: number;
516
+ h: number;
517
+ brightness: number;
518
+ contrast: number;
519
+ saturation: number;
520
+ temperature: number;
521
+ tint: number;
522
+ vibrance: number;
523
+ gamma: number;
524
+ highlights: number;
525
+ shadows: number;
526
+ whites: number;
527
+ blacks: number;
528
+ lightSense: number;
529
+ sharpen: number;
530
+ clarity: number;
531
+ grain: number;
532
+ fade: number;
533
+ vignette: number;
534
+ rotation?: number | undefined;
535
+ startAt?: number | undefined;
536
+ endAt?: number | undefined;
537
+ timelineTrack?: number | undefined;
538
+ hidden?: boolean | undefined;
539
+ locked?: boolean | undefined;
540
+ layerKind?: "filter" | "adjust" | undefined;
541
+ filterPreset?: string | undefined;
350
542
  })[] | undefined;
351
543
  poster?: {
352
544
  time: number;
545
+ src?: string | undefined;
546
+ useAsVideoCover?: boolean | undefined;
547
+ preview?: string | undefined;
548
+ } | undefined;
549
+ exportSettings?: {
550
+ format: "mp4" | "mov" | "mxf";
551
+ frameRate: number;
552
+ audioCodec: "aac" | "mp3";
553
+ width?: number | undefined;
554
+ fileName?: string | undefined;
555
+ height?: number | undefined;
556
+ videoBitrateKbps?: number | undefined;
557
+ audioBitrateKbps?: number | undefined;
353
558
  } | undefined;
354
559
  }>;
355
560
  /** 重置为给定状态(清空 history、源登记保留) */
356
- reset(state?: VideoEditStateWithTransitions): void;
561
+ reset(state?: VideoEditStateT): void;
357
562
  }
358
563
 
359
- export { type AudioSourceMeta, type EngineListener, type ExportPlan, type FilterKey, type MutOpts, TransitionT, VideoEditStateWithTransitions, VideoEditorEngine, type VideoSourceMeta };
564
+ export { type AudioSourceMeta, type EngineListener, type ExportPlan, type FilterKey, type MutOpts, type VideoEditStateWithTransitions, VideoEditorEngine, type VideoSourceMeta };
@@ -1 +1 @@
1
- import{createHistory as t,defaultVideoEditState as s,canUndo as i,canRedo as e,undo as r,redo as a,replacePresent as o,pushHistory as n,clampAudioClip as p,totalDuration as h,splitAtOutput as l,removeClip as u,duplicateClip as c,reorderClips as d,trimClipEdge as y,contentDuration as m,locateOutput as M,usedVideoSrcIndices as S,remapSrcIndices as v,VideoEditState as C}from"./chunk-MGKYVYOH.js";function f(t){const s=Math.min(Math.max(Math.round(t),2),4096);return s%2==0?s:s-1}var A=t=>Math.min(Math.max(t,-180),180),B=class{constructor(i=s()){this.videoSources=[],this.audioSources=[],this.listeners=new Set,this.transientBase=null,this.getSnapshot=()=>this.history.present,this.subscribe=t=>(this.listeners.add(t),()=>this.listeners.delete(t)),this.history=t(i)}getState(){return this.history.present}emit(){const t=this.history.present;for(const s of this.listeners)s(t)}canUndo(){return i(this.history)}canRedo(){return e(this.history)}undo(){this.transientBase=null,this.history=r(this.history),this.emit()}redo(){this.transientBase=null,this.history=a(this.history),this.emit()}applyMut(t,s=!1){if(s)null===this.transientBase&&(this.transientBase=this.history.present),this.history=o(this.history,t(this.transientBase));else{const s=t(this.transientBase??this.history.present),i=this.transientBase?{...this.history,present:this.transientBase}:this.history;this.history=n(i,s),this.transientBase=null}this.emit()}registerVideoSource(i){const e=this.videoSources.length;this.videoSources.push(i);const r={srcIdx:e,in:0,out:i.duration};return 0===e||0===this.history.present.clips.length?(this.transientBase=null,this.history=t({...s(),clips:[r],canvas:{w:f(i.width),h:f(i.height)},poster:{time:Math.min(1,i.duration/2)}}),this.emit()):this.applyMut(t=>({...t,clips:[...t.clips,r]})),e}registerAudioSource(t){const s=this.audioSources.length;return this.audioSources.push(t),this.applyMut(i=>{const e=new Set((i.audioClips??[]).map((t,s)=>Number.isInteger(t?.track)&&t.track>=0?t.track:s));let r=0;for(;e.has(r);)r+=1;const a=p({srcIdx:s,track:r,startAt:0,in:0,out:t.duration,volume:1},t.duration,h(i.clips));return{...i,audioClips:[...i.audioClips,a]}}),s}getVideoSource(t){return this.videoSources[t]}getAudioSource(t){return this.audioSources[t]}addClipFromSource(t){const s=this.videoSources[t];s&&this.applyMut(i=>({...i,clips:[...i.clips,{srcIdx:t,in:0,out:s.duration}]}))}splitAtPlayhead(t){this.applyMut(s=>({...s,clips:l(s.clips,t)}))}removeClip(t){this.applyMut(s=>({...s,clips:u(s.clips,t)}))}duplicateClip(t){this.applyMut(s=>({...s,clips:c(s.clips,t)}))}reorderClips(t,s){this.applyMut(i=>({...i,clips:d(i.clips,t,s)}))}trimClip(t,s,i,e){this.applyMut(e=>{const r=e.clips[t];if(!r)return e;const a=this.videoSources[r.srcIdx]?.duration??r.out;return{...e,clips:y(e.clips,t,s,i,a)}},e?.transient)}moveAudioClip(t,s,i){this.applyMut(i=>this.patchAudio(i,t,t=>({...t,startAt:s})),i?.transient)}trimAudioClip(t,s,i,e){this.applyMut(e=>this.patchAudio(e,t,t=>{if("in"===s){const s=i-t.in;return{...t,in:i,startAt:t.startAt+s}}return{...t,out:i}}),e?.transient)}setAudioVolume(t,s,i){this.applyMut(i=>this.patchAudio(i,t,t=>({...t,volume:s}),!1),i?.transient)}removeAudioClip(t){this.applyMut(s=>({...s,audioClips:s.audioClips.filter((s,i)=>i!==t)}))}patchAudio(t,s,i,e=!0){const r=t.audioClips[s];if(!r)return t;let a=i(r);if(e){const s=this.audioSources[r.srcIdx]?.duration??r.out;a=p(a,s,h(t.clips))}return{...t,audioClips:t.audioClips.map((t,i)=>i===s?a:t)}}setCrop(t,s){this.applyMut(s=>({...s,crop:t}),s?.transient)}clearCrop(){this.applyMut(t=>({...t,crop:void 0}))}setScale(t){this.applyMut(s=>({...s,scale:t}))}clearScale(){this.applyMut(t=>({...t,scale:void 0}))}setRotation(t,s){this.applyMut(s=>({...s,rotation:A(t)}),s?.transient)}rotateBy(t){this.applyMut(s=>{let i=s.rotation+t;return i>180&&(i-=360),i<-180&&(i+=360),{...s,rotation:A(i)}})}flipX(){this.applyMut(t=>({...t,flipX:!t.flipX}))}flipY(){this.applyMut(t=>({...t,flipY:!t.flipY}))}setFilter(t,s,i){this.applyMut(i=>({...i,filters:{...i.filters,[t]:s}}),i?.transient)}setFilters(t,s){this.applyMut(s=>({...s,filters:{...s.filters,...t}}),s?.transient)}setFilterPreset(t){this.applyMut(s=>({...s,filterPreset:t}))}addOverlay(t){this.applyMut(s=>({...s,overlays:[...s.overlays??[],t]}))}updateOverlay(t,s,i){this.applyMut(i=>{const e=i.overlays??[];return e[t]?{...i,overlays:e.map((i,e)=>e===t?{...i,...s}:i)}:i},i?.transient)}removeOverlay(t){this.applyMut(s=>({...s,overlays:(s.overlays??[]).filter((s,i)=>i!==t)}))}patch(t,s){s?.transient?(null===this.transientBase&&(this.transientBase=this.history.present),this.history=o(this.history,{...this.transientBase,...t}),this.emit()):this.commit(t)}commit(t){const s=t?{...this.history.present,...t}:this.history.present,i=this.transientBase;this.transientBase=null,this.history=n(i?{...this.history,present:i}:this.history,s),this.emit()}setKeepAudio(t){this.applyMut(s=>({...s,keepAudio:t}))}setPoster(t){this.applyMut(s=>({...s,poster:{time:Math.max(0,t)}}))}totalDuration(){return h(this.history.present.clips)}contentDuration(){const t=this.history.present;return m(t.clips,t.audioClips,t.overlays)}locate(t){return M(this.history.present.clips,t)}usedVideoSources(){return S(this.history.present.clips)}getExportPlan(){const t=this.history.present,s=S(t.clips),i=[...new Set(t.audioClips.map(t=>t.srcIdx))].sort((t,s)=>t-s),e=new Map(i.map((t,s)=>[t,s]));return{state:{...t,clips:v(t.clips,s),audioClips:t.audioClips.map(t=>({...t,srcIdx:e.get(t.srcIdx)??0}))},videoSrcOrder:s,audioSrcOrder:i}}validate(){return C.safeParse(this.getExportPlan().state)}reset(i=s()){this.transientBase=null,this.history=t(i),this.emit()}};export{B as VideoEditorEngine};
1
+ import{createHistory as t,canUndo as s,canRedo as i,undo as e,redo as r,replacePresent as a,pushHistory as o,clampAudioClip as n,totalDuration as h,MIN_CLIP as p,splitAtOutput as l,removeClip as u,duplicateClip as c,reorderClips as d,trimClipEdge as y,contentDuration as m,locateOutput as M,usedVideoSrcIndices as f,remapSrcIndices as v}from"./chunk-7D4QE3R2.js";import{defaultVideoEditState as S,VideoEditState as C}from"./chunk-T5QIAKTR.js";function A(t){const s=Math.min(Math.max(Math.round(t),2),4096);return s%2==0?s:s-1}var x=t=>Math.min(Math.max(t,-180),180),B=class{constructor(s=S()){this.videoSources=[],this.audioSources=[],this.listeners=new Set,this.transientBase=null,this.getSnapshot=()=>this.history.present,this.subscribe=t=>(this.listeners.add(t),()=>this.listeners.delete(t)),this.history=t(s)}getState(){return this.history.present}emit(){const t=this.history.present;for(const s of this.listeners)s(t)}canUndo(){return s(this.history)}canRedo(){return i(this.history)}undo(){this.transientBase=null,this.history=e(this.history),this.emit()}redo(){this.transientBase=null,this.history=r(this.history),this.emit()}applyMut(t,s=!1){if(s)null===this.transientBase&&(this.transientBase=this.history.present),this.history=a(this.history,t(this.transientBase));else{const s=t(this.transientBase??this.history.present),i=this.transientBase?{...this.history,present:this.transientBase}:this.history;this.history=o(i,s),this.transientBase=null}this.emit()}registerVideoSource(s){const i=this.videoSources.length;this.videoSources.push(s);const e={srcIdx:i,in:0,out:s.duration};return 0===i||0===this.history.present.clips.length?(this.transientBase=null,this.history=t({...S(),clips:[e],canvas:{w:A(s.width),h:A(s.height)}}),this.emit()):this.applyMut(t=>({...t,clips:[...t.clips,e]})),i}registerAudioSource(t){const s=this.audioSources.length;return this.audioSources.push(t),this.applyMut(i=>{const e=i.audioClips.reduce((t,s)=>{const i=Math.max(0,(s.out-s.in)/Math.max(.01,s.speed??1));return Math.max(t,s.startAt+i)},0),r=n({srcIdx:s,track:0,startAt:e,in:0,out:t.duration,speed:1,volume:1,fadeIn:0,fadeOut:0},t.duration,Math.max(h(i.clips),e+p));return{...i,audioClips:[...i.audioClips.map(t=>({...t,track:0})),r]}}),s}getVideoSource(t){return this.videoSources[t]}getAudioSource(t){return this.audioSources[t]}addClipFromSource(t){const s=this.videoSources[t];s&&this.applyMut(i=>({...i,clips:[...i.clips,{srcIdx:t,in:0,out:s.duration}]}))}splitAtPlayhead(t){this.applyMut(s=>({...s,clips:l(s.clips,t)}))}removeClip(t){this.applyMut(s=>({...s,clips:u(s.clips,t)}))}duplicateClip(t){this.applyMut(s=>({...s,clips:c(s.clips,t)}))}reorderClips(t,s){this.applyMut(i=>({...i,clips:d(i.clips,t,s)}))}trimClip(t,s,i,e){this.applyMut(e=>{const r=e.clips[t];if(!r)return e;const a=this.videoSources[r.srcIdx]?.duration??r.out;return{...e,clips:y(e.clips,t,s,i,a)}},e?.transient)}moveAudioClip(t,s,i){this.applyMut(i=>this.patchAudio(i,t,t=>({...t,startAt:s})),i?.transient)}trimAudioClip(t,s,i,e){this.applyMut(e=>this.patchAudio(e,t,t=>{if("in"===s){const s=i-t.in;return{...t,in:i,startAt:t.startAt+s}}return{...t,out:i}}),e?.transient)}setAudioVolume(t,s,i){this.applyMut(i=>this.patchAudio(i,t,t=>({...t,volume:s}),!1),i?.transient)}removeAudioClip(t){this.applyMut(s=>({...s,audioClips:s.audioClips.filter((s,i)=>i!==t)}))}patchAudio(t,s,i,e=!0){const r=t.audioClips[s];if(!r)return t;let a=i(r);if(e){const s=this.audioSources[r.srcIdx]?.duration??r.out;a=n(a,s,h(t.clips))}return{...t,audioClips:t.audioClips.map((t,i)=>i===s?a:t)}}setCrop(t,s){this.applyMut(s=>({...s,crop:t}),s?.transient)}clearCrop(){this.applyMut(t=>({...t,crop:void 0}))}setScale(t){this.applyMut(s=>({...s,scale:t}))}clearScale(){this.applyMut(t=>({...t,scale:void 0}))}setRotation(t,s){this.applyMut(s=>({...s,rotation:x(t)}),s?.transient)}rotateBy(t){this.applyMut(s=>{let i=s.rotation+t;return i>180&&(i-=360),i<-180&&(i+=360),{...s,rotation:x(i)}})}flipX(){this.applyMut(t=>({...t,flipX:!t.flipX}))}flipY(){this.applyMut(t=>({...t,flipY:!t.flipY}))}setFilter(t,s,i){this.applyMut(i=>({...i,filters:{...i.filters,[t]:s}}),i?.transient)}setFilters(t,s){this.applyMut(s=>({...s,filters:{...s.filters,...t}}),s?.transient)}setFilterPreset(t){this.applyMut(s=>({...s,filterPreset:t}))}addOverlay(t){this.applyMut(s=>({...s,overlays:[...s.overlays??[],t]}))}updateOverlay(t,s,i){this.applyMut(i=>{const e=i.overlays??[];return e[t]?{...i,overlays:e.map((i,e)=>e===t?{...i,...s}:i)}:i},i?.transient)}removeOverlay(t){this.applyMut(s=>({...s,overlays:(s.overlays??[]).filter((s,i)=>i!==t)}))}patch(t,s){s?.transient?(null===this.transientBase&&(this.transientBase=this.history.present),this.history=a(this.history,{...this.transientBase,...t}),this.emit()):this.commit(t)}commit(t){const s=t?{...this.history.present,...t}:this.history.present,i=this.transientBase;this.transientBase=null,this.history=o(i?{...this.history,present:i}:this.history,s),this.emit()}setKeepAudio(t){this.applyMut(s=>({...s,keepAudio:t}))}setPoster(t){this.applyMut(s=>({...s,poster:{time:Math.max(0,t)}}))}totalDuration(){return h(this.history.present.clips)}contentDuration(){const t=this.history.present;return m(t.clips,t.audioClips)}locate(t){return M(this.history.present.clips,t)}usedVideoSources(){return f(this.history.present.clips)}getExportPlan(){const t=this.history.present,s=f(t.clips),i=t.audioClips.filter(t=>!t.muted),e=[...new Set(i.map(t=>t.srcIdx))].sort((t,s)=>t-s),r=new Map(e.map((t,s)=>[t,s]));return{state:{...t,clips:v(t.clips,s),audioClips:i.map(t=>({...t,srcIdx:r.get(t.srcIdx)??0}))},videoSrcOrder:s,audioSrcOrder:e}}validate(){return C.safeParse(this.getExportPlan().state)}reset(s=S()){this.transientBase=null,this.history=t(s),this.emit()}};export{B as VideoEditorEngine};