vivid-editor-core 0.1.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.
@@ -0,0 +1,266 @@
1
+ /**
2
+ * AI Art Director — State Orchestrator
3
+ *
4
+ * Processes structured AI commands against the editor Zustand store.
5
+ * Each command maps to one or more store mutations (e.g. adding a visual clip
6
+ * always creates both a TimelineClip AND a CanvasObject).
7
+ */
8
+ import type { TextOverlay } from './types/editor.js';
9
+ import type { TimelineClip, CanvasObject, TrackDefinition, AssetClip } from './store.js';
10
+ import type { BeatAnalysis } from './types/beat.js';
11
+ import type { Animations, Animation as AnimationCurve, AnimatableProp } from './types/animation.js';
12
+ import type { Effect } from './types/effect.js';
13
+ import type { Mask as MaskV2 } from './types/mask.js';
14
+ import type { AudioReactiveModifier } from './types/audioReactive.js';
15
+ export interface AddTextCommand {
16
+ type: 'ADD_TEXT';
17
+ payload: TextOverlay;
18
+ }
19
+ export interface UpdateTextCommand {
20
+ type: 'UPDATE_TEXT';
21
+ payload: Partial<TextOverlay> & {
22
+ id: string;
23
+ };
24
+ }
25
+ export interface RemoveTextCommand {
26
+ type: 'REMOVE_TEXT';
27
+ payload: {
28
+ id: string;
29
+ };
30
+ }
31
+ export interface AddClipCommand {
32
+ type: 'ADD_CLIP';
33
+ /** The asset to place on the timeline (must already exist in assetLibrary) */
34
+ payload: {
35
+ assetId: string;
36
+ /** Timeline placement — startMs is auto-computed if omitted */
37
+ startMs?: number;
38
+ durationMs?: number;
39
+ trackId?: string;
40
+ /** Canvas transform — defaults to full-canvas cover */
41
+ canvasObject?: Partial<Omit<CanvasObject, 'id' | 'clipId'>>;
42
+ };
43
+ }
44
+ export interface UpdateClipCommand {
45
+ type: 'UPDATE_CLIP';
46
+ payload: Partial<Pick<TimelineClip, 'startMs' | 'durationMs' | 'sourceOffsetMs' | 'volume' | 'opacity' | 'playbackRate'>> & {
47
+ id: string;
48
+ };
49
+ }
50
+ export interface RemoveClipCommand {
51
+ type: 'REMOVE_CLIP';
52
+ payload: {
53
+ id: string;
54
+ };
55
+ }
56
+ export interface UpdateCanvasObjectCommand {
57
+ type: 'UPDATE_CANVAS_OBJECT';
58
+ payload: Partial<CanvasObject> & {
59
+ id: string;
60
+ };
61
+ }
62
+ export interface SetCanvasPresetCommand {
63
+ type: 'SET_CANVAS_PRESET';
64
+ payload: {
65
+ id: string;
66
+ label: string;
67
+ width: number;
68
+ height: number;
69
+ };
70
+ }
71
+ export interface AddTrackCommand {
72
+ type: 'ADD_TRACK';
73
+ payload: {
74
+ type: 'visual' | 'audio';
75
+ };
76
+ }
77
+ export interface SplitClipCommand {
78
+ type: 'SPLIT_CLIP';
79
+ payload: {
80
+ clipId: string;
81
+ splitAtMs: number;
82
+ };
83
+ }
84
+ export interface DuplicateClipCommand {
85
+ type: 'DUPLICATE_CLIP';
86
+ payload: {
87
+ id: string;
88
+ };
89
+ }
90
+ export interface SetTransitionCommand {
91
+ type: 'SET_TRANSITION';
92
+ payload: {
93
+ clipId: string;
94
+ edge: 'in' | 'out';
95
+ type: 'dissolve' | 'fade-black' | 'crossfade' | 'fade-in' | 'fade-out';
96
+ durationMs: number;
97
+ };
98
+ }
99
+ export interface SetClipAnimationCommand {
100
+ type: 'SET_CLIP_ANIMATION';
101
+ payload: {
102
+ clipId: string;
103
+ phase: 'in' | 'out';
104
+ type: 'none' | 'fade' | 'slide-up' | 'slide-down' | 'zoom-in' | 'zoom-out' | 'zoom-pan' | 'spin' | 'blur-reveal';
105
+ durationMs: number;
106
+ };
107
+ }
108
+ export interface SetCinematicLookCommand {
109
+ type: 'SET_CINEMATIC_LOOK';
110
+ payload: {
111
+ look: 'none' | 'kodak-portra' | 'noir' | 'cyberpunk' | 'kodak-portra-400' | 'fuji-provia' | 'ilford-hp5' | 'cinestill-800t' | 'bleach-bypass' | 'polaroid-vintage' | 'technicolor' | 'cross-process' | 'muted-cinematic' | 'cyberpunk-neon';
112
+ };
113
+ }
114
+ export interface DetachAudioCommand {
115
+ type: 'DETACH_AUDIO';
116
+ payload: {
117
+ clipId: string;
118
+ };
119
+ }
120
+ /**
121
+ * Beat-synced rhythmic editing of the visual track to a music clip.
122
+ *
123
+ * `audioClipId` — id of an audio clip already in timeline. Must have a
124
+ * cached BeatAnalysis (otherwise the orchestrator returns an error).
125
+ *
126
+ * `beatInterval` — how many beats between cuts. 4 = 1 cut per measure.
127
+ *
128
+ * `mode`:
129
+ * - "redistribute" (default): take all visual clips, slice them up so
130
+ * each segment lasts exactly `beatInterval` beats, and lay them down
131
+ * end-to-end starting at firstBeatMs. Ignores existing visual clip
132
+ * positions/durations. Best when clips are placeholders that need
133
+ * rhythmic timing.
134
+ * - "snap": leave clips where they are, just nudge their start/end
135
+ * edges to the nearest beat. Conservative.
136
+ *
137
+ * `syncClips`: which visual clips to include. "all" = every visual
138
+ * clip on V* tracks. Otherwise an explicit list of clip ids.
139
+ */
140
+ export interface CutToBeatCommand {
141
+ type: 'CUT_TO_BEAT';
142
+ payload: {
143
+ audioClipId: string;
144
+ beatInterval: number;
145
+ mode?: 'redistribute' | 'snap';
146
+ syncClips?: 'all' | string[];
147
+ };
148
+ }
149
+ /** Set keyframe animations on one property of a canvas object or text overlay. */
150
+ export interface SetObjectAnimationCommand {
151
+ type: 'SET_OBJECT_ANIMATION';
152
+ payload: {
153
+ objectId: string;
154
+ objectType: 'canvas' | 'text';
155
+ property: AnimatableProp;
156
+ animation: AnimationCurve;
157
+ };
158
+ }
159
+ /** Replace ALL animations on an object at once. */
160
+ export interface SetAnimationsCommand {
161
+ type: 'SET_ANIMATIONS';
162
+ payload: {
163
+ objectId: string;
164
+ objectType: 'canvas' | 'text';
165
+ animations: Animations;
166
+ };
167
+ }
168
+ /** Append (or replace by type) one effect on a canvas object / text overlay. */
169
+ export interface AddEffectCommand {
170
+ type: 'ADD_EFFECT';
171
+ payload: {
172
+ objectId: string;
173
+ objectType: 'canvas' | 'text';
174
+ effect: Effect;
175
+ /** When true, replace any existing effect of the same type. */
176
+ replace?: boolean;
177
+ };
178
+ }
179
+ /** Remove an effect by type from a canvas object / text overlay. */
180
+ export interface RemoveEffectCommand {
181
+ type: 'REMOVE_EFFECT';
182
+ payload: {
183
+ objectId: string;
184
+ objectType: 'canvas' | 'text';
185
+ effectType: Effect['type'];
186
+ };
187
+ }
188
+ /** Bind a property to an audio feature (RMS / band / beat). */
189
+ export interface AddAudioReactiveCommand {
190
+ type: 'ADD_AUDIO_REACTIVE';
191
+ payload: {
192
+ objectId: string;
193
+ objectType: 'canvas' | 'text';
194
+ modifier: AudioReactiveModifier;
195
+ };
196
+ }
197
+ /** Set the v2 mask on a canvas object (rect / circle / reveal / clipPath). */
198
+ export interface SetMaskCommand {
199
+ type: 'SET_MASK';
200
+ payload: {
201
+ objectId: string;
202
+ mask: MaskV2;
203
+ };
204
+ }
205
+ export type AiCommand = AddTextCommand | UpdateTextCommand | RemoveTextCommand | AddClipCommand | UpdateClipCommand | RemoveClipCommand | UpdateCanvasObjectCommand | SetCanvasPresetCommand | AddTrackCommand | SplitClipCommand | DuplicateClipCommand | SetTransitionCommand | SetClipAnimationCommand | SetCinematicLookCommand | DetachAudioCommand | CutToBeatCommand | SetObjectAnimationCommand | SetAnimationsCommand | AddEffectCommand | RemoveEffectCommand | AddAudioReactiveCommand | SetMaskCommand;
206
+ export interface EditorSnapshot {
207
+ timelineClips: TimelineClip[];
208
+ canvasObjects: CanvasObject[];
209
+ tracks: TrackDefinition[];
210
+ textOverlays: TextOverlay[];
211
+ assetLibrary: AssetClip[];
212
+ canvasPreset: {
213
+ id: string;
214
+ label: string;
215
+ width: number;
216
+ height: number;
217
+ };
218
+ videoDurationMs: number;
219
+ /** Beat analysis cache, keyed by audio asset id. Optional — present
220
+ * only when the AI panel was opened after audio analysis completed. */
221
+ audioBeatsByAssetId?: Record<string, BeatAnalysis | 'analyzing' | 'failed'>;
222
+ }
223
+ export interface OrchestratorActions {
224
+ addTextOverlay: (overlay: TextOverlay) => void;
225
+ updateTextOverlay: (id: string, patch: Partial<TextOverlay>) => void;
226
+ removeTextOverlay: (id: string) => void;
227
+ addClipToTimeline: (asset: AssetClip) => void;
228
+ updateClipBounds: (id: string, updates: Partial<Pick<TimelineClip, 'startMs' | 'durationMs' | 'sourceOffsetMs'>>) => void;
229
+ deleteClipById: (id: string) => void;
230
+ setClipVolume: (id: string, volume: number) => void;
231
+ setClipOpacity: (id: string, opacity: number) => void;
232
+ setClipSpeed: (id: string, rate: number) => void;
233
+ setSelectedClipId: (id: string | null) => void;
234
+ splitClip: (splitAtMs: number) => void;
235
+ duplicateClip: (id: string) => void;
236
+ setClipTransition: (clipId: string, edge: 'in' | 'out', config: {
237
+ type: string;
238
+ durationMs: number;
239
+ } | undefined) => void;
240
+ setClipAnimation: (clipId: string, phase: 'in' | 'out', config: {
241
+ type: string;
242
+ durationMs: number;
243
+ } | undefined) => void;
244
+ detachAudio: (clipId: string) => void;
245
+ updateCanvasObject: (id: string, patch: Partial<CanvasObject>) => void;
246
+ setCanvasPreset: (preset: {
247
+ id: string;
248
+ label: string;
249
+ width: number;
250
+ height: number;
251
+ }) => void;
252
+ setCinematicLook: (look: string) => void;
253
+ addTrack: (type: 'visual' | 'audio') => TrackDefinition;
254
+ replaceTimelineClips: (clips: TimelineClip[], canvasObjects?: CanvasObject[]) => void;
255
+ pushUndo: () => void;
256
+ }
257
+ /**
258
+ * Execute an array of AI commands against the editor store.
259
+ *
260
+ * Pushes a single undo checkpoint before processing all commands,
261
+ * so the entire AI action can be undone in one Ctrl+Z.
262
+ */
263
+ export declare function executeAiCommands(commands: AiCommand[], snapshot: EditorSnapshot, actions: OrchestratorActions): {
264
+ applied: number;
265
+ errors: string[];
266
+ };