@meframe/core 0.0.26 → 0.0.28
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/Meframe.d.ts +2 -2
- package/dist/Meframe.d.ts.map +1 -1
- package/dist/Meframe.js +9 -3
- package/dist/Meframe.js.map +1 -1
- package/dist/cache/CacheManager.d.ts +2 -0
- package/dist/cache/CacheManager.d.ts.map +1 -1
- package/dist/cache/CacheManager.js +9 -2
- package/dist/cache/CacheManager.js.map +1 -1
- package/dist/cache/l1/AudioL1Cache.d.ts +1 -1
- package/dist/cache/l1/AudioL1Cache.js +2 -2
- package/dist/cache/l1/AudioL1Cache.js.map +1 -1
- package/dist/controllers/PreRenderService.js +3 -0
- package/dist/controllers/PreRenderService.js.map +1 -1
- package/dist/model/CompositionModel.d.ts +1 -0
- package/dist/model/CompositionModel.d.ts.map +1 -1
- package/dist/model/CompositionModel.js +1 -1
- package/dist/model/CompositionModel.js.map +1 -1
- package/dist/model/patch.js +22 -59
- package/dist/model/patch.js.map +1 -1
- package/dist/model/types.d.ts +5 -0
- package/dist/model/types.d.ts.map +1 -1
- package/dist/model/types.js.map +1 -1
- package/dist/orchestrator/Orchestrator.d.ts +2 -1
- package/dist/orchestrator/Orchestrator.d.ts.map +1 -1
- package/dist/orchestrator/Orchestrator.js +10 -2
- package/dist/orchestrator/Orchestrator.js.map +1 -1
- package/dist/stages/decode/BaseDecoder.js +1 -1
- package/dist/stages/decode/BaseDecoder.js.map +1 -1
- package/dist/stages/decode/types.d.ts +1 -0
- package/dist/stages/decode/types.d.ts.map +1 -1
- package/dist/workers/{BaseDecoder.BGsRDny7.js → BaseDecoder.BWYu1W0B.js} +2 -2
- package/dist/workers/BaseDecoder.BWYu1W0B.js.map +1 -0
- package/dist/workers/stages/decode/{audio-decode.worker.3SD5i_Oe.js → audio-decode.worker.DnS17GD9.js} +2 -2
- package/dist/workers/stages/decode/{audio-decode.worker.3SD5i_Oe.js.map → audio-decode.worker.DnS17GD9.js.map} +1 -1
- package/dist/workers/stages/decode/{video-decode.worker.BAB6216v.js → video-decode.worker.BEYsjOXp.js} +2 -2
- package/dist/workers/stages/decode/{video-decode.worker.BAB6216v.js.map → video-decode.worker.BEYsjOXp.js.map} +1 -1
- package/dist/workers/worker-manifest.json +2 -2
- package/package.json +1 -1
- package/dist/workers/BaseDecoder.BGsRDny7.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CompositionModel.js","sources":["../../src/model/CompositionModel.ts"],"sourcesContent":["import {\n CompositionModelData,\n Track,\n Clip,\n Resource,\n TimeUs,\n AnimationEffect,\n hasResourceId,\n} from './types';\nimport { binarySearchRange, binarySearchOverlapping } from '../utils/binary-search';\nimport { validateCompositionStructure } from './validation';\n\nexport class CompositionModel {\n public readonly version = '1.0' as const;\n public readonly fps: 24 | 25 | 30 | 60;\n public durationUs!: TimeUs; // Assigned in buildIndexes()\n public readonly mainTrackId: string;\n public tracks: Track[];\n public readonly resources: Map<string, Resource>;\n\n private readonly trackMap: Map<string, Track>;\n private readonly clipMap: Map<string, Clip>;\n private readonly resourceRefCount: Map<string, number>;\n\n public readonly renderConfig?: {\n width: number;\n height: number;\n backgroundColor?: string;\n };\n\n public readonly ext?: Record<string, unknown>;\n\n constructor(data: CompositionModelData) {\n const errors = validateCompositionStructure(data);\n if (errors.length > 0) {\n throw new Error(\n `Validation failed:\\n${errors.map((e) => `${e.path}: ${e.message}`).join('\\n')}`\n );\n }\n\n this.fps = data.fps;\n this.mainTrackId = data.mainTrackId ?? 'main';\n this.tracks = data.tracks;\n this.resources = new Map(Object.entries(data.resources));\n this.renderConfig = data.renderConfig;\n this.ext = data.ext;\n\n // Build indexes\n this.trackMap = new Map();\n this.clipMap = new Map();\n this.resourceRefCount = new Map();\n\n this.buildIndexes();\n\n console.log(\n 'CompositionModel constructed',\n this.tracks.find((t) => t.id === this.mainTrackId)?.clips[0]\n );\n }\n\n // Track operations\n findTrack(id: string): Track | null {\n return this.trackMap.get(id) || null;\n }\n\n getTracksByKind(kind: 'video' | 'audio' | 'caption' | 'overlay' | 'fx'): Track[] {\n return this.tracks.filter((track) => track.kind === kind);\n }\n\n // Clip operations with binary search optimization\n findClip(id: string): Clip | null {\n return this.clipMap.get(id) || null;\n }\n\n getClipsAtTime(timeUs: TimeUs, trackId?: string): Clip[] {\n const tracks = trackId ? [this.findTrack(trackId)] : this.tracks;\n const clips: Clip[] = [];\n\n for (const track of tracks) {\n if (!track) continue;\n // Use binary search for single point lookup\n const clip = binarySearchRange(track.clips, timeUs, (entry) => ({\n start: entry.startUs,\n end: entry.startUs + entry.durationUs,\n }));\n\n if (clip) {\n clips.push(clip);\n }\n }\n\n return clips;\n }\n\n getActiveClips(startUs: TimeUs, endUs: TimeUs): Clip[] {\n const clips: Clip[] = [];\n\n for (const track of this.tracks) {\n // Use binary search for range overlap\n const overlappingClips = binarySearchOverlapping(track.clips, startUs, endUs, (clip) => ({\n start: clip.startUs,\n end: clip.startUs + clip.durationUs,\n }));\n\n clips.push(...overlappingClips);\n }\n\n return clips;\n }\n\n getClipIdsByResourceId(resourceId: string): string[] {\n const resource = this.resources.get(resourceId);\n return resource?.clipIds || [];\n }\n\n getClipIdAtTime(trackId: string, timeUs: TimeUs): string | undefined {\n const track = this.findTrack(trackId);\n if (!track) {\n return undefined;\n }\n\n const clip = binarySearchRange(track.clips, timeUs, (entry) => ({\n start: entry.startUs,\n end: entry.startUs + entry.durationUs,\n }));\n\n return clip?.id;\n }\n\n /**\n * Get neighboring clips (Prev/Current/Next) at a specific time for video tracks\n * Returns prev, current, and next clip IDs\n */\n getNeighboringClips(timeUs: TimeUs): { prev?: string; current?: string; next?: string } {\n const videoTracks = this.getTracksByKind('video');\n const result: { prev?: string; current?: string; next?: string } = {};\n\n for (const track of videoTracks) {\n const clips = track.clips;\n\n for (let i = 0; i < clips.length; i++) {\n const clip = clips[i];\n if (!clip) continue;\n\n const clipEndUs = clip.startUs + clip.durationUs;\n\n if (clip.startUs <= timeUs && timeUs < clipEndUs) {\n if (!result.current) {\n result.current = clip.id;\n }\n\n if (i > 0 && !result.prev) {\n const prevClip = clips[i - 1];\n if (prevClip) {\n result.prev = prevClip.id;\n }\n }\n\n if (i < clips.length - 1 && !result.next) {\n const nextClip = clips[i + 1];\n if (nextClip) {\n result.next = nextClip.id;\n }\n }\n }\n }\n }\n\n return result;\n }\n\n /**\n * Get all clip IDs that should be cached using adaptive strategy\n * - Short clips (≤ maxDuration): cache Current + Next (smooth transitions)\n * - Long clips (> maxDuration): cache Current only (memory control)\n * @param timeUs - Current playback time\n * @param maxDuration - Max duration for 2-clip strategy (default 5s)\n */\n getClipsToCacheAtTime(timeUs: TimeUs, maxDuration = 5_000_000): Set<string> {\n const { current, next } = this.getNeighboringClips(timeUs);\n const clipIds = new Set<string>();\n\n if (!current) return clipIds;\n clipIds.add(current);\n\n // Only cache next clip if current clip is short enough\n const currentClip = this.findClip(current);\n if (currentClip && currentClip.durationUs <= maxDuration && next) {\n clipIds.add(next);\n }\n\n return clipIds;\n }\n\n // Resource operations\n getResource(id: string): Resource | null {\n return this.resources.get(id) || null;\n }\n\n updateResourceState(id: string, state: 'pending' | 'loading' | 'ready' | 'error'): void {\n const resource = this.resources.get(id);\n if (resource) {\n resource.state = state;\n }\n }\n\n getUnusedResources(): Resource[] {\n const unused: Resource[] = [];\n\n for (const [id, resource] of this.resources) {\n if (!this.resourceRefCount.has(id) || this.resourceRefCount.get(id) === 0) {\n unused.push(resource);\n }\n }\n\n return unused;\n }\n\n // Time operations\n getDuration(): TimeUs {\n return this.durationUs;\n }\n\n getTrackDuration(trackId: string): TimeUs {\n const track = this.findTrack(trackId);\n if (!track || track.clips.length === 0) return 0;\n\n // Since clips are sorted, last clip determines duration\n const lastClip = track.clips[track.clips.length - 1];\n return (lastClip?.startUs ?? 0) + (lastClip?.durationUs ?? 0);\n }\n\n buildIndexes(options?: {\n incremental?: boolean;\n trackId?: string;\n clipId?: string;\n operation?: 'add' | 'update' | 'remove';\n }): void {\n const track = options?.trackId ? this.findTrack(options.trackId) : undefined;\n const isAttachmentTrack = track && track.kind !== 'video' && track.kind !== 'audio';\n\n // Incremental update for video/audio track clip operations\n if (options?.incremental && !isAttachmentTrack && options.clipId && options.operation) {\n const clip = this.clipMap.get(options.clipId);\n\n if (options.operation === 'add' && clip) {\n this.addClipToIndexes(clip);\n } else if (options.operation === 'remove' && clip) {\n this.removeClipFromIndexes(clip);\n } else if (options.operation === 'update' && clip) {\n // Handle resource change during update\n if (clip.oldResourceId) {\n this.updateClipResourceIndex(\n options.clipId,\n clip.oldResourceId,\n hasResourceId(clip) ? clip.resourceId : undefined\n );\n }\n }\n\n // Recalculate duration only if affected main track\n if (track?.id === this.mainTrackId) {\n this.recalculateDuration();\n }\n return;\n }\n\n // Full rebuild: needed for attachment tracks or initial load\n this.fullRebuildIndexes();\n }\n\n private fullRebuildIndexes(): void {\n // Clear existing indexes\n this.trackMap.clear();\n this.clipMap.clear();\n this.resourceRefCount.clear();\n\n // Step 1: Sink attachment tracks to main track (preserves original tracks)\n this.sinkAttachmentTracks();\n\n let maxEndUs = 0;\n\n // Step 2: Build all indexes in one pass (track, clip, resource)\n for (const track of this.tracks) {\n this.trackMap.set(track.id, track);\n\n for (const clip of track.clips) {\n (clip as Clip).trackId = track.id;\n (clip as Clip).trackKind = track.kind;\n this.clipMap.set(clip.id, clip);\n\n // Main track resource index (only for clips with resourceId)\n if (hasResourceId(clip)) {\n const resource = this.resources.get(clip.resourceId);\n if (resource) {\n resource.clipIds = [...(resource.clipIds || []), clip.id];\n }\n const count = this.resourceRefCount.get(clip.resourceId) || 0;\n this.resourceRefCount.set(clip.resourceId, count + 1);\n }\n\n // Attachment resource indexes (attachments are already sunk)\n const attachments = clip.attachments ?? [];\n for (const attachment of attachments) {\n const attachmentResourceId = attachment.data?.resourceId;\n if (attachmentResourceId && typeof attachmentResourceId === 'string') {\n const attachmentResource = this.resources.get(attachmentResourceId);\n if (attachmentResource) {\n const clipIds = attachmentResource.clipIds || [];\n if (!clipIds.includes(clip.id)) {\n attachmentResource.clipIds = [...clipIds, clip.id];\n }\n }\n const attachmentCount = this.resourceRefCount.get(attachmentResourceId) || 0;\n this.resourceRefCount.set(attachmentResourceId, attachmentCount + 1);\n }\n }\n\n // Calculate max end time\n const clipEndUs = clip.startUs + clip.durationUs;\n if (clipEndUs > maxEndUs) {\n maxEndUs = clipEndUs;\n }\n }\n }\n\n this.durationUs = maxEndUs;\n }\n\n private addClipToIndexes(clip: Clip): void {\n this.clipMap.set(clip.id, clip);\n\n if (hasResourceId(clip)) {\n const resource = this.resources.get(clip.resourceId);\n if (resource) {\n if (!resource.clipIds) {\n resource.clipIds = [];\n }\n if (!resource.clipIds.includes(clip.id)) {\n resource.clipIds.push(clip.id);\n }\n }\n const count = this.resourceRefCount.get(clip.resourceId) || 0;\n this.resourceRefCount.set(clip.resourceId, count + 1);\n }\n }\n\n private removeClipFromIndexes(clip: Clip): void {\n this.clipMap.delete(clip.id);\n\n const resourceId = clip.oldResourceId || (hasResourceId(clip) ? clip.resourceId : undefined);\n if (resourceId) {\n const resource = this.resources.get(resourceId);\n if (resource?.clipIds) {\n resource.clipIds = resource.clipIds.filter((id) => id !== clip.id);\n }\n const count = this.resourceRefCount.get(resourceId) || 0;\n this.resourceRefCount.set(resourceId, Math.max(0, count - 1));\n }\n }\n\n /**\n * Incrementally update resource index when clip's resourceId changes\n */\n updateClipResourceIndex(\n clipId: string,\n oldResourceId: string | undefined,\n newResourceId: string | undefined\n ): void {\n // Remove from old resource\n if (oldResourceId) {\n const oldResource = this.resources.get(oldResourceId);\n if (oldResource?.clipIds) {\n oldResource.clipIds = oldResource.clipIds.filter((id) => id !== clipId);\n }\n const oldCount = this.resourceRefCount.get(oldResourceId) || 0;\n this.resourceRefCount.set(oldResourceId, Math.max(0, oldCount - 1));\n }\n\n // Add to new resource\n if (newResourceId) {\n const newResource = this.resources.get(newResourceId);\n if (newResource) {\n if (!newResource.clipIds) {\n newResource.clipIds = [];\n }\n if (!newResource.clipIds.includes(clipId)) {\n newResource.clipIds.push(clipId);\n }\n }\n const newCount = this.resourceRefCount.get(newResourceId) || 0;\n this.resourceRefCount.set(newResourceId, newCount + 1);\n }\n }\n\n /**\n * Recalculate total duration based on main track\n */\n recalculateDuration(): void {\n const mainTrack = this.findTrack(this.mainTrackId);\n if (!mainTrack || mainTrack.clips.length === 0) {\n this.durationUs = 0;\n return;\n }\n\n // Since clips are sorted, last clip determines duration\n const lastClip = mainTrack.clips[mainTrack.clips.length - 1];\n this.durationUs = (lastClip?.startUs ?? 0) + (lastClip?.durationUs ?? 0);\n }\n\n private sinkAttachmentTracks(): void {\n let mainTrack: Track | undefined;\n const attachmentTracks = [];\n\n // Sort all tracks\n for (const track of this.tracks) {\n track.clips.sort((a, b) => a.startUs - b.startUs);\n\n if (track.id === this.mainTrackId) {\n mainTrack = track;\n continue;\n }\n // Collect attachment tracks for sinking (caption, overlay, fx)\n // Video and audio tracks are not sunk\n if (track.kind === 'caption' || track.kind === 'overlay' || track.kind === 'fx') {\n attachmentTracks.push(track);\n }\n }\n\n if (!mainTrack) {\n throw new Error('Main track not found');\n }\n\n // Clear existing attachments before sinking (in case of rebuild)\n for (const clip of mainTrack.clips) {\n clip.attachments = [];\n }\n\n for (const attachmentTrack of attachmentTracks) {\n for (const attachmentClip of attachmentTrack.clips) {\n // Use track.kind directly as attachment kind\n const attachmentKind = attachmentTrack.kind;\n\n for (const mainClip of mainTrack.clips) {\n const overlap = this.getTimeOverlap(attachmentClip, mainClip);\n if (!overlap) continue;\n\n if (!mainClip.attachments) {\n mainClip.attachments = [];\n }\n\n // Extract animation effect\n const animationEffect = attachmentClip.effects?.find(\n (e) => e.effectType === 'animation'\n ) as AnimationEffect | undefined;\n\n // Extract target dimensions from metadata\n const targetWidth = attachmentClip.metadata?.targetWidth as number | undefined;\n const targetHeight = attachmentClip.metadata?.targetHeight as number | undefined;\n\n const attachmentData: Record<string, unknown> = {\n animation: animationEffect?.params,\n overlayClipStartUs: attachmentClip.startUs,\n mainClipStartUs: mainClip.startUs,\n ...(targetWidth !== undefined && { targetWidth }),\n ...(targetHeight !== undefined && { targetHeight }),\n };\n\n // Add resourceId if exists (trackKind not yet set, check field directly)\n if ('resourceId' in attachmentClip && attachmentClip.resourceId) {\n attachmentData.resourceId = attachmentClip.resourceId;\n }\n\n // Add text if exists (trackKind not yet set, check field directly)\n if ('text' in attachmentClip && attachmentClip.text) {\n attachmentData.text = attachmentClip.text;\n }\n\n mainClip.attachments.push({\n id: `${attachmentKind}-${attachmentClip.id}-${mainClip.id}`,\n kind: attachmentKind,\n startUs: overlap.clipRelativeStart,\n durationUs: overlap.duration,\n data: attachmentData,\n });\n }\n }\n }\n }\n\n private getTimeOverlap(\n attachmentClip: Clip,\n mainClip: Clip\n ): { clipRelativeStart: number; duration: number } | null {\n const attachmentStart = attachmentClip.startUs;\n const attachmentEnd = attachmentClip.startUs + attachmentClip.durationUs;\n const mainStart = mainClip.startUs;\n const mainEnd = mainClip.startUs + mainClip.durationUs;\n\n if (attachmentEnd <= mainStart || attachmentStart >= mainEnd) {\n return null;\n }\n\n const overlapStart = Math.max(attachmentStart, mainStart);\n const overlapEnd = Math.min(attachmentEnd, mainEnd);\n const duration = overlapEnd - overlapStart;\n const clipRelativeStart = overlapStart - mainStart;\n\n return { clipRelativeStart, duration };\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CompositionModel.js","sources":["../../src/model/CompositionModel.ts"],"sourcesContent":["import {\n CompositionModelData,\n Track,\n Clip,\n Resource,\n TimeUs,\n AnimationEffect,\n hasResourceId,\n} from './types';\nimport { binarySearchRange, binarySearchOverlapping } from '../utils/binary-search';\nimport { validateCompositionStructure } from './validation';\n\nexport class CompositionModel {\n public readonly version = '1.0' as const;\n public readonly fps: 24 | 25 | 30 | 60;\n public durationUs!: TimeUs; // Assigned in buildIndexes()\n public readonly mainTrackId: string;\n public tracks: Track[];\n public readonly resources: Map<string, Resource>;\n\n private readonly trackMap: Map<string, Track>;\n private readonly clipMap: Map<string, Clip>;\n private readonly resourceRefCount: Map<string, number>;\n\n public readonly renderConfig?: {\n width: number;\n height: number;\n backgroundColor?: string;\n };\n\n public readonly ext?: Record<string, unknown>;\n\n constructor(data: CompositionModelData) {\n const errors = validateCompositionStructure(data);\n if (errors.length > 0) {\n throw new Error(\n `Validation failed:\\n${errors.map((e) => `${e.path}: ${e.message}`).join('\\n')}`\n );\n }\n\n this.fps = data.fps;\n this.mainTrackId = data.mainTrackId ?? 'main';\n this.tracks = data.tracks;\n this.resources = new Map(Object.entries(data.resources));\n this.renderConfig = data.renderConfig;\n this.ext = data.ext;\n\n // Build indexes\n this.trackMap = new Map();\n this.clipMap = new Map();\n this.resourceRefCount = new Map();\n\n this.buildIndexes();\n\n console.log(\n 'CompositionModel constructed',\n this.tracks.find((t) => t.id === this.mainTrackId)?.clips[0]\n );\n }\n\n // Track operations\n findTrack(id: string): Track | null {\n return this.trackMap.get(id) || null;\n }\n\n getTracksByKind(kind: 'video' | 'audio' | 'caption' | 'overlay' | 'fx'): Track[] {\n return this.tracks.filter((track) => track.kind === kind);\n }\n\n // Clip operations with binary search optimization\n findClip(id: string): Clip | null {\n return this.clipMap.get(id) || null;\n }\n\n getClipsAtTime(timeUs: TimeUs, trackId?: string): Clip[] {\n const tracks = trackId ? [this.findTrack(trackId)] : this.tracks;\n const clips: Clip[] = [];\n\n for (const track of tracks) {\n if (!track) continue;\n // Use binary search for single point lookup\n const clip = binarySearchRange(track.clips, timeUs, (entry) => ({\n start: entry.startUs,\n end: entry.startUs + entry.durationUs,\n }));\n\n if (clip) {\n clips.push(clip);\n }\n }\n\n return clips;\n }\n\n getActiveClips(startUs: TimeUs, endUs: TimeUs): Clip[] {\n const clips: Clip[] = [];\n\n for (const track of this.tracks) {\n // Use binary search for range overlap\n const overlappingClips = binarySearchOverlapping(track.clips, startUs, endUs, (clip) => ({\n start: clip.startUs,\n end: clip.startUs + clip.durationUs,\n }));\n\n clips.push(...overlappingClips);\n }\n\n return clips;\n }\n\n getClipIdsByResourceId(resourceId: string): string[] {\n const resource = this.resources.get(resourceId);\n return resource?.clipIds || [];\n }\n\n getClipIdAtTime(trackId: string, timeUs: TimeUs): string | undefined {\n const track = this.findTrack(trackId);\n if (!track) {\n return undefined;\n }\n\n const clip = binarySearchRange(track.clips, timeUs, (entry) => ({\n start: entry.startUs,\n end: entry.startUs + entry.durationUs,\n }));\n\n return clip?.id;\n }\n\n /**\n * Get neighboring clips (Prev/Current/Next) at a specific time for video tracks\n * Returns prev, current, and next clip IDs\n */\n getNeighboringClips(timeUs: TimeUs): { prev?: string; current?: string; next?: string } {\n const videoTracks = this.getTracksByKind('video');\n const result: { prev?: string; current?: string; next?: string } = {};\n\n for (const track of videoTracks) {\n const clips = track.clips;\n\n for (let i = 0; i < clips.length; i++) {\n const clip = clips[i];\n if (!clip) continue;\n\n const clipEndUs = clip.startUs + clip.durationUs;\n\n if (clip.startUs <= timeUs && timeUs < clipEndUs) {\n if (!result.current) {\n result.current = clip.id;\n }\n\n if (i > 0 && !result.prev) {\n const prevClip = clips[i - 1];\n if (prevClip) {\n result.prev = prevClip.id;\n }\n }\n\n if (i < clips.length - 1 && !result.next) {\n const nextClip = clips[i + 1];\n if (nextClip) {\n result.next = nextClip.id;\n }\n }\n }\n }\n }\n\n return result;\n }\n\n /**\n * Get all clip IDs that should be cached using adaptive strategy\n * - Short clips (≤ maxDuration): cache Current + Next (smooth transitions)\n * - Long clips (> maxDuration): cache Current only (memory control)\n * @param timeUs - Current playback time\n * @param maxDuration - Max duration for 2-clip strategy (default 5s)\n */\n getClipsToCacheAtTime(timeUs: TimeUs, maxDuration = 5_000_000): Set<string> {\n const { current, next } = this.getNeighboringClips(timeUs);\n const clipIds = new Set<string>();\n\n if (!current) return clipIds;\n clipIds.add(current);\n\n // Only cache next clip if current clip is short enough\n const currentClip = this.findClip(current);\n if (currentClip && currentClip.durationUs <= maxDuration && next) {\n clipIds.add(next);\n }\n\n return clipIds;\n }\n\n // Resource operations\n getResource(id: string): Resource | null {\n return this.resources.get(id) || null;\n }\n\n updateResourceState(id: string, state: 'pending' | 'loading' | 'ready' | 'error'): void {\n const resource = this.resources.get(id);\n if (resource) {\n resource.state = state;\n }\n }\n\n getUnusedResources(): Resource[] {\n const unused: Resource[] = [];\n\n for (const [id, resource] of this.resources) {\n if (!this.resourceRefCount.has(id) || this.resourceRefCount.get(id) === 0) {\n unused.push(resource);\n }\n }\n\n return unused;\n }\n\n // Time operations\n getDuration(): TimeUs {\n return this.durationUs;\n }\n\n getTrackDuration(trackId: string): TimeUs {\n const track = this.findTrack(trackId);\n if (!track || track.clips.length === 0) return 0;\n\n // Since clips are sorted, last clip determines duration\n const lastClip = track.clips[track.clips.length - 1];\n return (lastClip?.startUs ?? 0) + (lastClip?.durationUs ?? 0);\n }\n\n buildIndexes(options?: {\n incremental?: boolean;\n trackId?: string;\n clipId?: string;\n clip?: Clip;\n operation?: 'add' | 'update' | 'remove';\n }): void {\n const track = options?.trackId ? this.findTrack(options.trackId) : undefined;\n const isAttachmentTrack = track && track.kind !== 'video' && track.kind !== 'audio';\n // Incremental update for video/audio track clip operations\n if (options?.incremental && !isAttachmentTrack && options.clipId && options.operation) {\n const clip = options.clip ?? this.clipMap.get(options.clipId);\n\n if (options.operation === 'add' && clip) {\n this.addClipToIndexes(clip);\n } else if (options.operation === 'remove' && clip) {\n this.removeClipFromIndexes(clip);\n } else if (options.operation === 'update' && clip) {\n // Handle resource change during update\n if (clip.oldResourceId) {\n this.updateClipResourceIndex(\n options.clipId,\n clip.oldResourceId,\n hasResourceId(clip) ? clip.resourceId : undefined\n );\n }\n }\n\n // Recalculate duration only if affected main track\n if (track?.id === this.mainTrackId) {\n this.recalculateDuration();\n }\n return;\n }\n\n // Full rebuild: needed for attachment tracks or initial load\n this.fullRebuildIndexes();\n }\n\n private fullRebuildIndexes(): void {\n // Clear existing indexes\n this.trackMap.clear();\n this.clipMap.clear();\n this.resourceRefCount.clear();\n\n // Step 1: Sink attachment tracks to main track (preserves original tracks)\n this.sinkAttachmentTracks();\n\n let maxEndUs = 0;\n\n // Step 2: Build all indexes in one pass (track, clip, resource)\n for (const track of this.tracks) {\n this.trackMap.set(track.id, track);\n\n for (const clip of track.clips) {\n (clip as Clip).trackId = track.id;\n (clip as Clip).trackKind = track.kind;\n this.clipMap.set(clip.id, clip);\n\n // Main track resource index (only for clips with resourceId)\n if (hasResourceId(clip)) {\n const resource = this.resources.get(clip.resourceId);\n if (resource) {\n resource.clipIds = [...(resource.clipIds || []), clip.id];\n }\n const count = this.resourceRefCount.get(clip.resourceId) || 0;\n this.resourceRefCount.set(clip.resourceId, count + 1);\n }\n\n // Attachment resource indexes (attachments are already sunk)\n const attachments = clip.attachments ?? [];\n for (const attachment of attachments) {\n const attachmentResourceId = attachment.data?.resourceId;\n if (attachmentResourceId && typeof attachmentResourceId === 'string') {\n const attachmentResource = this.resources.get(attachmentResourceId);\n if (attachmentResource) {\n const clipIds = attachmentResource.clipIds || [];\n if (!clipIds.includes(clip.id)) {\n attachmentResource.clipIds = [...clipIds, clip.id];\n }\n }\n const attachmentCount = this.resourceRefCount.get(attachmentResourceId) || 0;\n this.resourceRefCount.set(attachmentResourceId, attachmentCount + 1);\n }\n }\n\n // Calculate max end time\n const clipEndUs = clip.startUs + clip.durationUs;\n if (clipEndUs > maxEndUs) {\n maxEndUs = clipEndUs;\n }\n }\n }\n\n this.durationUs = maxEndUs;\n }\n\n private addClipToIndexes(clip: Clip): void {\n this.clipMap.set(clip.id, clip);\n\n if (hasResourceId(clip)) {\n const resource = this.resources.get(clip.resourceId);\n if (resource) {\n if (!resource.clipIds) {\n resource.clipIds = [];\n }\n if (!resource.clipIds.includes(clip.id)) {\n resource.clipIds.push(clip.id);\n }\n }\n const count = this.resourceRefCount.get(clip.resourceId) || 0;\n this.resourceRefCount.set(clip.resourceId, count + 1);\n }\n }\n\n private removeClipFromIndexes(clip: Clip): void {\n this.clipMap.delete(clip.id);\n\n const resourceId = clip.oldResourceId || (hasResourceId(clip) ? clip.resourceId : undefined);\n if (resourceId) {\n const resource = this.resources.get(resourceId);\n if (resource?.clipIds) {\n resource.clipIds = resource.clipIds.filter((id) => id !== clip.id);\n }\n const count = this.resourceRefCount.get(resourceId) || 0;\n this.resourceRefCount.set(resourceId, Math.max(0, count - 1));\n }\n }\n\n /**\n * Incrementally update resource index when clip's resourceId changes\n */\n updateClipResourceIndex(\n clipId: string,\n oldResourceId: string | undefined,\n newResourceId: string | undefined\n ): void {\n // Remove from old resource\n if (oldResourceId) {\n const oldResource = this.resources.get(oldResourceId);\n if (oldResource?.clipIds) {\n oldResource.clipIds = oldResource.clipIds.filter((id) => id !== clipId);\n }\n const oldCount = this.resourceRefCount.get(oldResourceId) || 0;\n this.resourceRefCount.set(oldResourceId, Math.max(0, oldCount - 1));\n }\n\n // Add to new resource\n if (newResourceId) {\n const newResource = this.resources.get(newResourceId);\n if (newResource) {\n if (!newResource.clipIds) {\n newResource.clipIds = [];\n }\n if (!newResource.clipIds.includes(clipId)) {\n newResource.clipIds.push(clipId);\n }\n }\n const newCount = this.resourceRefCount.get(newResourceId) || 0;\n this.resourceRefCount.set(newResourceId, newCount + 1);\n }\n }\n\n /**\n * Recalculate total duration based on main track\n */\n recalculateDuration(): void {\n const mainTrack = this.findTrack(this.mainTrackId);\n if (!mainTrack || mainTrack.clips.length === 0) {\n this.durationUs = 0;\n return;\n }\n\n // Since clips are sorted, last clip determines duration\n const lastClip = mainTrack.clips[mainTrack.clips.length - 1];\n this.durationUs = (lastClip?.startUs ?? 0) + (lastClip?.durationUs ?? 0);\n }\n\n private sinkAttachmentTracks(): void {\n let mainTrack: Track | undefined;\n const attachmentTracks = [];\n\n // Sort all tracks\n for (const track of this.tracks) {\n track.clips.sort((a, b) => a.startUs - b.startUs);\n\n if (track.id === this.mainTrackId) {\n mainTrack = track;\n continue;\n }\n // Collect attachment tracks for sinking (caption, overlay, fx)\n // Video and audio tracks are not sunk\n if (track.kind === 'caption' || track.kind === 'overlay' || track.kind === 'fx') {\n attachmentTracks.push(track);\n }\n }\n\n if (!mainTrack) {\n throw new Error('Main track not found');\n }\n\n // Clear existing attachments before sinking (in case of rebuild)\n for (const clip of mainTrack.clips) {\n clip.attachments = [];\n }\n\n for (const attachmentTrack of attachmentTracks) {\n for (const attachmentClip of attachmentTrack.clips) {\n // Use track.kind directly as attachment kind\n const attachmentKind = attachmentTrack.kind;\n\n for (const mainClip of mainTrack.clips) {\n const overlap = this.getTimeOverlap(attachmentClip, mainClip);\n if (!overlap) continue;\n\n if (!mainClip.attachments) {\n mainClip.attachments = [];\n }\n\n // Extract animation effect\n const animationEffect = attachmentClip.effects?.find(\n (e) => e.effectType === 'animation'\n ) as AnimationEffect | undefined;\n\n // Extract target dimensions from metadata\n const targetWidth = attachmentClip.metadata?.targetWidth as number | undefined;\n const targetHeight = attachmentClip.metadata?.targetHeight as number | undefined;\n\n const attachmentData: Record<string, unknown> = {\n animation: animationEffect?.params,\n overlayClipStartUs: attachmentClip.startUs,\n mainClipStartUs: mainClip.startUs,\n ...(targetWidth !== undefined && { targetWidth }),\n ...(targetHeight !== undefined && { targetHeight }),\n };\n\n // Add resourceId if exists (trackKind not yet set, check field directly)\n if ('resourceId' in attachmentClip && attachmentClip.resourceId) {\n attachmentData.resourceId = attachmentClip.resourceId;\n }\n\n // Add text if exists (trackKind not yet set, check field directly)\n if ('text' in attachmentClip && attachmentClip.text) {\n attachmentData.text = attachmentClip.text;\n }\n\n mainClip.attachments.push({\n id: `${attachmentKind}-${attachmentClip.id}-${mainClip.id}`,\n kind: attachmentKind,\n startUs: overlap.clipRelativeStart,\n durationUs: overlap.duration,\n data: attachmentData,\n });\n }\n }\n }\n }\n\n private getTimeOverlap(\n attachmentClip: Clip,\n mainClip: Clip\n ): { clipRelativeStart: number; duration: number } | null {\n const attachmentStart = attachmentClip.startUs;\n const attachmentEnd = attachmentClip.startUs + attachmentClip.durationUs;\n const mainStart = mainClip.startUs;\n const mainEnd = mainClip.startUs + mainClip.durationUs;\n\n if (attachmentEnd <= mainStart || attachmentStart >= mainEnd) {\n return null;\n }\n\n const overlapStart = Math.max(attachmentStart, mainStart);\n const overlapEnd = Math.min(attachmentEnd, mainEnd);\n const duration = overlapEnd - overlapStart;\n const clipRelativeStart = overlapStart - mainStart;\n\n return { clipRelativeStart, duration };\n }\n}\n"],"names":[],"mappings":"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"}
|
package/dist/model/patch.js
CHANGED
|
@@ -164,74 +164,30 @@ function updateTrack(model, op) {
|
|
|
164
164
|
function addClip(model, op) {
|
|
165
165
|
const track = model.findTrack(op.trackId);
|
|
166
166
|
if (!track || !op.clip) return;
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
resourceId: partialClip.resourceId,
|
|
174
|
-
startUs: op.clip.startUs,
|
|
175
|
-
durationUs: op.clip.durationUs,
|
|
176
|
-
trimStartUs: op.clip.trimStartUs,
|
|
177
|
-
trimEndUs: op.clip.trimEndUs,
|
|
178
|
-
effects: op.clip.effects,
|
|
179
|
-
attachments: op.clip.attachments,
|
|
180
|
-
transitionIn: op.clip.transitionIn,
|
|
181
|
-
transitionOut: op.clip.transitionOut,
|
|
182
|
-
metadata: op.clip.metadata
|
|
183
|
-
};
|
|
184
|
-
} else if (track.kind === "audio") {
|
|
185
|
-
newClip = {
|
|
186
|
-
id: op.clip.id || `clip_${Date.now()}`,
|
|
187
|
-
trackKind: "audio",
|
|
188
|
-
resourceId: partialClip.resourceId,
|
|
189
|
-
startUs: op.clip.startUs,
|
|
190
|
-
durationUs: op.clip.durationUs,
|
|
191
|
-
trimStartUs: op.clip.trimStartUs,
|
|
192
|
-
trimEndUs: op.clip.trimEndUs,
|
|
193
|
-
effects: op.clip.effects,
|
|
194
|
-
attachments: op.clip.attachments,
|
|
195
|
-
transitionIn: op.clip.transitionIn,
|
|
196
|
-
transitionOut: op.clip.transitionOut,
|
|
197
|
-
metadata: op.clip.metadata
|
|
198
|
-
};
|
|
199
|
-
} else if (track.kind === "caption") {
|
|
200
|
-
newClip = {
|
|
201
|
-
id: op.clip.id || `clip_${Date.now()}`,
|
|
202
|
-
trackKind: "caption",
|
|
203
|
-
text: partialClip.text || "",
|
|
204
|
-
startUs: op.clip.startUs,
|
|
205
|
-
durationUs: op.clip.durationUs,
|
|
206
|
-
effects: op.clip.effects,
|
|
207
|
-
attachments: op.clip.attachments,
|
|
208
|
-
transitionIn: op.clip.transitionIn,
|
|
209
|
-
transitionOut: op.clip.transitionOut,
|
|
210
|
-
metadata: op.clip.metadata
|
|
211
|
-
};
|
|
212
|
-
} else {
|
|
213
|
-
newClip = {
|
|
214
|
-
id: op.clip.id || `clip_${Date.now()}`,
|
|
215
|
-
trackKind: "fx",
|
|
216
|
-
startUs: op.clip.startUs,
|
|
217
|
-
durationUs: op.clip.durationUs,
|
|
218
|
-
effects: op.clip.effects,
|
|
219
|
-
attachments: op.clip.attachments,
|
|
220
|
-
transitionIn: op.clip.transitionIn,
|
|
221
|
-
transitionOut: op.clip.transitionOut,
|
|
222
|
-
metadata: op.clip.metadata
|
|
223
|
-
};
|
|
224
|
-
}
|
|
167
|
+
const newClip = {
|
|
168
|
+
id: op.clip.id || `clip_${Date.now()}`,
|
|
169
|
+
trackId: track.id,
|
|
170
|
+
trackKind: track.kind,
|
|
171
|
+
...op.clip
|
|
172
|
+
};
|
|
225
173
|
const insertIndex = track.clips.findIndex((c) => c.startUs > newClip.startUs);
|
|
226
174
|
if (insertIndex === -1) {
|
|
227
175
|
track.clips.push(newClip);
|
|
228
176
|
} else {
|
|
229
|
-
track.clips.splice(insertIndex, 0, newClip);
|
|
177
|
+
track.clips.splice(insertIndex - 1, 0, newClip);
|
|
178
|
+
}
|
|
179
|
+
const insertedStartUs = newClip.startUs;
|
|
180
|
+
const insertedDurationUs = newClip.durationUs;
|
|
181
|
+
for (const clip of track.clips) {
|
|
182
|
+
if (clip.startUs >= insertedStartUs && clip.id !== newClip.id) {
|
|
183
|
+
clip.startUs += insertedDurationUs;
|
|
184
|
+
}
|
|
230
185
|
}
|
|
231
186
|
model.buildIndexes({
|
|
232
187
|
incremental: true,
|
|
233
188
|
trackId: op.trackId,
|
|
234
189
|
clipId: newClip.id,
|
|
190
|
+
clip: newClip,
|
|
235
191
|
operation: "add"
|
|
236
192
|
});
|
|
237
193
|
}
|
|
@@ -242,7 +198,14 @@ function removeClip(model, op) {
|
|
|
242
198
|
if (clipIndex === -1) return;
|
|
243
199
|
const removedClip = track.clips[clipIndex];
|
|
244
200
|
if (!removedClip) return;
|
|
201
|
+
const removedStartUs = removedClip.startUs;
|
|
202
|
+
const removedDurationUs = removedClip.durationUs;
|
|
245
203
|
track.clips.splice(clipIndex, 1);
|
|
204
|
+
for (const clip of track.clips) {
|
|
205
|
+
if (clip.startUs > removedStartUs) {
|
|
206
|
+
clip.startUs = Math.max(0, clip.startUs - removedDurationUs);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
246
209
|
model.buildIndexes({
|
|
247
210
|
incremental: true,
|
|
248
211
|
trackId: op.trackId,
|
package/dist/model/patch.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"patch.js","sources":["../../src/model/patch.ts"],"sourcesContent":["import { CompositionModel } from './CompositionModel';\nimport {\n CompositionPatch,\n PatchOperation,\n TrackOperation,\n ClipOperation,\n ResourceOperation,\n AttachmentOperation,\n TransitionOperation,\n EffectOperation,\n hasResourceId,\n Track,\n Clip,\n Resource,\n Attachment,\n Transition,\n Effect,\n} from './types';\n\n/**\n * Apply patch to model and return affected clip IDs\n * Simplified for 2-Clip strategy - no complex time range calculation needed\n */\nexport function applyPatch(model: CompositionModel, patch: CompositionPatch): Set<string> {\n const affectedClips = new Set<string>();\n\n // Apply all operations and collect affected clips\n for (const op of patch.operations) {\n applyOperation(model, op);\n collectAffectedClips(model, op, affectedClips);\n }\n return affectedClips;\n}\n\n/**\n * Collect clips affected by a patch operation\n */\nfunction collectAffectedClips(\n model: CompositionModel,\n op: PatchOperation,\n affectedClips: Set<string>\n): void {\n switch (op.type) {\n // Track operations affect all clips in track\n case 'addTrack':\n case 'removeTrack':\n case 'updateTrack': {\n const trackOp = op as TrackOperation;\n\n // For track operations, mark main track clips as affected\n // because attachment tracks (caption/fx/overlay) are sunk into main track clips\n // Orchestrator will rebuild indexes to resync attachments after patch\n const mainTrack = model.tracks.find((t) => t.id === model.mainTrackId);\n if (mainTrack) {\n mainTrack.clips.forEach((clip) => affectedClips.add(clip.id));\n }\n\n // Also mark clips in the operated track itself\n if (trackOp.trackId) {\n const track = model.findTrack(trackOp.trackId);\n if (track) {\n track.clips.forEach((clip) => affectedClips.add(clip.id));\n }\n }\n break;\n }\n\n // Clip operations\n case 'addClip':\n case 'removeClip':\n case 'updateClip': {\n const clipOp = op as ClipOperation;\n if (clipOp.clipId) {\n affectedClips.add(clipOp.clipId);\n }\n break;\n }\n\n // moveClip: Only affects cache if cross-track with different effects\n // case 'moveClip': {\n // const clipOp = op as ClipOperation;\n // if (!clipOp.clipId || !clipOp.trackId || !clipOp.targetTrackId) break;\n\n // // Same track: only position change, no re-render needed\n // if (clipOp.trackId === clipOp.targetTrackId) {\n // break;\n // }\n\n // // Cross-track: check if tracks have different effects\n // const sourceTrack = model.findTrack(clipOp.trackId);\n // const targetTrack = model.findTrack(clipOp.targetTrackId);\n\n // // If either track has effects, conservative: re-render\n // const hasEffectsDiff =\n // (sourceTrack?.effects && sourceTrack.effects.length > 0) ||\n // (targetTrack?.effects && targetTrack.effects.length > 0);\n\n // if (hasEffectsDiff) {\n // affectedClips.add(clipOp.clipId);\n // }\n // // Otherwise: no re-render, just position change\n // break;\n // }\n\n // addResource doesn't affect existing clips\n case 'addResource': {\n // New resource doesn't affect existing clips\n // If updateClip is in the same patch, it will be handled by updateClip operation\n break;\n }\n\n // Resource changes affect all clips using that resource\n case 'updateResource':\n case 'removeResource': {\n const resourceOp = op as ResourceOperation;\n if (resourceOp.resourceId) {\n for (const track of model.tracks) {\n for (const clip of track.clips) {\n if (hasResourceId(clip) && clip.resourceId === resourceOp.resourceId) {\n affectedClips.add(clip.id);\n }\n }\n }\n }\n break;\n }\n\n // Attachment operations\n case 'addAttachment':\n case 'updateAttachment':\n case 'removeAttachment': {\n const attachmentOp = op as AttachmentOperation;\n if (attachmentOp.clipId) {\n affectedClips.add(attachmentOp.clipId);\n }\n break;\n }\n\n // Transition operations\n case 'addTransition':\n case 'updateTransition':\n case 'removeTransition': {\n const transitionOp = op as TransitionOperation;\n if (transitionOp.clipId) {\n affectedClips.add(transitionOp.clipId);\n }\n break;\n }\n\n // Effect operations\n case 'addEffect':\n case 'updateEffect':\n case 'removeEffect': {\n const effectOp = op as EffectOperation;\n if (effectOp.targetType === 'track' && effectOp.targetId) {\n const track = model.findTrack(effectOp.targetId);\n if (track) {\n track.clips.forEach((clip) => affectedClips.add(clip.id));\n }\n } else if (effectOp.targetType === 'clip' && effectOp.targetId) {\n affectedClips.add(effectOp.targetId);\n }\n break;\n }\n }\n}\n\nfunction applyOperation(model: CompositionModel, op: PatchOperation): void {\n switch (op.type) {\n // Track operations\n case 'addTrack':\n addTrack(model, op as TrackOperation);\n break;\n case 'removeTrack':\n removeTrack(model, op as TrackOperation);\n break;\n case 'updateTrack':\n updateTrack(model, op as TrackOperation);\n break;\n\n // Clip operations\n case 'addClip':\n addClip(model, op as ClipOperation);\n break;\n case 'removeClip':\n removeClip(model, op as ClipOperation);\n break;\n case 'updateClip':\n updateClip(model, op as ClipOperation);\n break;\n // case 'moveClip':\n // moveClip(model, op as ClipOperation);\n // break;\n\n // Resource operations\n case 'addResource':\n addResource(model, op as ResourceOperation);\n break;\n case 'updateResource':\n updateResource(model, op as ResourceOperation);\n break;\n case 'removeResource':\n removeResource(model, op as ResourceOperation);\n break;\n\n // Attachment operations\n case 'addAttachment':\n addAttachment(model, op as AttachmentOperation);\n break;\n case 'updateAttachment':\n updateAttachment(model, op as AttachmentOperation);\n break;\n case 'removeAttachment':\n removeAttachment(model, op as AttachmentOperation);\n break;\n\n // Transition operations\n case 'addTransition':\n case 'updateTransition':\n case 'removeTransition':\n handleTransition(model, op as TransitionOperation);\n break;\n\n // Effect operations\n case 'addEffect':\n case 'updateEffect':\n case 'removeEffect':\n handleEffect(model, op as EffectOperation);\n break;\n\n default:\n break;\n }\n}\n\n// Track operations\nfunction addTrack(model: CompositionModel, op: TrackOperation): void {\n if (!op.track) return;\n\n const newTrack: Track = {\n id: op.track.id || `track_${Date.now()}`,\n kind: op.track.kind || 'video',\n clips: op.track.clips || [],\n effects: op.track.effects,\n duckingRules: op.track.duckingRules,\n };\n\n model.tracks.push(newTrack);\n model.buildIndexes();\n}\n\nfunction removeTrack(model: CompositionModel, op: TrackOperation): void {\n if (!op.trackId) return;\n\n const index = model.tracks.findIndex((t) => t.id === op.trackId);\n if (index === -1) return;\n\n model.tracks.splice(index, 1);\n model.buildIndexes();\n}\n\nfunction updateTrack(model: CompositionModel, op: TrackOperation): void {\n if (!op.trackId || !op.track) return;\n\n const track = model.findTrack(op.trackId);\n if (!track) return;\n\n Object.assign(track, op.track);\n model.buildIndexes();\n}\n\n// Clip operations\nfunction addClip(model: CompositionModel, op: ClipOperation): void {\n const track = model.findTrack(op.trackId);\n if (!track || !op.clip) return;\n\n let newClip: Clip;\n\n // Create clip based on track kind\n const partialClip = op.clip as any;\n if (track.kind === 'video') {\n newClip = {\n id: op.clip.id || `clip_${Date.now()}`,\n trackKind: 'video',\n resourceId: partialClip.resourceId!,\n startUs: op.clip.startUs!,\n durationUs: op.clip.durationUs!,\n trimStartUs: op.clip.trimStartUs,\n trimEndUs: op.clip.trimEndUs,\n effects: op.clip.effects,\n attachments: op.clip.attachments,\n transitionIn: op.clip.transitionIn,\n transitionOut: op.clip.transitionOut,\n metadata: op.clip.metadata,\n };\n } else if (track.kind === 'audio') {\n newClip = {\n id: op.clip.id || `clip_${Date.now()}`,\n trackKind: 'audio',\n resourceId: partialClip.resourceId!,\n startUs: op.clip.startUs!,\n durationUs: op.clip.durationUs!,\n trimStartUs: op.clip.trimStartUs,\n trimEndUs: op.clip.trimEndUs,\n effects: op.clip.effects,\n attachments: op.clip.attachments,\n transitionIn: op.clip.transitionIn,\n transitionOut: op.clip.transitionOut,\n metadata: op.clip.metadata,\n };\n } else if (track.kind === 'caption') {\n newClip = {\n id: op.clip.id || `clip_${Date.now()}`,\n trackKind: 'caption',\n text: partialClip.text || '',\n startUs: op.clip.startUs!,\n durationUs: op.clip.durationUs!,\n effects: op.clip.effects,\n attachments: op.clip.attachments,\n transitionIn: op.clip.transitionIn,\n transitionOut: op.clip.transitionOut,\n metadata: op.clip.metadata,\n };\n } else {\n // fx clip\n newClip = {\n id: op.clip.id || `clip_${Date.now()}`,\n trackKind: 'fx',\n startUs: op.clip.startUs!,\n durationUs: op.clip.durationUs!,\n effects: op.clip.effects,\n attachments: op.clip.attachments,\n transitionIn: op.clip.transitionIn,\n transitionOut: op.clip.transitionOut,\n metadata: op.clip.metadata,\n };\n }\n\n // Insert clip in sorted position\n const insertIndex = track.clips.findIndex((c) => c.startUs > newClip.startUs);\n if (insertIndex === -1) {\n track.clips.push(newClip);\n } else {\n track.clips.splice(insertIndex, 0, newClip);\n }\n\n model.buildIndexes({\n incremental: true,\n trackId: op.trackId,\n clipId: newClip.id,\n operation: 'add',\n });\n}\n\nfunction removeClip(model: CompositionModel, op: ClipOperation): void {\n const track = model.findTrack(op.trackId);\n if (!track || !op.clipId) return;\n\n const clipIndex = track.clips.findIndex((c) => c.id === op.clipId);\n if (clipIndex === -1) return;\n\n const removedClip = track.clips[clipIndex];\n if (!removedClip) return;\n\n track.clips.splice(clipIndex, 1);\n\n model.buildIndexes({\n incremental: true,\n trackId: op.trackId,\n clipId: op.clipId,\n operation: 'remove',\n });\n}\n\nfunction updateClip(model: CompositionModel, op: ClipOperation): void {\n const clip = model.findClip(op.clipId!);\n if (!clip || !op.clip) return;\n\n // Save old resourceId before update (for resource switching)\n const oldResourceId = hasResourceId(clip) ? clip.resourceId : undefined;\n const track = model.findTrack(op.trackId);\n\n Object.assign(clip, op.clip);\n\n // Mark old resourceId for cleanup\n const newResourceId = 'resourceId' in op.clip ? op.clip.resourceId : undefined;\n if (newResourceId !== undefined && newResourceId !== oldResourceId) {\n clip.oldResourceId = oldResourceId;\n }\n\n // Re-sort if startUs changed\n if (op.clip.startUs !== undefined) {\n if (track) {\n track.clips.sort((a, b) => a.startUs - b.startUs);\n }\n }\n\n model.buildIndexes({\n incremental: true,\n trackId: op.trackId,\n clipId: op.clipId,\n operation: 'update',\n });\n}\n\n// function moveClip(model: CompositionModel, op: ClipOperation): void {\n// if (!op.clipId || !op.targetTrackId) return;\n\n// const sourceTrack = model.findTrack(op.trackId);\n// const targetTrack = model.findTrack(op.targetTrackId);\n// const clip = model.findClip(op.clipId);\n\n// if (!sourceTrack || !targetTrack || !clip) return;\n\n// // Remove from source track\n// const clipIndex = sourceTrack.clips.findIndex((c) => c.id === op.clipId);\n// if (clipIndex === -1) return;\n\n// sourceTrack.clips.splice(clipIndex, 1);\n\n// // Update position if specified\n// if (op.targetStartUs !== undefined) {\n// clip.startUs = op.targetStartUs;\n// }\n\n// // Update trackId if cross-track move\n// if (op.targetTrackId !== op.trackId) {\n// clip.trackId = op.targetTrackId;\n// }\n\n// // Add to target track in sorted position\n// const insertIndex = targetTrack.clips.findIndex((c) => c.startUs > clip.startUs);\n// if (insertIndex === -1) {\n// targetTrack.clips.push(clip);\n// } else {\n// targetTrack.clips.splice(insertIndex, 0, clip);\n// }\n\n// rebuildIndexes(model);\n// }\n\n// Resource operations\nfunction addResource(model: CompositionModel, op: ResourceOperation): void {\n if (!op.resource) return;\n\n const newResource: Resource = {\n id: op.resourceId,\n type: op.resource.type!,\n uri: op.resource.uri!,\n metadata: op.resource.metadata,\n state: op.resource.state || 'pending',\n };\n\n model.resources.set(op.resourceId, newResource);\n}\n\nfunction updateResource(model: CompositionModel, op: ResourceOperation): void {\n const resource = model.getResource(op.resourceId);\n if (!resource || !op.resource) return;\n\n Object.assign(resource, op.resource);\n}\n\nfunction removeResource(model: CompositionModel, op: ResourceOperation): void {\n if (!model.resources.has(op.resourceId)) return;\n\n model.resources.delete(op.resourceId);\n}\n\n// Attachment operations\nfunction addAttachment(model: CompositionModel, op: AttachmentOperation): void {\n const clip = model.findClip(op.clipId);\n if (!clip || !op.attachment) return;\n\n if (!clip.attachments) {\n clip.attachments = [];\n }\n\n const newAttachment: Attachment = {\n id: op.attachment.id || `attachment_${Date.now()}`,\n kind: op.attachment.kind!,\n startUs: op.attachment.startUs!,\n durationUs: op.attachment.durationUs!,\n data: op.attachment.data!,\n };\n\n clip.attachments.push(newAttachment);\n}\n\nfunction updateAttachment(model: CompositionModel, op: AttachmentOperation): void {\n const clip = model.findClip(op.clipId);\n if (!clip || !clip.attachments || !op.attachmentId || !op.attachment) return;\n\n const attachment = clip.attachments.find((a) => a.id === op.attachmentId);\n if (!attachment) return;\n\n Object.assign(attachment, op.attachment);\n}\n\nfunction removeAttachment(model: CompositionModel, op: AttachmentOperation): void {\n const clip = model.findClip(op.clipId);\n if (!clip || !clip.attachments || !op.attachmentId) return;\n\n const attachmentIndex = clip.attachments.findIndex((a) => a.id === op.attachmentId);\n if (attachmentIndex === -1) return;\n\n clip.attachments.splice(attachmentIndex, 1);\n}\n\n// Transition operations\nfunction handleTransition(model: CompositionModel, op: TransitionOperation): void {\n const clip = model.findClip(op.clipId);\n if (!clip) return;\n\n if (op.position === 'in') {\n if (op.type === 'removeTransition') {\n clip.transitionIn = undefined;\n } else {\n clip.transitionIn = op.transition as Transition;\n }\n } else {\n if (op.type === 'removeTransition') {\n clip.transitionOut = undefined;\n } else {\n clip.transitionOut = op.transition as Transition;\n }\n }\n}\n\n// Effect operations\nfunction handleEffect(model: CompositionModel, op: EffectOperation): void {\n if (op.targetType === 'track') {\n const track = model.findTrack(op.targetId);\n if (!track) return;\n\n if (!track.effects) track.effects = [];\n\n if (op.type === 'addEffect' && op.effect) {\n track.effects.push(op.effect as Effect);\n } else if (op.type === 'removeEffect' && op.effectId) {\n const index = track.effects.findIndex((e) => e.id === op.effectId);\n if (index !== -1) track.effects.splice(index, 1);\n } else if (op.type === 'updateEffect' && op.effectId && op.effect) {\n const effect = track.effects.find((e) => e.id === op.effectId);\n if (effect) Object.assign(effect, op.effect);\n }\n } else {\n const clip = model.findClip(op.targetId);\n if (!clip) return;\n\n if (!clip.effects) clip.effects = [];\n\n if (op.type === 'addEffect' && op.effect) {\n clip.effects.push(op.effect as Effect);\n } else if (op.type === 'removeEffect' && op.effectId) {\n const index = clip.effects.findIndex((e) => e.id === op.effectId);\n if (index !== -1) clip.effects.splice(index, 1);\n } else if (op.type === 'updateEffect' && op.effectId && op.effect) {\n const effect = clip.effects.find((e) => e.id === op.effectId);\n if (effect) Object.assign(effect, op.effect);\n }\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"patch.js","sources":["../../src/model/patch.ts"],"sourcesContent":["import { CompositionModel } from './CompositionModel';\nimport {\n CompositionPatch,\n PatchOperation,\n TrackOperation,\n ClipOperation,\n ResourceOperation,\n AttachmentOperation,\n TransitionOperation,\n EffectOperation,\n hasResourceId,\n Track,\n Clip,\n Resource,\n Attachment,\n Transition,\n Effect,\n} from './types';\n\n/**\n * Apply patch to model and return affected clip IDs\n * Simplified for 2-Clip strategy - no complex time range calculation needed\n */\nexport function applyPatch(model: CompositionModel, patch: CompositionPatch): Set<string> {\n const affectedClips = new Set<string>();\n\n // Apply all operations and collect affected clips\n for (const op of patch.operations) {\n applyOperation(model, op);\n collectAffectedClips(model, op, affectedClips);\n }\n return affectedClips;\n}\n\n/**\n * Collect clips affected by a patch operation\n */\nfunction collectAffectedClips(\n model: CompositionModel,\n op: PatchOperation,\n affectedClips: Set<string>\n): void {\n switch (op.type) {\n // Track operations affect all clips in track\n case 'addTrack':\n case 'removeTrack':\n case 'updateTrack': {\n const trackOp = op as TrackOperation;\n\n // For track operations, mark main track clips as affected\n // because attachment tracks (caption/fx/overlay) are sunk into main track clips\n // Orchestrator will rebuild indexes to resync attachments after patch\n const mainTrack = model.tracks.find((t) => t.id === model.mainTrackId);\n if (mainTrack) {\n mainTrack.clips.forEach((clip) => affectedClips.add(clip.id));\n }\n\n // Also mark clips in the operated track itself\n if (trackOp.trackId) {\n const track = model.findTrack(trackOp.trackId);\n if (track) {\n track.clips.forEach((clip) => affectedClips.add(clip.id));\n }\n }\n break;\n }\n\n // Clip operations\n case 'addClip':\n case 'removeClip':\n case 'updateClip': {\n const clipOp = op as ClipOperation;\n if (clipOp.clipId) {\n affectedClips.add(clipOp.clipId);\n }\n break;\n }\n\n // moveClip: Only affects cache if cross-track with different effects\n // case 'moveClip': {\n // const clipOp = op as ClipOperation;\n // if (!clipOp.clipId || !clipOp.trackId || !clipOp.targetTrackId) break;\n\n // // Same track: only position change, no re-render needed\n // if (clipOp.trackId === clipOp.targetTrackId) {\n // break;\n // }\n\n // // Cross-track: check if tracks have different effects\n // const sourceTrack = model.findTrack(clipOp.trackId);\n // const targetTrack = model.findTrack(clipOp.targetTrackId);\n\n // // If either track has effects, conservative: re-render\n // const hasEffectsDiff =\n // (sourceTrack?.effects && sourceTrack.effects.length > 0) ||\n // (targetTrack?.effects && targetTrack.effects.length > 0);\n\n // if (hasEffectsDiff) {\n // affectedClips.add(clipOp.clipId);\n // }\n // // Otherwise: no re-render, just position change\n // break;\n // }\n\n // addResource doesn't affect existing clips\n case 'addResource': {\n // New resource doesn't affect existing clips\n // If updateClip is in the same patch, it will be handled by updateClip operation\n break;\n }\n\n // Resource changes affect all clips using that resource\n case 'updateResource':\n case 'removeResource': {\n const resourceOp = op as ResourceOperation;\n if (resourceOp.resourceId) {\n for (const track of model.tracks) {\n for (const clip of track.clips) {\n if (hasResourceId(clip) && clip.resourceId === resourceOp.resourceId) {\n affectedClips.add(clip.id);\n }\n }\n }\n }\n break;\n }\n\n // Attachment operations\n case 'addAttachment':\n case 'updateAttachment':\n case 'removeAttachment': {\n const attachmentOp = op as AttachmentOperation;\n if (attachmentOp.clipId) {\n affectedClips.add(attachmentOp.clipId);\n }\n break;\n }\n\n // Transition operations\n case 'addTransition':\n case 'updateTransition':\n case 'removeTransition': {\n const transitionOp = op as TransitionOperation;\n if (transitionOp.clipId) {\n affectedClips.add(transitionOp.clipId);\n }\n break;\n }\n\n // Effect operations\n case 'addEffect':\n case 'updateEffect':\n case 'removeEffect': {\n const effectOp = op as EffectOperation;\n if (effectOp.targetType === 'track' && effectOp.targetId) {\n const track = model.findTrack(effectOp.targetId);\n if (track) {\n track.clips.forEach((clip) => affectedClips.add(clip.id));\n }\n } else if (effectOp.targetType === 'clip' && effectOp.targetId) {\n affectedClips.add(effectOp.targetId);\n }\n break;\n }\n }\n}\n\nfunction applyOperation(model: CompositionModel, op: PatchOperation): void {\n switch (op.type) {\n // Track operations\n case 'addTrack':\n addTrack(model, op as TrackOperation);\n break;\n case 'removeTrack':\n removeTrack(model, op as TrackOperation);\n break;\n case 'updateTrack':\n updateTrack(model, op as TrackOperation);\n break;\n\n // Clip operations\n case 'addClip':\n addClip(model, op as ClipOperation);\n break;\n case 'removeClip':\n removeClip(model, op as ClipOperation);\n break;\n case 'updateClip':\n updateClip(model, op as ClipOperation);\n break;\n // case 'moveClip':\n // moveClip(model, op as ClipOperation);\n // break;\n\n // Resource operations\n case 'addResource':\n addResource(model, op as ResourceOperation);\n break;\n case 'updateResource':\n updateResource(model, op as ResourceOperation);\n break;\n case 'removeResource':\n removeResource(model, op as ResourceOperation);\n break;\n\n // Attachment operations\n case 'addAttachment':\n addAttachment(model, op as AttachmentOperation);\n break;\n case 'updateAttachment':\n updateAttachment(model, op as AttachmentOperation);\n break;\n case 'removeAttachment':\n removeAttachment(model, op as AttachmentOperation);\n break;\n\n // Transition operations\n case 'addTransition':\n case 'updateTransition':\n case 'removeTransition':\n handleTransition(model, op as TransitionOperation);\n break;\n\n // Effect operations\n case 'addEffect':\n case 'updateEffect':\n case 'removeEffect':\n handleEffect(model, op as EffectOperation);\n break;\n\n default:\n break;\n }\n}\n\n// Track operations\nfunction addTrack(model: CompositionModel, op: TrackOperation): void {\n if (!op.track) return;\n\n const newTrack: Track = {\n id: op.track.id || `track_${Date.now()}`,\n kind: op.track.kind || 'video',\n clips: op.track.clips || [],\n effects: op.track.effects,\n duckingRules: op.track.duckingRules,\n };\n\n model.tracks.push(newTrack);\n model.buildIndexes();\n}\n\nfunction removeTrack(model: CompositionModel, op: TrackOperation): void {\n if (!op.trackId) return;\n\n const index = model.tracks.findIndex((t) => t.id === op.trackId);\n if (index === -1) return;\n\n model.tracks.splice(index, 1);\n model.buildIndexes();\n}\n\nfunction updateTrack(model: CompositionModel, op: TrackOperation): void {\n if (!op.trackId || !op.track) return;\n\n const track = model.findTrack(op.trackId);\n if (!track) return;\n\n Object.assign(track, op.track);\n model.buildIndexes();\n}\n\n// Clip operations\nfunction addClip(model: CompositionModel, op: ClipOperation): void {\n const track = model.findTrack(op.trackId);\n if (!track || !op.clip) return;\n\n // Create clip based on track kind\n const newClip = {\n id: op.clip.id || `clip_${Date.now()}`,\n trackId: track.id,\n trackKind: track.kind,\n ...op.clip,\n } as Clip;\n\n // Insert clip in sorted position\n const insertIndex = track.clips.findIndex((c) => c.startUs > newClip.startUs);\n if (insertIndex === -1) {\n track.clips.push(newClip);\n } else {\n track.clips.splice(insertIndex - 1, 0, newClip);\n }\n\n // Single loop: find new clip and adjust subsequent clips\n const insertedStartUs = newClip.startUs;\n const insertedDurationUs = newClip.durationUs;\n\n for (const clip of track.clips) {\n if (clip.startUs >= insertedStartUs && clip.id !== newClip.id) {\n // Push back clips that start at or after the insertion point\n clip.startUs += insertedDurationUs;\n }\n }\n\n model.buildIndexes({\n incremental: true,\n trackId: op.trackId,\n clipId: newClip.id,\n clip: newClip,\n operation: 'add',\n });\n}\n\nfunction removeClip(model: CompositionModel, op: ClipOperation): void {\n const track = model.findTrack(op.trackId);\n if (!track || !op.clipId) return;\n\n const clipIndex = track.clips.findIndex((c) => c.id === op.clipId);\n if (clipIndex === -1) return;\n\n const removedClip = track.clips[clipIndex];\n if (!removedClip) return;\n\n const removedStartUs = removedClip.startUs;\n const removedDurationUs = removedClip.durationUs;\n\n track.clips.splice(clipIndex, 1);\n\n // Auto-adjust subsequent clips: move forward clips after the removed clip\n for (const clip of track.clips) {\n if (clip.startUs > removedStartUs) {\n clip.startUs = Math.max(0, clip.startUs - removedDurationUs);\n }\n }\n\n model.buildIndexes({\n incremental: true,\n trackId: op.trackId,\n clipId: op.clipId,\n operation: 'remove',\n });\n}\n\nfunction updateClip(model: CompositionModel, op: ClipOperation): void {\n const clip = model.findClip(op.clipId!);\n if (!clip || !op.clip) return;\n\n // Save old resourceId before update (for resource switching)\n const oldResourceId = hasResourceId(clip) ? clip.resourceId : undefined;\n const track = model.findTrack(op.trackId);\n\n Object.assign(clip, op.clip);\n\n // Mark old resourceId for cleanup\n const newResourceId = 'resourceId' in op.clip ? op.clip.resourceId : undefined;\n if (newResourceId !== undefined && newResourceId !== oldResourceId) {\n clip.oldResourceId = oldResourceId;\n }\n\n // Re-sort if startUs changed\n if (op.clip.startUs !== undefined) {\n if (track) {\n track.clips.sort((a, b) => a.startUs - b.startUs);\n }\n }\n\n model.buildIndexes({\n incremental: true,\n trackId: op.trackId,\n clipId: op.clipId,\n operation: 'update',\n });\n}\n\n// function moveClip(model: CompositionModel, op: ClipOperation): void {\n// if (!op.clipId || !op.targetTrackId) return;\n\n// const sourceTrack = model.findTrack(op.trackId);\n// const targetTrack = model.findTrack(op.targetTrackId);\n// const clip = model.findClip(op.clipId);\n\n// if (!sourceTrack || !targetTrack || !clip) return;\n\n// // Remove from source track\n// const clipIndex = sourceTrack.clips.findIndex((c) => c.id === op.clipId);\n// if (clipIndex === -1) return;\n\n// sourceTrack.clips.splice(clipIndex, 1);\n\n// // Update position if specified\n// if (op.targetStartUs !== undefined) {\n// clip.startUs = op.targetStartUs;\n// }\n\n// // Update trackId if cross-track move\n// if (op.targetTrackId !== op.trackId) {\n// clip.trackId = op.targetTrackId;\n// }\n\n// // Add to target track in sorted position\n// const insertIndex = targetTrack.clips.findIndex((c) => c.startUs > clip.startUs);\n// if (insertIndex === -1) {\n// targetTrack.clips.push(clip);\n// } else {\n// targetTrack.clips.splice(insertIndex, 0, clip);\n// }\n\n// rebuildIndexes(model);\n// }\n\n// Resource operations\nfunction addResource(model: CompositionModel, op: ResourceOperation): void {\n if (!op.resource) return;\n\n const newResource: Resource = {\n id: op.resourceId,\n type: op.resource.type!,\n uri: op.resource.uri!,\n metadata: op.resource.metadata,\n state: op.resource.state || 'pending',\n };\n\n model.resources.set(op.resourceId, newResource);\n}\n\nfunction updateResource(model: CompositionModel, op: ResourceOperation): void {\n const resource = model.getResource(op.resourceId);\n if (!resource || !op.resource) return;\n\n Object.assign(resource, op.resource);\n}\n\nfunction removeResource(model: CompositionModel, op: ResourceOperation): void {\n if (!model.resources.has(op.resourceId)) return;\n\n model.resources.delete(op.resourceId);\n}\n\n// Attachment operations\nfunction addAttachment(model: CompositionModel, op: AttachmentOperation): void {\n const clip = model.findClip(op.clipId);\n if (!clip || !op.attachment) return;\n\n if (!clip.attachments) {\n clip.attachments = [];\n }\n\n const newAttachment: Attachment = {\n id: op.attachment.id || `attachment_${Date.now()}`,\n kind: op.attachment.kind!,\n startUs: op.attachment.startUs!,\n durationUs: op.attachment.durationUs!,\n data: op.attachment.data!,\n };\n\n clip.attachments.push(newAttachment);\n}\n\nfunction updateAttachment(model: CompositionModel, op: AttachmentOperation): void {\n const clip = model.findClip(op.clipId);\n if (!clip || !clip.attachments || !op.attachmentId || !op.attachment) return;\n\n const attachment = clip.attachments.find((a) => a.id === op.attachmentId);\n if (!attachment) return;\n\n Object.assign(attachment, op.attachment);\n}\n\nfunction removeAttachment(model: CompositionModel, op: AttachmentOperation): void {\n const clip = model.findClip(op.clipId);\n if (!clip || !clip.attachments || !op.attachmentId) return;\n\n const attachmentIndex = clip.attachments.findIndex((a) => a.id === op.attachmentId);\n if (attachmentIndex === -1) return;\n\n clip.attachments.splice(attachmentIndex, 1);\n}\n\n// Transition operations\nfunction handleTransition(model: CompositionModel, op: TransitionOperation): void {\n const clip = model.findClip(op.clipId);\n if (!clip) return;\n\n if (op.position === 'in') {\n if (op.type === 'removeTransition') {\n clip.transitionIn = undefined;\n } else {\n clip.transitionIn = op.transition as Transition;\n }\n } else {\n if (op.type === 'removeTransition') {\n clip.transitionOut = undefined;\n } else {\n clip.transitionOut = op.transition as Transition;\n }\n }\n}\n\n// Effect operations\nfunction handleEffect(model: CompositionModel, op: EffectOperation): void {\n if (op.targetType === 'track') {\n const track = model.findTrack(op.targetId);\n if (!track) return;\n\n if (!track.effects) track.effects = [];\n\n if (op.type === 'addEffect' && op.effect) {\n track.effects.push(op.effect as Effect);\n } else if (op.type === 'removeEffect' && op.effectId) {\n const index = track.effects.findIndex((e) => e.id === op.effectId);\n if (index !== -1) track.effects.splice(index, 1);\n } else if (op.type === 'updateEffect' && op.effectId && op.effect) {\n const effect = track.effects.find((e) => e.id === op.effectId);\n if (effect) Object.assign(effect, op.effect);\n }\n } else {\n const clip = model.findClip(op.targetId);\n if (!clip) return;\n\n if (!clip.effects) clip.effects = [];\n\n if (op.type === 'addEffect' && op.effect) {\n clip.effects.push(op.effect as Effect);\n } else if (op.type === 'removeEffect' && op.effectId) {\n const index = clip.effects.findIndex((e) => e.id === op.effectId);\n if (index !== -1) clip.effects.splice(index, 1);\n } else if (op.type === 'updateEffect' && op.effectId && op.effect) {\n const effect = clip.effects.find((e) => e.id === op.effectId);\n if (effect) Object.assign(effect, op.effect);\n }\n }\n}\n"],"names":[],"mappings":"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"}
|
package/dist/model/types.d.ts
CHANGED
|
@@ -227,5 +227,10 @@ export declare function isCaptionClip(clip: Clip): clip is CaptionClip;
|
|
|
227
227
|
export declare function isFxClip(clip: Clip): clip is FxClip;
|
|
228
228
|
export declare function hasResourceId(clip: Clip): clip is VideoClip | AudioClip;
|
|
229
229
|
export declare function hasAudioConfig(clip: Clip): clip is VideoClip | AudioClip;
|
|
230
|
+
export interface SetCompositionModelOptions {
|
|
231
|
+
clearL1Cache?: boolean;
|
|
232
|
+
clearL2Cache?: boolean;
|
|
233
|
+
needExport?: boolean;
|
|
234
|
+
}
|
|
230
235
|
export {};
|
|
231
236
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/model/types.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/model/types.ts"],"names":[],"mappings":"AACA,MAAM,MAAM,MAAM,GAAG,MAAM,CAAC;AAG5B,eAAO,MAAM,uBAAuB,UAAY,CAAC;AACjD,eAAO,MAAM,4BAA4B,OAAQ,CAAC;AAGlD,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,KAAK,CAAC;IACf,GAAG,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAEpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,YAAY,CAAC;IAE5B,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAGD,MAAM,WAAW,KAAK;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,OAAO,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,IAAI,CAAC;IACvD,KAAK,EAAE,IAAI,EAAE,CAAC;IAEd,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,YAAY,CAAC,EAAE,WAAW,EAAE,CAAC;CAC9B;AAGD,UAAU,QAAQ;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;IAE3B,YAAY,CAAC,EAAE,UAAU,CAAC;IAC1B,aAAa,CAAC,EAAE,UAAU,CAAC;IAE3B,QAAQ,CAAC,EAAE;QACT,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,MAAM,CAAC;QACzC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;KACxB,CAAC;IAGF,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,SAAU,SAAQ,QAAQ;IACzC,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IAGnB,WAAW,CAAC,EAAE;QACZ,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,OAAO,CAAC;KACjB,CAAC;CACH;AAED,MAAM,WAAW,SAAU,SAAQ,QAAQ;IACzC,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IAGnB,WAAW,CAAC,EAAE;QACZ,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,OAAO,CAAC;KACjB,CAAC;CACH;AAED,MAAM,WAAW,WAAY,SAAQ,QAAQ;IAC3C,SAAS,EAAE,SAAS,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,KAAK,CAAC;QAClB,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;KACf,CAAC,CAAC;IACH,SAAS,CAAC,EAAE;QACV,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,YAAY,GAAG,cAAc,GAAG,iBAAiB,GAAG,mBAAmB,CAAC;QAChG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;KACxB,CAAC;IACF,UAAU,CAAC,EAAE,OAAO,GAAG,OAAO,GAAG,MAAM,CAAC;CACzC;AAED,MAAM,WAAW,MAAO,SAAQ,QAAQ;IACtC,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,WAAY,SAAQ,QAAQ;IAC3C,SAAS,EAAE,SAAS,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IAGnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,IAAI,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,WAAW,GAAG,MAAM,CAAC;AAG9E,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;IACpD,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IAEnB,KAAK,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC;CACnD;AAGD,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,QAAQ,GAAG,KAAK,GAAG,WAAW,GAAG,MAAM,CAAC;IACpD,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAGD,MAAM,WAAW,eAAgB,SAAQ,MAAM;IAC7C,UAAU,EAAE,WAAW,CAAC;IACxB,MAAM,EAAE;QACN,QAAQ,EAAE;YAAE,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QACnC,SAAS,EAAE,iBAAiB,EAAE,CAAC;KAChC,CAAC;CACH;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,QAAQ,GAAG,SAAS,GAAG,UAAU,GAAG,aAAa,CAAC;CAC5D;AAED,MAAM,WAAW,WAAW;IAC1B,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,cAAc,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;IACnD,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,QAAQ,GAAG,SAAS,GAAG,UAAU,GAAG,MAAM,CAAC;IACnD,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,CAAC;IAC9C,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,KAAK,CAAC;QAClB,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;KACf,CAAC,CAAC;IACH,SAAS,CAAC,EAAE;QACV,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,YAAY,GAAG,cAAc,GAAG,iBAAiB,GAAG,mBAAmB,CAAC;QAChG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;KACxB,CAAC;IACF,UAAU,CAAC,EAAE,OAAO,GAAG,OAAO,GAAG,MAAM,CAAC;IACxC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,WAAW;IAC1B,eAAe,EAAE,OAAO,GAAG,OAAO,GAAG,MAAM,CAAC;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAGD,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,cAAc,EAAE,CAAC;IAC7B,QAAQ,CAAC,EAAE;QACT,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;CACH;AAED,MAAM,MAAM,cAAc,GACtB,cAAc,GACd,aAAa,GACb,iBAAiB,GACjB,mBAAmB,GACnB,mBAAmB,GACnB,eAAe,GACf,qBAAqB,CAAC;AAG1B,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,UAAU,GAAG,aAAa,GAAG,aAAa,CAAC;IACjD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;CACxB;AAGD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,SAAS,GAAG,YAAY,GAAG,YAAY,GAAG,UAAU,CAAC;IAC3D,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAGD,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,aAAa,GAAG,gBAAgB,GAAG,gBAAgB,CAAC;IAC1D,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;CAC9B;AAGD,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,eAAe,GAAG,kBAAkB,GAAG,kBAAkB,CAAC;IAChE,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;CAClC;AAGD,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,eAAe,GAAG,kBAAkB,GAAG,kBAAkB,CAAC;IAChE,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,IAAI,GAAG,KAAK,CAAC;IACvB,UAAU,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;CAClC;AAGD,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,oBAAoB,CAAC;IAC3B,YAAY,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;CACtC;AAGD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,WAAW,GAAG,cAAc,GAAG,cAAc,CAAC;IACpD,UAAU,EAAE,OAAO,GAAG,MAAM,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;CAC1B;AAGD,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAGD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,GAAG,CAAC;CACZ;AAGD,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,IAAI,SAAS,CAEzD;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,IAAI,SAAS,CAEzD;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,IAAI,WAAW,CAE7D;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,IAAI,MAAM,CAEnD;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,IAAI,SAAS,GAAG,SAAS,CAEvE;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,IAAI,SAAS,GAAG,SAAS,CAExE;AAED,MAAM,WAAW,0BAA0B;IACzC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB"}
|
package/dist/model/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sources":["../../src/model/types.ts"],"sourcesContent":["// All time values in microseconds (µs)\nexport type TimeUs = number; // 1 second = 1_000_000 µs\n\n// Helper constants\nexport const MICROSECONDS_PER_SECOND = 1_000_000;\nexport const MICROSECONDS_PER_MILLISECOND = 1_000;\n\n// ────── Root Object ──────\nexport interface CompositionModelData {\n version: '1.0';\n fps: 24 | 25 | 30 | 60;\n durationUs: TimeUs;\n tracks: Track[];\n resources: Record<string, Resource>;\n\n mainTrackId?: string;\n renderConfig?: RenderConfig;\n\n ext?: Record<string, unknown>;\n}\n\nexport interface RenderConfig {\n width: number;\n height: number;\n backgroundColor?: string;\n}\n\n// ────── Track ──────\nexport interface Track {\n id: string;\n kind: 'video' | 'audio' | 'caption' | 'overlay' | 'fx';\n clips: Clip[];\n\n effects?: Effect[];\n duckingRules?: DuckingRule[];\n}\n\n// ────── Clip ──────\ninterface BaseClip {\n id: string;\n startUs: TimeUs;\n durationUs: TimeUs;\n trackId?: string;\n\n trimStartUs?: TimeUs;\n trimEndUs?: TimeUs;\n\n effects?: Effect[];\n attachments?: Attachment[];\n\n transitionIn?: Transition;\n transitionOut?: Transition;\n\n metadata?: {\n purpose?: 'caption' | 'overlay' | 'mask';\n [key: string]: unknown;\n };\n\n // Internal: temporary field for tracking old resourceId during patch operations\n oldResourceId?: string;\n}\n\nexport interface VideoClip extends BaseClip {\n trackKind: 'video';\n resourceId: string;\n\n // Audio configuration for video's original sound\n audioConfig?: {\n volume?: number; // 0.0-1.0, default 1.0\n muted?: boolean; // default false\n };\n}\n\nexport interface AudioClip extends BaseClip {\n trackKind: 'audio';\n resourceId: string;\n\n // Audio configuration\n audioConfig?: {\n volume?: number; // 0.0-1.0, default 1.0\n muted?: boolean; // default false\n };\n}\n\nexport interface CaptionClip extends BaseClip {\n trackKind: 'caption';\n text: string;\n localeCode?: string;\n fontTemplate?: string;\n fontFamily?: string;\n wordTimings?: Array<{\n text: string;\n startUs: TimeUs;\n endUs: TimeUs;\n }>;\n animation?: {\n type: 'none' | 'fade' | 'wordByWord' | 'characterKTV' | 'wordByWordFancy' | 'wordByWordSlideUp';\n [key: string]: unknown;\n };\n letterCase?: 'upper' | 'lower' | 'none';\n}\n\nexport interface FxClip extends BaseClip {\n trackKind: 'fx';\n}\n\nexport interface OverlayClip extends BaseClip {\n trackKind: 'overlay';\n resourceId: string;\n\n // Optional overlay-specific config\n opacity?: number; // 0.0-1.0, default 1.0\n}\n\nexport type Clip = VideoClip | AudioClip | CaptionClip | OverlayClip | FxClip;\n\n// ────── Resource ──────\nexport interface Resource {\n id: string;\n type: 'video' | 'image' | 'audio' | 'json' | string;\n uri: string;\n metadata?: Record<string, unknown>;\n clipIds?: string[];\n // Runtime state maintained by engine\n state?: 'pending' | 'loading' | 'ready' | 'error';\n}\n\n// ────── Common Structures ──────\nexport interface Effect {\n id: string;\n effectType: 'filter' | 'lut' | 'animation' | string;\n params?: Record<string, unknown>;\n}\n\n// Animation effect (effectType: 'animation')\nexport interface AnimationEffect extends Effect {\n effectType: 'animation';\n params: {\n position: { x: number; y: number };\n keyframes: AnimationKeyframe[];\n };\n}\n\nexport interface AnimationKeyframe {\n time: number; // Relative to clip.startUs (microseconds)\n transform?: Transform2D;\n opacity?: number;\n easing?: 'linear' | 'ease-in' | 'ease-out' | 'ease-in-out';\n}\n\nexport interface Transform2D {\n x?: number; // Relative offset\n y?: number;\n scaleX?: number;\n scaleY?: number;\n rotation?: number; // Degrees\n anchorX?: number; // Rotation center x (0-1)\n anchorY?: number; // Rotation center y (0-1)\n}\n\nexport interface Transition {\n id: string;\n transitionType: 'fade' | 'wipe' | 'slide' | string;\n durationUs: TimeUs;\n curve?: 'linear' | 'ease-in' | 'ease-out' | string;\n params?: Record<string, unknown>;\n}\n\nexport interface Attachment {\n id: string;\n kind: 'caption' | 'overlay' | 'mask' | string;\n startUs: TimeUs;\n durationUs: TimeUs;\n data: Record<string, unknown>;\n}\n\nexport interface CaptionAttachmentData {\n text: string;\n localeCode?: string;\n fontTemplate?: string;\n fontFamily?: string;\n wordTimings?: Array<{\n text: string;\n startUs: TimeUs;\n endUs: TimeUs;\n }>;\n animation?: {\n type: 'none' | 'fade' | 'wordByWord' | 'characterKTV' | 'wordByWordFancy' | 'wordByWordSlideUp';\n [key: string]: unknown;\n };\n letterCase?: 'upper' | 'lower' | 'none';\n overlayClipStartUs?: TimeUs;\n mainClipStartUs?: TimeUs;\n}\n\nexport interface DuckingRule {\n targetTrackKind: 'voice' | 'audio' | string;\n ratio: number;\n attackMs: number;\n releaseMs: number;\n}\n\n// ────── Patch System ──────\nexport interface CompositionPatch {\n operations: PatchOperation[];\n metadata?: {\n timestamp: number;\n source?: string;\n version?: string;\n };\n}\n\nexport type PatchOperation =\n | TrackOperation\n | ClipOperation\n | ResourceOperation\n | AttachmentOperation\n | TransitionOperation\n | EffectOperation\n | RenderConfigOperation;\n\n// Track operations\nexport interface TrackOperation {\n type: 'addTrack' | 'updateTrack' | 'removeTrack';\n trackId?: string;\n track?: Partial<Track>;\n}\n\n// Clip operations\nexport interface ClipOperation {\n type: 'addClip' | 'updateClip' | 'removeClip' | 'moveClip';\n trackId: string;\n clipId?: string;\n clip?: Partial<Clip>;\n targetTrackId?: string;\n targetStartUs?: TimeUs;\n}\n\n// Resource operations\nexport interface ResourceOperation {\n type: 'addResource' | 'updateResource' | 'removeResource';\n resourceId: string;\n resource?: Partial<Resource>;\n}\n\n// Attachment operations\nexport interface AttachmentOperation {\n type: 'addAttachment' | 'updateAttachment' | 'removeAttachment';\n trackId: string;\n clipId: string;\n attachmentId?: string;\n attachment?: Partial<Attachment>;\n}\n\n// Transition operations\nexport interface TransitionOperation {\n type: 'addTransition' | 'updateTransition' | 'removeTransition';\n trackId: string;\n clipId: string;\n position: 'in' | 'out';\n transition?: Partial<Transition>;\n}\n\n// Render config operations\nexport interface RenderConfigOperation {\n type: 'updateRenderConfig';\n renderConfig?: Partial<RenderConfig>;\n}\n\n// Effect operations\nexport interface EffectOperation {\n type: 'addEffect' | 'updateEffect' | 'removeEffect';\n targetType: 'track' | 'clip';\n targetId: string;\n effectId?: string;\n effect?: Partial<Effect>;\n}\n\n// ────── Dirty Range ──────\nexport interface DirtyRange {\n trackId: string;\n startUs: TimeUs;\n endUs: TimeUs;\n reason: string;\n}\n\n// ────── Validation ──────\nexport interface ValidationError {\n path: string;\n message: string;\n value: any;\n}\n\n// ────── Type Guards ──────\nexport function isVideoClip(clip: Clip): clip is VideoClip {\n return clip.trackKind === 'video';\n}\n\nexport function isAudioClip(clip: Clip): clip is AudioClip {\n return clip.trackKind === 'audio';\n}\n\nexport function isCaptionClip(clip: Clip): clip is CaptionClip {\n return clip.trackKind === 'caption';\n}\n\nexport function isFxClip(clip: Clip): clip is FxClip {\n return clip.trackKind === 'fx';\n}\n\nexport function hasResourceId(clip: Clip): clip is VideoClip | AudioClip {\n return isVideoClip(clip) || isAudioClip(clip);\n}\n\nexport function hasAudioConfig(clip: Clip): clip is VideoClip | AudioClip {\n return isVideoClip(clip) || isAudioClip(clip);\n}\n"],"names":[],"mappings":"AAsSO,SAAS,YAAY,MAA+B;AACzD,SAAO,KAAK,cAAc;AAC5B;AAEO,SAAS,YAAY,MAA+B;AACzD,SAAO,KAAK,cAAc;AAC5B;AAUO,SAAS,cAAc,MAA2C;AACvE,SAAO,YAAY,IAAI,KAAK,YAAY,IAAI;AAC9C;AAEO,SAAS,eAAe,MAA2C;AACxE,SAAO,YAAY,IAAI,KAAK,YAAY,IAAI;AAC9C;"}
|
|
1
|
+
{"version":3,"file":"types.js","sources":["../../src/model/types.ts"],"sourcesContent":["// All time values in microseconds (µs)\nexport type TimeUs = number; // 1 second = 1_000_000 µs\n\n// Helper constants\nexport const MICROSECONDS_PER_SECOND = 1_000_000;\nexport const MICROSECONDS_PER_MILLISECOND = 1_000;\n\n// ────── Root Object ──────\nexport interface CompositionModelData {\n version: '1.0';\n fps: 24 | 25 | 30 | 60;\n durationUs: TimeUs;\n tracks: Track[];\n resources: Record<string, Resource>;\n\n mainTrackId?: string;\n renderConfig?: RenderConfig;\n\n ext?: Record<string, unknown>;\n}\n\nexport interface RenderConfig {\n width: number;\n height: number;\n backgroundColor?: string;\n}\n\n// ────── Track ──────\nexport interface Track {\n id: string;\n kind: 'video' | 'audio' | 'caption' | 'overlay' | 'fx';\n clips: Clip[];\n\n effects?: Effect[];\n duckingRules?: DuckingRule[];\n}\n\n// ────── Clip ──────\ninterface BaseClip {\n id: string;\n startUs: TimeUs;\n durationUs: TimeUs;\n trackId?: string;\n\n trimStartUs?: TimeUs;\n trimEndUs?: TimeUs;\n\n effects?: Effect[];\n attachments?: Attachment[];\n\n transitionIn?: Transition;\n transitionOut?: Transition;\n\n metadata?: {\n purpose?: 'caption' | 'overlay' | 'mask';\n [key: string]: unknown;\n };\n\n // Internal: temporary field for tracking old resourceId during patch operations\n oldResourceId?: string;\n}\n\nexport interface VideoClip extends BaseClip {\n trackKind: 'video';\n resourceId: string;\n\n // Audio configuration for video's original sound\n audioConfig?: {\n volume?: number; // 0.0-1.0, default 1.0\n muted?: boolean; // default false\n };\n}\n\nexport interface AudioClip extends BaseClip {\n trackKind: 'audio';\n resourceId: string;\n\n // Audio configuration\n audioConfig?: {\n volume?: number; // 0.0-1.0, default 1.0\n muted?: boolean; // default false\n };\n}\n\nexport interface CaptionClip extends BaseClip {\n trackKind: 'caption';\n text: string;\n localeCode?: string;\n fontTemplate?: string;\n fontFamily?: string;\n wordTimings?: Array<{\n text: string;\n startUs: TimeUs;\n endUs: TimeUs;\n }>;\n animation?: {\n type: 'none' | 'fade' | 'wordByWord' | 'characterKTV' | 'wordByWordFancy' | 'wordByWordSlideUp';\n [key: string]: unknown;\n };\n letterCase?: 'upper' | 'lower' | 'none';\n}\n\nexport interface FxClip extends BaseClip {\n trackKind: 'fx';\n}\n\nexport interface OverlayClip extends BaseClip {\n trackKind: 'overlay';\n resourceId: string;\n\n // Optional overlay-specific config\n opacity?: number; // 0.0-1.0, default 1.0\n}\n\nexport type Clip = VideoClip | AudioClip | CaptionClip | OverlayClip | FxClip;\n\n// ────── Resource ──────\nexport interface Resource {\n id: string;\n type: 'video' | 'image' | 'audio' | 'json' | string;\n uri: string;\n metadata?: Record<string, unknown>;\n clipIds?: string[];\n // Runtime state maintained by engine\n state?: 'pending' | 'loading' | 'ready' | 'error';\n}\n\n// ────── Common Structures ──────\nexport interface Effect {\n id: string;\n effectType: 'filter' | 'lut' | 'animation' | string;\n params?: Record<string, unknown>;\n}\n\n// Animation effect (effectType: 'animation')\nexport interface AnimationEffect extends Effect {\n effectType: 'animation';\n params: {\n position: { x: number; y: number };\n keyframes: AnimationKeyframe[];\n };\n}\n\nexport interface AnimationKeyframe {\n time: number; // Relative to clip.startUs (microseconds)\n transform?: Transform2D;\n opacity?: number;\n easing?: 'linear' | 'ease-in' | 'ease-out' | 'ease-in-out';\n}\n\nexport interface Transform2D {\n x?: number; // Relative offset\n y?: number;\n scaleX?: number;\n scaleY?: number;\n rotation?: number; // Degrees\n anchorX?: number; // Rotation center x (0-1)\n anchorY?: number; // Rotation center y (0-1)\n}\n\nexport interface Transition {\n id: string;\n transitionType: 'fade' | 'wipe' | 'slide' | string;\n durationUs: TimeUs;\n curve?: 'linear' | 'ease-in' | 'ease-out' | string;\n params?: Record<string, unknown>;\n}\n\nexport interface Attachment {\n id: string;\n kind: 'caption' | 'overlay' | 'mask' | string;\n startUs: TimeUs;\n durationUs: TimeUs;\n data: Record<string, unknown>;\n}\n\nexport interface CaptionAttachmentData {\n text: string;\n localeCode?: string;\n fontTemplate?: string;\n fontFamily?: string;\n wordTimings?: Array<{\n text: string;\n startUs: TimeUs;\n endUs: TimeUs;\n }>;\n animation?: {\n type: 'none' | 'fade' | 'wordByWord' | 'characterKTV' | 'wordByWordFancy' | 'wordByWordSlideUp';\n [key: string]: unknown;\n };\n letterCase?: 'upper' | 'lower' | 'none';\n overlayClipStartUs?: TimeUs;\n mainClipStartUs?: TimeUs;\n}\n\nexport interface DuckingRule {\n targetTrackKind: 'voice' | 'audio' | string;\n ratio: number;\n attackMs: number;\n releaseMs: number;\n}\n\n// ────── Patch System ──────\nexport interface CompositionPatch {\n operations: PatchOperation[];\n metadata?: {\n timestamp: number;\n source?: string;\n version?: string;\n };\n}\n\nexport type PatchOperation =\n | TrackOperation\n | ClipOperation\n | ResourceOperation\n | AttachmentOperation\n | TransitionOperation\n | EffectOperation\n | RenderConfigOperation;\n\n// Track operations\nexport interface TrackOperation {\n type: 'addTrack' | 'updateTrack' | 'removeTrack';\n trackId?: string;\n track?: Partial<Track>;\n}\n\n// Clip operations\nexport interface ClipOperation {\n type: 'addClip' | 'updateClip' | 'removeClip' | 'moveClip';\n trackId: string;\n clipId?: string;\n clip?: Partial<Clip>;\n targetTrackId?: string;\n targetStartUs?: TimeUs;\n}\n\n// Resource operations\nexport interface ResourceOperation {\n type: 'addResource' | 'updateResource' | 'removeResource';\n resourceId: string;\n resource?: Partial<Resource>;\n}\n\n// Attachment operations\nexport interface AttachmentOperation {\n type: 'addAttachment' | 'updateAttachment' | 'removeAttachment';\n trackId: string;\n clipId: string;\n attachmentId?: string;\n attachment?: Partial<Attachment>;\n}\n\n// Transition operations\nexport interface TransitionOperation {\n type: 'addTransition' | 'updateTransition' | 'removeTransition';\n trackId: string;\n clipId: string;\n position: 'in' | 'out';\n transition?: Partial<Transition>;\n}\n\n// Render config operations\nexport interface RenderConfigOperation {\n type: 'updateRenderConfig';\n renderConfig?: Partial<RenderConfig>;\n}\n\n// Effect operations\nexport interface EffectOperation {\n type: 'addEffect' | 'updateEffect' | 'removeEffect';\n targetType: 'track' | 'clip';\n targetId: string;\n effectId?: string;\n effect?: Partial<Effect>;\n}\n\n// ────── Dirty Range ──────\nexport interface DirtyRange {\n trackId: string;\n startUs: TimeUs;\n endUs: TimeUs;\n reason: string;\n}\n\n// ────── Validation ──────\nexport interface ValidationError {\n path: string;\n message: string;\n value: any;\n}\n\n// ────── Type Guards ──────\nexport function isVideoClip(clip: Clip): clip is VideoClip {\n return clip.trackKind === 'video';\n}\n\nexport function isAudioClip(clip: Clip): clip is AudioClip {\n return clip.trackKind === 'audio';\n}\n\nexport function isCaptionClip(clip: Clip): clip is CaptionClip {\n return clip.trackKind === 'caption';\n}\n\nexport function isFxClip(clip: Clip): clip is FxClip {\n return clip.trackKind === 'fx';\n}\n\nexport function hasResourceId(clip: Clip): clip is VideoClip | AudioClip {\n return isVideoClip(clip) || isAudioClip(clip);\n}\n\nexport function hasAudioConfig(clip: Clip): clip is VideoClip | AudioClip {\n return isVideoClip(clip) || isAudioClip(clip);\n}\n\nexport interface SetCompositionModelOptions {\n clearL1Cache?: boolean;\n clearL2Cache?: boolean;\n needExport?: boolean;\n}\n"],"names":[],"mappings":"AAsSO,SAAS,YAAY,MAA+B;AACzD,SAAO,KAAK,cAAc;AAC5B;AAEO,SAAS,YAAY,MAA+B;AACzD,SAAO,KAAK,cAAc;AAC5B;AAUO,SAAS,cAAc,MAA2C;AACvE,SAAO,YAAY,IAAI,KAAK,YAAY,IAAI;AAC9C;AAEO,SAAS,eAAe,MAA2C;AACxE,SAAO,YAAY,IAAI,KAAK,YAAY,IAAI;AAC9C;"}
|
|
@@ -5,6 +5,7 @@ import { CacheManager } from '../cache/CacheManager';
|
|
|
5
5
|
import { IOrchestrator, OrchestratorConfig, RenderFrameOptions } from './types';
|
|
6
6
|
import { WorkerStatus, WorkerType } from '../worker/types';
|
|
7
7
|
import { CompositionModel, CompositionPatch, TimeUs, RcFrame } from '../model';
|
|
8
|
+
import { SetCompositionModelOptions } from '../model/types';
|
|
8
9
|
import { EventPayloadMap } from '../event/events';
|
|
9
10
|
import { CompositionPlanner } from './CompositionPlanner';
|
|
10
11
|
import { GlobalAudioSession } from './GlobalAudioSession';
|
|
@@ -34,7 +35,7 @@ export declare class Orchestrator implements IOrchestrator {
|
|
|
34
35
|
on<K extends keyof EventPayloadMap>(event: K, handler: (payload: EventPayloadMap[K]) => void): void;
|
|
35
36
|
off<K extends keyof EventPayloadMap>(event: K, handler: (payload: EventPayloadMap[K]) => void): void;
|
|
36
37
|
once<K extends keyof EventPayloadMap>(event: K, handler: (payload: EventPayloadMap[K]) => void): void;
|
|
37
|
-
setCompositionModel(model: CompositionModel): Promise<void>;
|
|
38
|
+
setCompositionModel(model: CompositionModel, options?: SetCompositionModelOptions): Promise<void>;
|
|
38
39
|
applyPatch(patch: CompositionPatch): Promise<void>;
|
|
39
40
|
private handleResourceStateChange;
|
|
40
41
|
restartWorker(type: WorkerType, clipId?: string): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Orchestrator.d.ts","sourceRoot":"","sources":["../../src/orchestrator/Orchestrator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAElD,OAAO,EAAyB,cAAc,EAAE,MAAM,+BAA+B,CAAC;AACtF,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAErD,OAAO,KAAK,EAAE,aAAa,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AACrF,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAY,MAAM,EAAE,OAAO,EAAQ,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"Orchestrator.d.ts","sourceRoot":"","sources":["../../src/orchestrator/Orchestrator.ts"],"names":[],"mappings":"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"}
|
|
@@ -120,7 +120,14 @@ class Orchestrator {
|
|
|
120
120
|
once(event, handler) {
|
|
121
121
|
this.eventBus.once(event, handler);
|
|
122
122
|
}
|
|
123
|
-
async setCompositionModel(model) {
|
|
123
|
+
async setCompositionModel(model, options) {
|
|
124
|
+
const { clearL1Cache = true, clearL2Cache = false } = options || {};
|
|
125
|
+
if (clearL1Cache) {
|
|
126
|
+
this.cacheManager.clearL1Cache();
|
|
127
|
+
}
|
|
128
|
+
if (clearL2Cache) {
|
|
129
|
+
await this.cacheManager.clearL2Cache();
|
|
130
|
+
}
|
|
124
131
|
this.compositionModel = model;
|
|
125
132
|
this.planner.setModel(model);
|
|
126
133
|
this.currentClipId = null;
|
|
@@ -299,7 +306,8 @@ class Orchestrator {
|
|
|
299
306
|
width: metadata.codedWidth,
|
|
300
307
|
height: metadata.codedHeight,
|
|
301
308
|
description: metadata.description,
|
|
302
|
-
hardwareAcceleration: metadata.hardwareAcceleration || "no-preference"
|
|
309
|
+
hardwareAcceleration: metadata.hardwareAcceleration || "no-preference",
|
|
310
|
+
thread: "main"
|
|
303
311
|
});
|
|
304
312
|
try {
|
|
305
313
|
const decodeStream = chunkStream.pipeThrough(decoder.createStream());
|