@codingfactory/mediables-vue 2.8.0 → 2.9.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.
Files changed (53) hide show
  1. package/dist/PixiFrameExporter-DGTn9-uZ.cjs +2 -0
  2. package/dist/{PixiFrameExporter-CqKXaoCX.cjs.map → PixiFrameExporter-DGTn9-uZ.cjs.map} +1 -1
  3. package/dist/{PixiFrameExporter-BcywK0MP.js → PixiFrameExporter-qCsqARff.js} +60 -59
  4. package/dist/{PixiFrameExporter-BcywK0MP.js.map → PixiFrameExporter-qCsqARff.js.map} +1 -1
  5. package/dist/components/video/ui-v2/AssetRail.vue.d.ts +2 -0
  6. package/dist/components/video/ui-v2/AssetRailItem.vue.d.ts +7 -0
  7. package/dist/components/video/ui-v2/AudioMixerPanel.vue.d.ts +33 -0
  8. package/dist/components/video/ui-v2/CaptionSrtPanel.vue.d.ts +9 -0
  9. package/dist/components/video/ui-v2/DesktopInspectorSections.vue.d.ts +21 -0
  10. package/dist/components/video/ui-v2/DraftRecoveryBanner.vue.d.ts +12 -0
  11. package/dist/components/video/ui-v2/KeyframePresetPanel.vue.d.ts +26 -0
  12. package/dist/components/video/ui-v2/MobileClipSummary.vue.d.ts +4 -0
  13. package/dist/components/video/ui-v2/MobileToolPicker.vue.d.ts +3 -0
  14. package/dist/components/video/ui-v2/SplitPanelLayout.vue.d.ts +9 -5
  15. package/dist/components/video/ui-v2/TimelineTrackHeader.vue.d.ts +2 -0
  16. package/dist/composables/useClientVideoExport.d.ts +27 -0
  17. package/dist/composables/useLiveStream.d.ts +2 -2
  18. package/dist/composables/useRadialMenu.d.ts +1 -1
  19. package/dist/composables/useVideoEditor.d.ts +119 -7
  20. package/dist/composables/useVideoFilters.d.ts +4 -4
  21. package/dist/index-B8iY-eYF.js +33011 -0
  22. package/dist/index-B8iY-eYF.js.map +1 -0
  23. package/dist/index-EmUdY4EL.cjs +350 -0
  24. package/dist/index-EmUdY4EL.cjs.map +1 -0
  25. package/dist/mediables-vue.cjs +1 -1
  26. package/dist/mediables-vue.mjs +1 -1
  27. package/dist/render-page/assets/{index-y90zwXpc.js → index-jZGmiMRr.js} +991 -151
  28. package/dist/render-page/index.html +1 -1
  29. package/dist/services/VideoJobClient.d.ts +1 -1
  30. package/dist/style.css +1 -1
  31. package/dist/types/api.d.ts +14 -0
  32. package/dist/types/video.d.ts +164 -5
  33. package/dist/video/project/audioMixerSchema.d.ts +152 -0
  34. package/dist/video/project/captionSrt.d.ts +23 -0
  35. package/dist/video/project/draftRecovery.d.ts +86 -0
  36. package/dist/video/project/exportPresets.d.ts +172 -0
  37. package/dist/video/project/index.d.ts +22 -0
  38. package/dist/video/project/keyframeAutomation.d.ts +91 -0
  39. package/dist/video/project/mediaSourceAnalysis.d.ts +127 -0
  40. package/dist/video/project/mediaSourceCache.d.ts +47 -0
  41. package/dist/video/project/recipeMigration.d.ts +26 -0
  42. package/dist/video/project/timelineSelection.d.ts +23 -0
  43. package/dist/video/project/timelineTransactions.d.ts +129 -0
  44. package/dist/video/project/visualLayerSchema.d.ts +238 -0
  45. package/dist/video-engine/adapters/AudioManager.d.ts +9 -0
  46. package/dist/video-engine/adapters/MediablesCompositionAdapter.d.ts +3 -0
  47. package/dist/video-engine/adapters/TextOverlayManager.d.ts +4 -2
  48. package/package.json +1 -1
  49. package/dist/PixiFrameExporter-CqKXaoCX.cjs +0 -2
  50. package/dist/index-DNo3Kr1t.cjs +0 -342
  51. package/dist/index-DNo3Kr1t.cjs.map +0 -1
  52. package/dist/index-DpkdpuMs.js +0 -29327
  53. package/dist/index-DpkdpuMs.js.map +0 -1
@@ -2,6 +2,15 @@
2
2
  * API Types for Video Processing
3
3
  */
4
4
  import type { VideoRecipe } from './video';
5
+ export type VideoJobPhase = 'preparing' | 'rendering' | 'encoding-video' | 'encoding-audio' | 'muxing' | 'storing' | 'complete';
6
+ export interface VideoJobProgressDetail {
7
+ raw_stage?: string;
8
+ raw_status?: string;
9
+ heartbeat?: number;
10
+ script_progress?: number;
11
+ updated_at?: string;
12
+ [key: string]: unknown;
13
+ }
5
14
  export interface VideoProcessingJob {
6
15
  id: string;
7
16
  user_id: string;
@@ -15,11 +24,16 @@ export interface VideoProcessingJob {
15
24
  height?: number;
16
25
  fps?: number;
17
26
  fileSize?: number;
27
+ [key: string]: unknown;
18
28
  };
19
29
  progress: number;
30
+ phase?: VideoJobPhase;
31
+ progress_message?: string;
32
+ progress_detail?: VideoJobProgressDetail;
20
33
  error_message?: string;
21
34
  started_at?: string;
22
35
  completed_at?: string;
36
+ cancelled_at?: string;
23
37
  created_at: string;
24
38
  updated_at: string;
25
39
  }
@@ -2,6 +2,20 @@
2
2
  * Video Subsystem Type Definitions
3
3
  * Provides comprehensive typing for video editing, playback, and export
4
4
  */
5
+ import type { KeyframeAutomationPoint } from '../video/project/keyframeAutomation';
6
+ import type { FilmstripFrameReference, WaveformPeakRmsSample } from '../video/project/mediaSourceAnalysis';
7
+ import type { CaptionTrackRecipe, VisualLayerRecipe } from '../video/project/visualLayerSchema';
8
+ export type { KeyframeAutomationPoint } from '../video/project/keyframeAutomation';
9
+ export type { CaptionTrackRecipe, VisualLayerRecipe } from '../video/project/visualLayerSchema';
10
+ export type JsonPrimitive = string | number | boolean | null;
11
+ export type JsonValue = JsonPrimitive | JsonValue[] | {
12
+ [key: string]: JsonValue;
13
+ };
14
+ export type JsonObject = {
15
+ [key: string]: JsonValue;
16
+ };
17
+ export type FilterParamValue = JsonValue;
18
+ export type FilterParamMap = Record<string, FilterParamValue>;
5
19
  /**
6
20
  * Core video media type extending base media
7
21
  */
@@ -38,9 +52,20 @@ export interface VideoMedia {
38
52
  /**
39
53
  * Timeline clip representation
40
54
  */
55
+ export type TimelineClipKind = 'clip' | 'video' | 'audio' | 'image' | 'text' | 'graphics';
41
56
  export interface TimelineClip {
42
57
  id: string;
43
- type: 'clip' | 'video';
58
+ type: TimelineClipKind;
59
+ /**
60
+ * Optional first-class track identifier. Existing flat recipes omit this and
61
+ * load into a default video track.
62
+ */
63
+ trackId?: string;
64
+ /**
65
+ * Optional media-source reference for multi-source projects. Existing recipes
66
+ * keep using recipe.source.
67
+ */
68
+ sourceRefId?: string;
44
69
  timelineStart: number;
45
70
  timelineEnd: number;
46
71
  startTime?: number;
@@ -60,6 +85,9 @@ export interface TimelineClip {
60
85
  filters?: AppliedFilter[];
61
86
  thumbnail?: string;
62
87
  label?: string;
88
+ waveformSamples?: readonly WaveformPeakRmsSample[];
89
+ filmstripFrames?: readonly FilmstripFrameReference[];
90
+ keyframes?: readonly KeyframeAutomationPoint[];
63
91
  url?: string;
64
92
  muted?: boolean;
65
93
  scale?: number;
@@ -72,6 +100,125 @@ export interface TimelineClip {
72
100
  scale?: number;
73
101
  };
74
102
  }
103
+ export type TimelineTrackType = 'video' | 'audio' | 'image' | 'text' | 'graphics' | 'caption';
104
+ export interface TimelineTrack {
105
+ id: string;
106
+ type: TimelineTrackType;
107
+ name: string;
108
+ order: number;
109
+ locked?: boolean;
110
+ hidden?: boolean;
111
+ muted?: boolean;
112
+ solo?: boolean;
113
+ height?: number;
114
+ clipIds?: string[];
115
+ }
116
+ export type TimelineClipSourceType = 'media' | 'url' | 'blob' | 'generated';
117
+ export interface TimelineClipSource {
118
+ id: string;
119
+ type: TimelineClipSourceType;
120
+ mediaUuid?: string;
121
+ url?: string;
122
+ filename?: string;
123
+ mimeType?: string;
124
+ duration?: number;
125
+ width?: number;
126
+ height?: number;
127
+ frameRate?: number;
128
+ hasAudio?: boolean;
129
+ thumbnailUrl?: string;
130
+ isPrivate?: boolean;
131
+ metadata?: JsonObject;
132
+ }
133
+ export interface TimelineMarker {
134
+ id: string;
135
+ time: number;
136
+ label?: string;
137
+ color?: string;
138
+ kind?: 'chapter' | 'edit' | 'beat' | 'comment';
139
+ }
140
+ export type TimelineSelectionItem = {
141
+ type: 'clip';
142
+ id: string;
143
+ } | {
144
+ type: 'track';
145
+ id: string;
146
+ } | {
147
+ type: 'marker';
148
+ id: string;
149
+ } | {
150
+ type: 'transition';
151
+ id: string;
152
+ } | {
153
+ type: 'keyframe';
154
+ id: string;
155
+ property: string;
156
+ };
157
+ export interface TimelineSnapSettings {
158
+ enabled: boolean;
159
+ grid?: boolean;
160
+ frames?: boolean;
161
+ clips?: boolean;
162
+ playhead?: boolean;
163
+ markers?: boolean;
164
+ beats?: boolean;
165
+ thresholdPixels?: number;
166
+ }
167
+ export type TimelineTransitionType = 'cut' | 'fade' | 'crossfade' | 'dip-to-black' | 'wipe-left' | 'wipe-right' | 'slide-left' | 'slide-right' | 'zoom';
168
+ export type TimelineTransitionEasing = 'linear' | 'ease-in' | 'ease-out' | 'ease-in-out';
169
+ export interface TimelineTransitionParams {
170
+ direction?: 'left' | 'right' | 'up' | 'down';
171
+ color?: string;
172
+ softness?: number;
173
+ }
174
+ export interface TimelineTransitionRecipe {
175
+ id: string;
176
+ type: TimelineTransitionType;
177
+ fromClipId: string;
178
+ toClipId: string;
179
+ duration: number;
180
+ easing: TimelineTransitionEasing;
181
+ cutTime?: number;
182
+ params?: TimelineTransitionParams;
183
+ }
184
+ export type TimelineEditAction = {
185
+ type: 'clip.split';
186
+ clipId: string;
187
+ time: number;
188
+ } | {
189
+ type: 'clip.delete';
190
+ clipId: string;
191
+ ripple: boolean;
192
+ } | {
193
+ type: 'clip.duplicate';
194
+ clipId: string;
195
+ newClipId: string;
196
+ } | {
197
+ type: 'clip.move';
198
+ clipId: string;
199
+ from: number;
200
+ to: number;
201
+ } | {
202
+ type: 'clip.trim';
203
+ clipId: string;
204
+ edge: 'start' | 'end';
205
+ from: number;
206
+ to: number;
207
+ } | {
208
+ type: 'clip.speed';
209
+ clipId: string;
210
+ from: number;
211
+ to: number;
212
+ } | {
213
+ type: 'selection.set';
214
+ items: TimelineSelectionItem[];
215
+ } | {
216
+ type: 'marker.add';
217
+ marker: TimelineMarker;
218
+ } | {
219
+ type: 'marker.remove';
220
+ markerId: string;
221
+ };
75
222
  /**
76
223
  * Filter definition for video processing
77
224
  */
@@ -81,7 +228,7 @@ export interface VideoFilterDefinition {
81
228
  category: 'color' | 'blur' | 'stylize' | 'effects' | 'transform';
82
229
  ffmpeg?: string;
83
230
  pixiFilter?: string;
84
- defaultParams?: Record<string, any>;
231
+ defaultParams?: FilterParamMap;
85
232
  paramRanges?: Record<string, {
86
233
  min: number;
87
234
  max: number;
@@ -94,7 +241,7 @@ export interface VideoFilterDefinition {
94
241
  export interface AppliedFilter {
95
242
  id: string;
96
243
  filterId: string;
97
- params: Record<string, any>;
244
+ params: FilterParamMap;
98
245
  intensity: number;
99
246
  ffmpegCommand?: string;
100
247
  }
@@ -201,9 +348,16 @@ export interface VideoRecipe {
201
348
  original_height: number;
202
349
  };
203
350
  timeline: TimelineClip[];
351
+ mediaSources?: TimelineClipSource[];
352
+ tracks?: TimelineTrack[];
353
+ markers?: TimelineMarker[];
354
+ transitions?: TimelineTransitionRecipe[];
355
+ snapSettings?: TimelineSnapSettings;
204
356
  filters: AppliedFilter[];
205
357
  audio: AudioSettings;
206
358
  textOverlays?: TextOverlayRecipe[];
359
+ captionTracks?: CaptionTrackRecipe[];
360
+ visualLayers?: VisualLayerRecipe[];
207
361
  audioTracks?: AudioTrackRecipe[];
208
362
  output: OutputSettings;
209
363
  /** PIXI-rendered poster frame as a data URL (transient — not persisted to backend) */
@@ -224,12 +378,17 @@ export interface VideoEditorState {
224
378
  mediaUuid: string;
225
379
  media?: VideoMedia;
226
380
  clips: TimelineClip[];
381
+ tracks?: TimelineTrack[];
382
+ mediaSources?: TimelineClipSource[];
383
+ transitions?: TimelineTransitionRecipe[];
227
384
  playheadPosition: number;
228
385
  totalDuration: number;
229
386
  originalDuration: number;
230
387
  filters: AppliedFilter[];
231
388
  activeFilterId?: string;
232
389
  textOverlays?: TextOverlayRecipe[];
390
+ captionTracks?: CaptionTrackRecipe[];
391
+ visualLayers?: VisualLayerRecipe[];
233
392
  audioTracks?: AudioTrackRecipe[];
234
393
  audioVolume: number;
235
394
  audioFadeIn: number;
@@ -286,7 +445,7 @@ export interface LiveStream {
286
445
  auto_record: boolean;
287
446
  low_latency: boolean;
288
447
  vod_media_uuid?: string;
289
- metadata?: Record<string, any>;
448
+ metadata?: Record<string, unknown>;
290
449
  }
291
450
  /**
292
451
  * Live stream creation options
@@ -296,7 +455,7 @@ export interface LiveStreamOptions {
296
455
  low_latency?: boolean;
297
456
  auto_record?: boolean;
298
457
  reconnect_window?: number;
299
- metadata?: Record<string, any>;
458
+ metadata?: Record<string, unknown>;
300
459
  }
301
460
  /**
302
461
  * Live stream statistics
@@ -0,0 +1,152 @@
1
+ import type { AudioSettings, AudioTrackRecipe } from '../../types/video';
2
+ export declare const AUDIO_MIXER_SCHEMA_VERSION: 1;
3
+ export declare const AUDIO_MIXER_MASTER_BUS_ID = "master";
4
+ export declare const AUDIO_MIXER_FADER_MIN_DB = -60;
5
+ export declare const AUDIO_MIXER_FADER_MAX_DB = 12;
6
+ export declare const AUDIO_MIXER_UNITY_DB = 0;
7
+ export declare const AUDIO_MIXER_METER_FLOOR_DB = -90;
8
+ export declare const AUDIO_MIXER_METER_CEILING_DB = 6;
9
+ export declare const DEFAULT_AUDIO_MIXER_EFFECT_SLOT_COUNT = 4;
10
+ export declare const AUDIO_MIXER_MAX_EFFECT_SLOT_COUNT = 8;
11
+ export type AudioMixerSchemaVersion = typeof AUDIO_MIXER_SCHEMA_VERSION;
12
+ export type AudioMixerDeviceClass = 'mobile' | 'desktop';
13
+ export type AudioMixerTrackKind = 'legacy-url' | 'media' | 'music' | 'voiceover' | 'ambience' | 'generated';
14
+ export type AudioMixerPanMode = 'constant-power' | 'linear';
15
+ export type AudioMixerMeterMode = 'off' | 'basic' | 'full';
16
+ export type AudioMixerEffectKind = 'empty' | 'gain' | 'eq' | 'compressor' | 'limiter' | 'noise-gate' | 'reverb' | 'delay' | 'custom';
17
+ export type AudioMixerEffectParameterValue = string | number | boolean;
18
+ export type AudioMixerEffectParameters = Record<string, AudioMixerEffectParameterValue>;
19
+ export interface AudioMixerCapabilityFlags {
20
+ canAdjustTrackFaders: boolean;
21
+ canAdjustMasterFader: boolean;
22
+ canMuteTracks: boolean;
23
+ canSoloTracks: boolean;
24
+ canAdjustPan: boolean;
25
+ canViewMeters: boolean;
26
+ canEditEffectSlots: boolean;
27
+ canEditRouting: boolean;
28
+ canEditAutomation: boolean;
29
+ meterMode: AudioMixerMeterMode;
30
+ maxEffectSlots: number;
31
+ }
32
+ export interface AudioMixerCapabilityMatrix {
33
+ mobile: AudioMixerCapabilityFlags;
34
+ desktop: AudioMixerCapabilityFlags;
35
+ }
36
+ export interface AudioMixerFader {
37
+ valueDb: number;
38
+ minDb: number;
39
+ maxDb: number;
40
+ unityDb: number;
41
+ linearGain: number;
42
+ }
43
+ export interface AudioMixerPan {
44
+ value: number;
45
+ mode: AudioMixerPanMode;
46
+ }
47
+ export interface AudioMixerMeterSnapshot {
48
+ peakDb: number;
49
+ rmsDb: number;
50
+ peakHoldDb: number;
51
+ clipping: boolean;
52
+ }
53
+ export interface AudioMixerEffectSlot {
54
+ id: string;
55
+ index: number;
56
+ kind: AudioMixerEffectKind;
57
+ label: string;
58
+ enabled: boolean;
59
+ bypassed: boolean;
60
+ wetMix: number;
61
+ parameters: AudioMixerEffectParameters;
62
+ }
63
+ export interface AudioMixerTrackControls {
64
+ fader: AudioMixerFader;
65
+ pan: AudioMixerPan;
66
+ muted: boolean;
67
+ solo: boolean;
68
+ meter: AudioMixerMeterSnapshot;
69
+ }
70
+ export type AudioMixerTrackSource = {
71
+ type: 'url';
72
+ url: string;
73
+ } | {
74
+ type: 'missing';
75
+ };
76
+ export interface AudioMixerTimelinePlacement {
77
+ startTime: number;
78
+ loop: boolean;
79
+ duration?: number;
80
+ fadeIn?: number;
81
+ fadeOut?: number;
82
+ }
83
+ export interface AudioMixerTrack {
84
+ id: string;
85
+ kind: AudioMixerTrackKind;
86
+ name: string;
87
+ order: number;
88
+ source: AudioMixerTrackSource;
89
+ controls: AudioMixerTrackControls;
90
+ timeline: AudioMixerTimelinePlacement;
91
+ effectSlots: AudioMixerEffectSlot[];
92
+ legacyTrackId?: string;
93
+ }
94
+ export interface AudioMixerMasterBus {
95
+ id: typeof AUDIO_MIXER_MASTER_BUS_ID;
96
+ name: string;
97
+ fader: AudioMixerFader;
98
+ muted: boolean;
99
+ meter: AudioMixerMeterSnapshot;
100
+ effectSlots: AudioMixerEffectSlot[];
101
+ }
102
+ export interface AudioMixerState {
103
+ schemaVersion: AudioMixerSchemaVersion;
104
+ capabilities: AudioMixerCapabilityMatrix;
105
+ tracks: AudioMixerTrack[];
106
+ master: AudioMixerMasterBus;
107
+ }
108
+ export interface EffectiveAudioMixerTrackState {
109
+ trackId: string;
110
+ soloed: boolean;
111
+ mutedByTrack: boolean;
112
+ mutedBySolo: boolean;
113
+ mutedByMaster: boolean;
114
+ effectivelyMuted: boolean;
115
+ audible: boolean;
116
+ effectiveGainLinear: number;
117
+ }
118
+ export interface LegacyAudioTrackMixerInput extends AudioTrackRecipe {
119
+ muted?: boolean;
120
+ solo?: boolean;
121
+ pan?: number;
122
+ faderDb?: number;
123
+ peakDb?: number;
124
+ rmsDb?: number;
125
+ peakHoldDb?: number;
126
+ effectSlots?: AudioMixerEffectSlot[];
127
+ }
128
+ export interface LegacyMasterAudioMixerInput extends Partial<AudioSettings> {
129
+ name?: string;
130
+ faderDb?: number;
131
+ peakDb?: number;
132
+ rmsDb?: number;
133
+ peakHoldDb?: number;
134
+ effectSlots?: AudioMixerEffectSlot[];
135
+ }
136
+ export interface NormalizeAudioMixerStateOptions {
137
+ master?: LegacyMasterAudioMixerInput;
138
+ capabilities?: AudioMixerCapabilityMatrix;
139
+ effectSlotCount?: number;
140
+ }
141
+ export declare function createDefaultAudioMixerCapabilities(): AudioMixerCapabilityMatrix;
142
+ export declare function getAudioMixerCapabilitiesForDevice(deviceClass: AudioMixerDeviceClass, capabilities?: AudioMixerCapabilityMatrix): AudioMixerCapabilityFlags;
143
+ export declare function linearVolumeToDb(linearVolume: number): number;
144
+ export declare function dbToLinearVolume(faderDb: number): number;
145
+ export declare function clampFaderDb(faderDb: number): number;
146
+ export declare function clampPanValue(pan: number): number;
147
+ export declare function computeEffectiveMuteSoloState(tracks: readonly AudioMixerTrack[], masterMuted?: boolean): EffectiveAudioMixerTrackState[];
148
+ export declare function normalizeMixerStateFromLegacyAudioTracks(legacyTracks: readonly LegacyAudioTrackMixerInput[], options?: NormalizeAudioMixerStateOptions): AudioMixerState;
149
+ export declare function createAudioMixerFader(valueDb: number): AudioMixerFader;
150
+ export declare function createAudioMixerPan(value: number, mode?: AudioMixerPanMode): AudioMixerPan;
151
+ export declare function createAudioMixerMeter(peakDb?: number, rmsDb?: number, peakHoldDb?: number): AudioMixerMeterSnapshot;
152
+ export declare function createEmptyAudioMixerEffectSlot(index: number): AudioMixerEffectSlot;
@@ -0,0 +1,23 @@
1
+ import type { CaptionSegmentRecipe } from './visualLayerSchema';
2
+ export type CaptionSrtErrorCode = 'invalid-cue-number' | 'missing-timing' | 'invalid-timing' | 'invalid-time' | 'invalid-duration' | 'overlapping-cues';
3
+ export interface CaptionSrtErrorContext {
4
+ cueIndex?: number;
5
+ cueNumber?: number;
6
+ lineNumber?: number;
7
+ segmentId?: string;
8
+ }
9
+ export declare class CaptionSrtError extends Error {
10
+ readonly code: CaptionSrtErrorCode;
11
+ readonly context: CaptionSrtErrorContext;
12
+ constructor(code: CaptionSrtErrorCode, message: string, context?: CaptionSrtErrorContext);
13
+ }
14
+ export interface CaptionSrtCue extends CaptionSegmentRecipe {
15
+ cueNumber: number;
16
+ }
17
+ export interface ParseCaptionSrtOptions {
18
+ idPrefix?: string;
19
+ }
20
+ export declare function parseCaptionSrt(source: string, options?: ParseCaptionSrtOptions): CaptionSrtCue[];
21
+ export declare function exportCaptionSrt(cues: readonly CaptionSegmentRecipe[]): string;
22
+ export declare function validateCaptionSrtCues(cues: readonly CaptionSegmentRecipe[]): void;
23
+ export declare function formatSrtTimestamp(seconds: number): string;
@@ -0,0 +1,86 @@
1
+ import type { VideoRecipe } from '../../types/video';
2
+ import type { NormalizedVideoProject } from './recipeMigration';
3
+ export declare const VIDEO_PROJECT_DRAFT_SNAPSHOT_SCHEMA_VERSION = "video-project-draft-snapshot:v1";
4
+ export declare const DEFAULT_VIDEO_PROJECT_DRAFT_STORAGE_PREFIX = "mediables:video-project-drafts";
5
+ export type VideoProjectDraftPayloadKind = 'recipe' | 'project';
6
+ export type VideoProjectDraftPayload = VideoRecipe | NormalizedVideoProject;
7
+ export type VideoProjectDraftDeviceKind = 'desktop' | 'mobile' | 'tablet' | 'unknown';
8
+ export type VideoProjectDraftSaveReason = 'autosave' | 'manual' | 'before-export' | 'before-close';
9
+ export type VideoProjectDraftRecoverySurface = 'desktop' | 'mobile';
10
+ export type VideoProjectDraftTimestampInput = string | number | Date;
11
+ export type VideoProjectDraftStorageResult<T> = T | Promise<T>;
12
+ export interface VideoProjectDraftSnapshotMetadata {
13
+ id: string;
14
+ payloadKind: VideoProjectDraftPayloadKind;
15
+ createdAt: string;
16
+ updatedAt: string;
17
+ deviceKind: VideoProjectDraftDeviceKind;
18
+ projectId?: string;
19
+ sourceMediaUuid?: string;
20
+ durationSeconds?: number;
21
+ editorVersion?: string;
22
+ title?: string;
23
+ saveReason?: VideoProjectDraftSaveReason;
24
+ }
25
+ export interface VideoProjectDraftSnapshot<Payload extends VideoProjectDraftPayload = VideoProjectDraftPayload> {
26
+ schemaVersion: typeof VIDEO_PROJECT_DRAFT_SNAPSHOT_SCHEMA_VERSION;
27
+ metadata: VideoProjectDraftSnapshotMetadata;
28
+ payload: Payload;
29
+ }
30
+ export interface CreateVideoProjectDraftSnapshotOptions {
31
+ id?: string;
32
+ projectId?: string;
33
+ now?: VideoProjectDraftTimestampInput;
34
+ createdAt?: VideoProjectDraftTimestampInput;
35
+ updatedAt?: VideoProjectDraftTimestampInput;
36
+ deviceKind?: VideoProjectDraftDeviceKind;
37
+ sourceMediaUuid?: string;
38
+ durationSeconds?: number;
39
+ editorVersion?: string;
40
+ title?: string;
41
+ saveReason?: VideoProjectDraftSaveReason;
42
+ }
43
+ export interface StoredVideoProjectDraftSnapshotEntry {
44
+ key: string;
45
+ value: string | null;
46
+ }
47
+ export interface VideoProjectDraftSnapshotRecord<Payload extends VideoProjectDraftPayload = VideoProjectDraftPayload> {
48
+ key: string;
49
+ snapshot: VideoProjectDraftSnapshot<Payload>;
50
+ }
51
+ export interface VideoProjectDraftSnapshotStorageAdapter {
52
+ getItem: (key: string) => VideoProjectDraftStorageResult<string | null>;
53
+ setItem: (key: string, value: string) => VideoProjectDraftStorageResult<void>;
54
+ removeItem: (key: string) => VideoProjectDraftStorageResult<void>;
55
+ listKeys: (prefix: string) => VideoProjectDraftStorageResult<readonly string[]>;
56
+ }
57
+ export interface VideoProjectDraftSnapshotRotationOptions {
58
+ maxCount: number;
59
+ maxAgeMs?: number;
60
+ now?: VideoProjectDraftTimestampInput;
61
+ projectId?: string;
62
+ }
63
+ export interface VideoProjectDraftSnapshotRotationResult {
64
+ retained: readonly VideoProjectDraftSnapshotRecord[];
65
+ removed: readonly VideoProjectDraftSnapshotRecord[];
66
+ }
67
+ export interface VideoProjectDraftRecoveryOptions {
68
+ projectId?: string;
69
+ savedAt?: VideoProjectDraftTimestampInput | null;
70
+ maxAgeMs?: number;
71
+ now?: VideoProjectDraftTimestampInput;
72
+ }
73
+ export declare const createVideoProjectDraftSnapshot: <Payload extends VideoProjectDraftPayload>(payload: Payload, options?: CreateVideoProjectDraftSnapshotOptions) => VideoProjectDraftSnapshot<Payload>;
74
+ export declare const createVideoProjectDraftStorageKey: (snapshot: VideoProjectDraftSnapshot, prefix?: string) => string;
75
+ export declare const serializeVideoProjectDraftSnapshot: (snapshot: VideoProjectDraftSnapshot) => string;
76
+ export declare const parseStoredVideoProjectDraftSnapshot: (value: string | null | undefined) => VideoProjectDraftSnapshot | null;
77
+ export declare const parseStoredVideoProjectDraftSnapshotRecords: (entries: readonly StoredVideoProjectDraftSnapshotEntry[]) => VideoProjectDraftSnapshotRecord[];
78
+ export declare const rotateVideoProjectDraftSnapshots: (records: readonly VideoProjectDraftSnapshotRecord[], options: VideoProjectDraftSnapshotRotationOptions) => VideoProjectDraftSnapshotRotationResult;
79
+ export declare const rotateStoredVideoProjectDraftSnapshots: (entries: readonly StoredVideoProjectDraftSnapshotEntry[], options: VideoProjectDraftSnapshotRotationOptions) => VideoProjectDraftSnapshotRotationResult;
80
+ export declare const isVideoProjectDraftSnapshotRestorable: (snapshot: VideoProjectDraftSnapshot, options?: VideoProjectDraftRecoveryOptions) => boolean;
81
+ export declare const getRestorableVideoProjectDraftSnapshotRecords: (records: readonly VideoProjectDraftSnapshotRecord[], options?: VideoProjectDraftRecoveryOptions) => VideoProjectDraftSnapshotRecord[];
82
+ export declare const chooseLatestRestorableVideoProjectDraftSnapshot: (records: readonly VideoProjectDraftSnapshotRecord[], options?: VideoProjectDraftRecoveryOptions) => VideoProjectDraftSnapshotRecord | null;
83
+ export declare const selectRestorableVideoProjectDraftsForSurface: (records: readonly VideoProjectDraftSnapshotRecord[], surface: VideoProjectDraftRecoverySurface, options?: VideoProjectDraftRecoveryOptions) => VideoProjectDraftSnapshotRecord[];
84
+ export declare const saveVideoProjectDraftSnapshot: (adapter: VideoProjectDraftSnapshotStorageAdapter, snapshot: VideoProjectDraftSnapshot, key?: string) => Promise<VideoProjectDraftSnapshotRecord>;
85
+ export declare const loadVideoProjectDraftSnapshotRecords: (adapter: VideoProjectDraftSnapshotStorageAdapter, prefix?: string) => Promise<VideoProjectDraftSnapshotRecord[]>;
86
+ export declare const removeVideoProjectDraftSnapshotRecords: (adapter: VideoProjectDraftSnapshotStorageAdapter, records: readonly VideoProjectDraftSnapshotRecord[]) => Promise<void>;