@meframe/core 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +42 -0
- package/LICENSE +22 -0
- package/README.md +396 -0
- package/dist/Meframe.d.ts +82 -0
- package/dist/Meframe.d.ts.map +1 -0
- package/dist/Meframe.js +290 -0
- package/dist/Meframe.js.map +1 -0
- package/dist/_virtual/mp4box.all.js +5 -0
- package/dist/_virtual/mp4box.all.js.map +1 -0
- package/dist/cache/BatchWriter.d.ts +25 -0
- package/dist/cache/BatchWriter.d.ts.map +1 -0
- package/dist/cache/CacheManager.d.ts +115 -0
- package/dist/cache/CacheManager.d.ts.map +1 -0
- package/dist/cache/CacheManager.js +388 -0
- package/dist/cache/CacheManager.js.map +1 -0
- package/dist/cache/CacheStatsDecorator.d.ts +27 -0
- package/dist/cache/CacheStatsDecorator.d.ts.map +1 -0
- package/dist/cache/L2Cache.d.ts +39 -0
- package/dist/cache/L2Cache.d.ts.map +1 -0
- package/dist/cache/L2Cache.js +282 -0
- package/dist/cache/L2Cache.js.map +1 -0
- package/dist/cache/index.d.ts +7 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/l1/AudioL1Cache.d.ts +30 -0
- package/dist/cache/l1/AudioL1Cache.d.ts.map +1 -0
- package/dist/cache/l1/AudioL1Cache.js +306 -0
- package/dist/cache/l1/AudioL1Cache.js.map +1 -0
- package/dist/cache/l1/MixedAudioL1Cache.d.ts +13 -0
- package/dist/cache/l1/MixedAudioL1Cache.d.ts.map +1 -0
- package/dist/cache/l1/MixedAudioL1Cache.js +52 -0
- package/dist/cache/l1/MixedAudioL1Cache.js.map +1 -0
- package/dist/cache/l1/VideoL1Cache.d.ts +69 -0
- package/dist/cache/l1/VideoL1Cache.d.ts.map +1 -0
- package/dist/cache/l1/VideoL1Cache.js +318 -0
- package/dist/cache/l1/VideoL1Cache.js.map +1 -0
- package/dist/cache/l1/gop-utils.d.ts +10 -0
- package/dist/cache/l1/gop-utils.d.ts.map +1 -0
- package/dist/cache/l1/gop-utils.js +78 -0
- package/dist/cache/l1/gop-utils.js.map +1 -0
- package/dist/cache/l1/index.d.ts +4 -0
- package/dist/cache/l1/index.d.ts.map +1 -0
- package/dist/cache/l1/types.d.ts +17 -0
- package/dist/cache/l1/types.d.ts.map +1 -0
- package/dist/cache/types.d.ts +93 -0
- package/dist/cache/types.d.ts.map +1 -0
- package/dist/config/ConfigLoader.d.ts +69 -0
- package/dist/config/ConfigLoader.d.ts.map +1 -0
- package/dist/config/ConfigLoader.js +133 -0
- package/dist/config/ConfigLoader.js.map +1 -0
- package/dist/config/defaults.d.ts +125 -0
- package/dist/config/defaults.d.ts.map +1 -0
- package/dist/config/defaults.js +191 -0
- package/dist/config/defaults.js.map +1 -0
- package/dist/config/index.d.ts +6 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/presets.d.ts +32 -0
- package/dist/config/presets.d.ts.map +1 -0
- package/dist/config/presets.js +11 -0
- package/dist/config/presets.js.map +1 -0
- package/dist/config/types.d.ts +199 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/validation.d.ts +19 -0
- package/dist/config/validation.d.ts.map +1 -0
- package/dist/config/validation.js +232 -0
- package/dist/config/validation.js.map +1 -0
- package/dist/controllers/PlaybackController.d.ts +55 -0
- package/dist/controllers/PlaybackController.d.ts.map +1 -0
- package/dist/controllers/PlaybackController.js +369 -0
- package/dist/controllers/PlaybackController.js.map +1 -0
- package/dist/controllers/PreRenderService.d.ts +34 -0
- package/dist/controllers/PreRenderService.d.ts.map +1 -0
- package/dist/controllers/PreRenderService.js +83 -0
- package/dist/controllers/PreRenderService.js.map +1 -0
- package/dist/controllers/PreRenderTaskQueue.d.ts +21 -0
- package/dist/controllers/PreRenderTaskQueue.d.ts.map +1 -0
- package/dist/controllers/PreviewHandle.d.ts +23 -0
- package/dist/controllers/PreviewHandle.d.ts.map +1 -0
- package/dist/controllers/PreviewHandle.js +39 -0
- package/dist/controllers/PreviewHandle.js.map +1 -0
- package/dist/controllers/index.d.ts +8 -0
- package/dist/controllers/index.d.ts.map +1 -0
- package/dist/controllers/types.d.ts +102 -0
- package/dist/controllers/types.d.ts.map +1 -0
- package/dist/event/EventBus.d.ts +42 -0
- package/dist/event/EventBus.d.ts.map +1 -0
- package/dist/event/EventBus.js +94 -0
- package/dist/event/EventBus.js.map +1 -0
- package/dist/event/events.d.ts +371 -0
- package/dist/event/events.d.ts.map +1 -0
- package/dist/event/events.js +71 -0
- package/dist/event/events.js.map +1 -0
- package/dist/event/index.d.ts +4 -0
- package/dist/event/index.d.ts.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/model/CompositionModel.d.ts +48 -0
- package/dist/model/CompositionModel.d.ts.map +1 -0
- package/dist/model/CompositionModel.js +197 -0
- package/dist/model/CompositionModel.js.map +1 -0
- package/dist/model/RcFrame.d.ts +34 -0
- package/dist/model/RcFrame.d.ts.map +1 -0
- package/dist/model/RcFrame.js +97 -0
- package/dist/model/RcFrame.js.map +1 -0
- package/dist/model/dirty-range.d.ts +5 -0
- package/dist/model/dirty-range.d.ts.map +1 -0
- package/dist/model/dirty-range.js +220 -0
- package/dist/model/dirty-range.js.map +1 -0
- package/dist/model/index.d.ts +7 -0
- package/dist/model/index.d.ts.map +1 -0
- package/dist/model/patch.d.ts +5 -0
- package/dist/model/patch.d.ts.map +1 -0
- package/dist/model/patch.js +250 -0
- package/dist/model/patch.js.map +1 -0
- package/dist/model/types.d.ts +135 -0
- package/dist/model/types.d.ts.map +1 -0
- package/dist/model/types.js +5 -0
- package/dist/model/types.js.map +1 -0
- package/dist/model/validation.d.ts +15 -0
- package/dist/model/validation.d.ts.map +1 -0
- package/dist/model/validation.js +74 -0
- package/dist/model/validation.js.map +1 -0
- package/dist/node_modules/.pnpm/mp4box@0.5.4/node_modules/mp4box/dist/mp4box.all.js +7046 -0
- package/dist/node_modules/.pnpm/mp4box@0.5.4/node_modules/mp4box/dist/mp4box.all.js.map +1 -0
- package/dist/orchestrator/ClipSessionManager.d.ts +75 -0
- package/dist/orchestrator/ClipSessionManager.d.ts.map +1 -0
- package/dist/orchestrator/ClipSessionManager.js +160 -0
- package/dist/orchestrator/ClipSessionManager.js.map +1 -0
- package/dist/orchestrator/CompositionPlanner.d.ts +55 -0
- package/dist/orchestrator/CompositionPlanner.d.ts.map +1 -0
- package/dist/orchestrator/CompositionPlanner.js +411 -0
- package/dist/orchestrator/CompositionPlanner.js.map +1 -0
- package/dist/orchestrator/Orchestrator.d.ts +59 -0
- package/dist/orchestrator/Orchestrator.d.ts.map +1 -0
- package/dist/orchestrator/Orchestrator.js +390 -0
- package/dist/orchestrator/Orchestrator.js.map +1 -0
- package/dist/orchestrator/VideoClipSession.d.ts +64 -0
- package/dist/orchestrator/VideoClipSession.d.ts.map +1 -0
- package/dist/orchestrator/VideoClipSession.js +309 -0
- package/dist/orchestrator/VideoClipSession.js.map +1 -0
- package/dist/orchestrator/index.d.ts +5 -0
- package/dist/orchestrator/index.d.ts.map +1 -0
- package/dist/orchestrator/types.d.ts +64 -0
- package/dist/orchestrator/types.d.ts.map +1 -0
- package/dist/plugins/BackpressureMonitor.d.ts +33 -0
- package/dist/plugins/BackpressureMonitor.d.ts.map +1 -0
- package/dist/plugins/BackpressureMonitor.js +62 -0
- package/dist/plugins/BackpressureMonitor.js.map +1 -0
- package/dist/plugins/PluginManager.d.ts +37 -0
- package/dist/plugins/PluginManager.d.ts.map +1 -0
- package/dist/plugins/PluginManager.js +66 -0
- package/dist/plugins/PluginManager.js.map +1 -0
- package/dist/plugins/types.d.ts +60 -0
- package/dist/plugins/types.d.ts.map +1 -0
- package/dist/stages/compose/AudioDucker.d.ts +59 -0
- package/dist/stages/compose/AudioDucker.d.ts.map +1 -0
- package/dist/stages/compose/AudioDucker.js +161 -0
- package/dist/stages/compose/AudioDucker.js.map +1 -0
- package/dist/stages/compose/AudioMixer.d.ts +29 -0
- package/dist/stages/compose/AudioMixer.d.ts.map +1 -0
- package/dist/stages/compose/AudioMixer.js +373 -0
- package/dist/stages/compose/AudioMixer.js.map +1 -0
- package/dist/stages/compose/FilterProcessor.d.ts +41 -0
- package/dist/stages/compose/FilterProcessor.d.ts.map +1 -0
- package/dist/stages/compose/FilterProcessor.js +226 -0
- package/dist/stages/compose/FilterProcessor.js.map +1 -0
- package/dist/stages/compose/GlobalAudioSession.d.ts +38 -0
- package/dist/stages/compose/GlobalAudioSession.d.ts.map +1 -0
- package/dist/stages/compose/GlobalAudioSession.js +122 -0
- package/dist/stages/compose/GlobalAudioSession.js.map +1 -0
- package/dist/stages/compose/LayerRenderer.d.ts +30 -0
- package/dist/stages/compose/LayerRenderer.d.ts.map +1 -0
- package/dist/stages/compose/LayerRenderer.js +215 -0
- package/dist/stages/compose/LayerRenderer.js.map +1 -0
- package/dist/stages/compose/OfflineAudioMixer.d.ts +14 -0
- package/dist/stages/compose/OfflineAudioMixer.d.ts.map +1 -0
- package/dist/stages/compose/OfflineAudioMixer.js +68 -0
- package/dist/stages/compose/OfflineAudioMixer.js.map +1 -0
- package/dist/stages/compose/TransitionProcessor.d.ts +30 -0
- package/dist/stages/compose/TransitionProcessor.d.ts.map +1 -0
- package/dist/stages/compose/TransitionProcessor.js +189 -0
- package/dist/stages/compose/TransitionProcessor.js.map +1 -0
- package/dist/stages/compose/VideoComposer.d.ts +30 -0
- package/dist/stages/compose/VideoComposer.d.ts.map +1 -0
- package/dist/stages/compose/VideoComposer.js +186 -0
- package/dist/stages/compose/VideoComposer.js.map +1 -0
- package/dist/stages/compose/audio-compose.worker.d.ts +79 -0
- package/dist/stages/compose/audio-compose.worker.d.ts.map +1 -0
- package/dist/stages/compose/audio-compose.worker.js +541 -0
- package/dist/stages/compose/audio-compose.worker.js.map +1 -0
- package/dist/stages/compose/instructions.d.ts +95 -0
- package/dist/stages/compose/instructions.d.ts.map +1 -0
- package/dist/stages/compose/types.d.ts +245 -0
- package/dist/stages/compose/types.d.ts.map +1 -0
- package/dist/stages/compose/video-compose.worker.d.ts +60 -0
- package/dist/stages/compose/video-compose.worker.d.ts.map +1 -0
- package/dist/stages/compose/video-compose.worker.js +369 -0
- package/dist/stages/compose/video-compose.worker.js.map +1 -0
- package/dist/stages/decode/AudioChunkDecoder.d.ts +41 -0
- package/dist/stages/decode/AudioChunkDecoder.d.ts.map +1 -0
- package/dist/stages/decode/AudioChunkDecoder.js +83 -0
- package/dist/stages/decode/AudioChunkDecoder.js.map +1 -0
- package/dist/stages/decode/BaseDecoder.d.ts +35 -0
- package/dist/stages/decode/BaseDecoder.d.ts.map +1 -0
- package/dist/stages/decode/BaseDecoder.js +130 -0
- package/dist/stages/decode/BaseDecoder.js.map +1 -0
- package/dist/stages/decode/VideoChunkDecoder.d.ts +54 -0
- package/dist/stages/decode/VideoChunkDecoder.d.ts.map +1 -0
- package/dist/stages/decode/VideoChunkDecoder.js +209 -0
- package/dist/stages/decode/VideoChunkDecoder.js.map +1 -0
- package/dist/stages/decode/decode.worker.d.ts +70 -0
- package/dist/stages/decode/decode.worker.d.ts.map +1 -0
- package/dist/stages/decode/decode.worker.js +436 -0
- package/dist/stages/decode/decode.worker.js.map +1 -0
- package/dist/stages/decode/index.d.ts +5 -0
- package/dist/stages/decode/index.d.ts.map +1 -0
- package/dist/stages/decode/types.d.ts +108 -0
- package/dist/stages/decode/types.d.ts.map +1 -0
- package/dist/stages/demux/MP3FrameParser.d.ts +33 -0
- package/dist/stages/demux/MP3FrameParser.d.ts.map +1 -0
- package/dist/stages/demux/MP3FrameParser.js +186 -0
- package/dist/stages/demux/MP3FrameParser.js.map +1 -0
- package/dist/stages/demux/MP4Demuxer.d.ts +45 -0
- package/dist/stages/demux/MP4Demuxer.d.ts.map +1 -0
- package/dist/stages/demux/MP4Demuxer.js +227 -0
- package/dist/stages/demux/MP4Demuxer.js.map +1 -0
- package/dist/stages/demux/aac-esds-extractor.d.ts +7 -0
- package/dist/stages/demux/aac-esds-extractor.d.ts.map +1 -0
- package/dist/stages/demux/audio-demux.worker.d.ts +51 -0
- package/dist/stages/demux/audio-demux.worker.d.ts.map +1 -0
- package/dist/stages/demux/audio-demux.worker.js +312 -0
- package/dist/stages/demux/audio-demux.worker.js.map +1 -0
- package/dist/stages/demux/types.d.ts +77 -0
- package/dist/stages/demux/types.d.ts.map +1 -0
- package/dist/stages/demux/video-demux.worker.d.ts +48 -0
- package/dist/stages/demux/video-demux.worker.d.ts.map +1 -0
- package/dist/stages/demux/video-demux.worker.js +173 -0
- package/dist/stages/demux/video-demux.worker.js.map +1 -0
- package/dist/stages/encode/AudioChunkEncoder.d.ts +21 -0
- package/dist/stages/encode/AudioChunkEncoder.d.ts.map +1 -0
- package/dist/stages/encode/AudioChunkEncoder.js +37 -0
- package/dist/stages/encode/AudioChunkEncoder.js.map +1 -0
- package/dist/stages/encode/BaseEncoder.d.ts +44 -0
- package/dist/stages/encode/BaseEncoder.d.ts.map +1 -0
- package/dist/stages/encode/BaseEncoder.js +164 -0
- package/dist/stages/encode/BaseEncoder.js.map +1 -0
- package/dist/stages/encode/EncoderPool.d.ts +28 -0
- package/dist/stages/encode/EncoderPool.d.ts.map +1 -0
- package/dist/stages/encode/VideoChunkEncoder.d.ts +26 -0
- package/dist/stages/encode/VideoChunkEncoder.d.ts.map +1 -0
- package/dist/stages/encode/VideoChunkEncoder.js +50 -0
- package/dist/stages/encode/VideoChunkEncoder.js.map +1 -0
- package/dist/stages/encode/encode.worker.d.ts +3 -0
- package/dist/stages/encode/encode.worker.d.ts.map +1 -0
- package/dist/stages/encode/encode.worker.js +318 -0
- package/dist/stages/encode/encode.worker.js.map +1 -0
- package/dist/stages/encode/index.d.ts +6 -0
- package/dist/stages/encode/index.d.ts.map +1 -0
- package/dist/stages/encode/types.d.ts +127 -0
- package/dist/stages/encode/types.d.ts.map +1 -0
- package/dist/stages/load/EventHandlers.d.ts +35 -0
- package/dist/stages/load/EventHandlers.d.ts.map +1 -0
- package/dist/stages/load/EventHandlers.js +65 -0
- package/dist/stages/load/EventHandlers.js.map +1 -0
- package/dist/stages/load/ResourceLoader.d.ts +36 -0
- package/dist/stages/load/ResourceLoader.d.ts.map +1 -0
- package/dist/stages/load/ResourceLoader.js +184 -0
- package/dist/stages/load/ResourceLoader.js.map +1 -0
- package/dist/stages/load/StreamFactory.d.ts +42 -0
- package/dist/stages/load/StreamFactory.d.ts.map +1 -0
- package/dist/stages/load/StreamFactory.js +201 -0
- package/dist/stages/load/StreamFactory.js.map +1 -0
- package/dist/stages/load/TaskManager.d.ts +50 -0
- package/dist/stages/load/TaskManager.d.ts.map +1 -0
- package/dist/stages/load/TaskManager.js +103 -0
- package/dist/stages/load/TaskManager.js.map +1 -0
- package/dist/stages/load/WindowByteRangeResolver.d.ts +47 -0
- package/dist/stages/load/WindowByteRangeResolver.d.ts.map +1 -0
- package/dist/stages/load/WindowByteRangeResolver.js +270 -0
- package/dist/stages/load/WindowByteRangeResolver.js.map +1 -0
- package/dist/stages/load/index.d.ts +11 -0
- package/dist/stages/load/index.d.ts.map +1 -0
- package/dist/stages/load/types.d.ts +177 -0
- package/dist/stages/load/types.d.ts.map +1 -0
- package/dist/stages/mux/MP4Muxer.d.ts +44 -0
- package/dist/stages/mux/MP4Muxer.d.ts.map +1 -0
- package/dist/stages/mux/MP4Muxer.js +262 -0
- package/dist/stages/mux/MP4Muxer.js.map +1 -0
- package/dist/stages/mux/OPFSWriter.d.ts +46 -0
- package/dist/stages/mux/OPFSWriter.d.ts.map +1 -0
- package/dist/stages/mux/index.d.ts +5 -0
- package/dist/stages/mux/index.d.ts.map +1 -0
- package/dist/stages/mux/mux.worker.d.ts +65 -0
- package/dist/stages/mux/mux.worker.d.ts.map +1 -0
- package/dist/stages/mux/mux.worker.js +219 -0
- package/dist/stages/mux/mux.worker.js.map +1 -0
- package/dist/stages/mux/types.d.ts +95 -0
- package/dist/stages/mux/types.d.ts.map +1 -0
- package/dist/stages/mux/utils.d.ts +32 -0
- package/dist/stages/mux/utils.d.ts.map +1 -0
- package/dist/stages/mux/utils.js +34 -0
- package/dist/stages/mux/utils.js.map +1 -0
- package/dist/types.d.ts +25 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/utils/BackpressureAdapter.d.ts +26 -0
- package/dist/utils/BackpressureAdapter.d.ts.map +1 -0
- package/dist/utils/binary-search.d.ts +33 -0
- package/dist/utils/binary-search.d.ts.map +1 -0
- package/dist/utils/binary-search.js +62 -0
- package/dist/utils/binary-search.js.map +1 -0
- package/dist/utils/canvas-utils.d.ts +96 -0
- package/dist/utils/canvas-utils.d.ts.map +1 -0
- package/dist/utils/canvas-utils.js +58 -0
- package/dist/utils/canvas-utils.js.map +1 -0
- package/dist/utils/object-utils.d.ts +34 -0
- package/dist/utils/object-utils.d.ts.map +1 -0
- package/dist/utils/object-utils.js +22 -0
- package/dist/utils/object-utils.js.map +1 -0
- package/dist/utils/time-utils.d.ts +10 -0
- package/dist/utils/time-utils.d.ts.map +1 -0
- package/dist/utils/time-utils.js +60 -0
- package/dist/utils/time-utils.js.map +1 -0
- package/dist/worker/BaseWorker.d.ts +44 -0
- package/dist/worker/BaseWorker.d.ts.map +1 -0
- package/dist/worker/BaseWorker.js +98 -0
- package/dist/worker/BaseWorker.js.map +1 -0
- package/dist/worker/WorkerChannel.d.ts +105 -0
- package/dist/worker/WorkerChannel.d.ts.map +1 -0
- package/dist/worker/WorkerChannel.js +355 -0
- package/dist/worker/WorkerChannel.js.map +1 -0
- package/dist/worker/WorkerPool.d.ts +52 -0
- package/dist/worker/WorkerPool.d.ts.map +1 -0
- package/dist/worker/WorkerPool.js +124 -0
- package/dist/worker/WorkerPool.js.map +1 -0
- package/dist/worker/index.d.ts +11 -0
- package/dist/worker/index.d.ts.map +1 -0
- package/dist/worker/transferable-helper.d.ts +89 -0
- package/dist/worker/transferable-helper.d.ts.map +1 -0
- package/dist/worker/transferable-helper.js +44 -0
- package/dist/worker/transferable-helper.js.map +1 -0
- package/dist/worker/types.d.ts +179 -0
- package/dist/worker/types.d.ts.map +1 -0
- package/dist/worker/types.js +50 -0
- package/dist/worker/types.js.map +1 -0
- package/dist/worker/worker-event-whitelist.d.ts +23 -0
- package/dist/worker/worker-event-whitelist.d.ts.map +1 -0
- package/dist/worker/worker-retry.d.ts +36 -0
- package/dist/worker/worker-retry.d.ts.map +1 -0
- package/dist/worker/worker-retry.js +55 -0
- package/dist/worker/worker-retry.js.map +1 -0
- package/package.json +105 -0
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
function resolveDirtyRanges(patch, model) {
|
|
2
|
+
const affectedClips = /* @__PURE__ */ new Set();
|
|
3
|
+
const affectedTracks = /* @__PURE__ */ new Set();
|
|
4
|
+
const affectedResources = /* @__PURE__ */ new Set();
|
|
5
|
+
for (const op of patch.operations) {
|
|
6
|
+
collectAffectedElements(op, model, affectedClips, affectedTracks, affectedResources);
|
|
7
|
+
}
|
|
8
|
+
return calculateTimeRanges(affectedClips, affectedTracks, affectedResources, model);
|
|
9
|
+
}
|
|
10
|
+
function collectAffectedElements(op, model, affectedClips, affectedTracks, affectedResources) {
|
|
11
|
+
switch (op.type) {
|
|
12
|
+
case "addTrack":
|
|
13
|
+
case "removeTrack":
|
|
14
|
+
case "updateTrack": {
|
|
15
|
+
const trackOp = op;
|
|
16
|
+
if (trackOp.trackId) {
|
|
17
|
+
affectedTracks.add(trackOp.trackId);
|
|
18
|
+
const track = model.findTrack(trackOp.trackId);
|
|
19
|
+
if (track) {
|
|
20
|
+
track.clips.forEach((clip) => affectedClips.add(clip.id));
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
case "addClip":
|
|
26
|
+
case "removeClip":
|
|
27
|
+
case "updateClip":
|
|
28
|
+
case "moveClip": {
|
|
29
|
+
const clipOp = op;
|
|
30
|
+
if (clipOp.clipId) {
|
|
31
|
+
affectedClips.add(clipOp.clipId);
|
|
32
|
+
}
|
|
33
|
+
if (clipOp.trackId) {
|
|
34
|
+
affectedTracks.add(clipOp.trackId);
|
|
35
|
+
}
|
|
36
|
+
if (clipOp.targetTrackId) {
|
|
37
|
+
affectedTracks.add(clipOp.targetTrackId);
|
|
38
|
+
}
|
|
39
|
+
if (clipOp.clip) {
|
|
40
|
+
collectOverlappingClips(
|
|
41
|
+
model,
|
|
42
|
+
clipOp.trackId,
|
|
43
|
+
clipOp.clip.startUs || 0,
|
|
44
|
+
(clipOp.clip.startUs || 0) + (clipOp.clip.durationUs || 0),
|
|
45
|
+
affectedClips
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
case "addResource":
|
|
51
|
+
case "updateResource":
|
|
52
|
+
case "removeResource": {
|
|
53
|
+
const resourceOp = op;
|
|
54
|
+
affectedResources.add(resourceOp.resourceId);
|
|
55
|
+
for (const track of model.tracks) {
|
|
56
|
+
for (const clip of track.clips) {
|
|
57
|
+
if (clip.resourceId === resourceOp.resourceId) {
|
|
58
|
+
affectedClips.add(clip.id);
|
|
59
|
+
affectedTracks.add(track.id);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
case "addAttachment":
|
|
66
|
+
case "updateAttachment":
|
|
67
|
+
case "removeAttachment": {
|
|
68
|
+
const attachmentOp = op;
|
|
69
|
+
if (attachmentOp.clipId) {
|
|
70
|
+
affectedClips.add(attachmentOp.clipId);
|
|
71
|
+
}
|
|
72
|
+
if (attachmentOp.trackId) {
|
|
73
|
+
affectedTracks.add(attachmentOp.trackId);
|
|
74
|
+
}
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
case "addTransition":
|
|
78
|
+
case "updateTransition":
|
|
79
|
+
case "removeTransition": {
|
|
80
|
+
const transitionOp = op;
|
|
81
|
+
if (transitionOp.clipId) {
|
|
82
|
+
affectedClips.add(transitionOp.clipId);
|
|
83
|
+
collectAdjacentClips(model, transitionOp.trackId, transitionOp.clipId, affectedClips);
|
|
84
|
+
}
|
|
85
|
+
if (transitionOp.trackId) {
|
|
86
|
+
affectedTracks.add(transitionOp.trackId);
|
|
87
|
+
}
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
case "addEffect":
|
|
91
|
+
case "updateEffect":
|
|
92
|
+
case "removeEffect": {
|
|
93
|
+
const effectOp = op;
|
|
94
|
+
if (effectOp.targetType === "track") {
|
|
95
|
+
affectedTracks.add(effectOp.targetId);
|
|
96
|
+
const track = model.findTrack(effectOp.targetId);
|
|
97
|
+
if (track) {
|
|
98
|
+
track.clips.forEach((clip) => affectedClips.add(clip.id));
|
|
99
|
+
}
|
|
100
|
+
} else if (effectOp.targetType === "clip") {
|
|
101
|
+
affectedClips.add(effectOp.targetId);
|
|
102
|
+
}
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function collectOverlappingClips(model, trackId, startUs, endUs, affectedClips) {
|
|
108
|
+
const track = model.findTrack(trackId);
|
|
109
|
+
if (!track) return;
|
|
110
|
+
const overlapping = model.getActiveClips(startUs, endUs);
|
|
111
|
+
overlapping.forEach((clip) => affectedClips.add(clip.id));
|
|
112
|
+
}
|
|
113
|
+
function collectAdjacentClips(model, trackId, clipId, affectedClips) {
|
|
114
|
+
const track = model.findTrack(trackId);
|
|
115
|
+
if (!track) return;
|
|
116
|
+
const clipIndex = track.clips.findIndex((c) => c.id === clipId);
|
|
117
|
+
if (clipIndex === -1) return;
|
|
118
|
+
const prevClip = track.clips[clipIndex - 1];
|
|
119
|
+
if (clipIndex > 0 && prevClip) {
|
|
120
|
+
affectedClips.add(prevClip.id);
|
|
121
|
+
}
|
|
122
|
+
const nextClip = track.clips[clipIndex + 1];
|
|
123
|
+
if (clipIndex < track.clips.length - 1 && nextClip) {
|
|
124
|
+
affectedClips.add(nextClip.id);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
function calculateTimeRanges(affectedClips, affectedTracks, _affectedResources, model) {
|
|
128
|
+
const ranges = [];
|
|
129
|
+
const processedTracks = /* @__PURE__ */ new Set();
|
|
130
|
+
for (const clipId of affectedClips) {
|
|
131
|
+
const clip = model.findClip(clipId);
|
|
132
|
+
if (!clip) continue;
|
|
133
|
+
for (const track of model.tracks) {
|
|
134
|
+
if (track.clips.some((c) => c.id === clipId)) {
|
|
135
|
+
if (!processedTracks.has(track.id)) {
|
|
136
|
+
const range = calculateTrackDirtyRange(track.id, affectedClips, model);
|
|
137
|
+
if (range) {
|
|
138
|
+
ranges.push(range);
|
|
139
|
+
processedTracks.add(track.id);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
for (const trackId of affectedTracks) {
|
|
147
|
+
if (!processedTracks.has(trackId)) {
|
|
148
|
+
const track = model.findTrack(trackId);
|
|
149
|
+
if (track) {
|
|
150
|
+
ranges.push({
|
|
151
|
+
trackId,
|
|
152
|
+
startUs: 0,
|
|
153
|
+
endUs: model.getTrackDuration(trackId),
|
|
154
|
+
reason: "track_operation"
|
|
155
|
+
});
|
|
156
|
+
processedTracks.add(trackId);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return mergeRanges(ranges);
|
|
161
|
+
}
|
|
162
|
+
function calculateTrackDirtyRange(trackId, affectedClips, model) {
|
|
163
|
+
const track = model.findTrack(trackId);
|
|
164
|
+
if (!track) return null;
|
|
165
|
+
let minStartUs = Infinity;
|
|
166
|
+
let maxEndUs = 0;
|
|
167
|
+
let hasAffectedClips = false;
|
|
168
|
+
for (const clip of track.clips) {
|
|
169
|
+
if (affectedClips.has(clip.id)) {
|
|
170
|
+
hasAffectedClips = true;
|
|
171
|
+
minStartUs = Math.min(minStartUs, clip.startUs);
|
|
172
|
+
maxEndUs = Math.max(maxEndUs, clip.startUs + clip.durationUs);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
if (!hasAffectedClips) return null;
|
|
176
|
+
return {
|
|
177
|
+
trackId,
|
|
178
|
+
startUs: minStartUs,
|
|
179
|
+
endUs: maxEndUs,
|
|
180
|
+
reason: "clips_affected"
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
function mergeRanges(ranges) {
|
|
184
|
+
if (ranges.length <= 1) return ranges;
|
|
185
|
+
const trackGroups = /* @__PURE__ */ new Map();
|
|
186
|
+
for (const range of ranges) {
|
|
187
|
+
const group = trackGroups.get(range.trackId) || [];
|
|
188
|
+
group.push(range);
|
|
189
|
+
trackGroups.set(range.trackId, group);
|
|
190
|
+
}
|
|
191
|
+
const merged = [];
|
|
192
|
+
for (const [trackId, trackRanges] of trackGroups) {
|
|
193
|
+
trackRanges.sort((a, b) => a.startUs - b.startUs);
|
|
194
|
+
let current = trackRanges[0];
|
|
195
|
+
for (let i = 1; i < trackRanges.length; i++) {
|
|
196
|
+
const next = trackRanges[i];
|
|
197
|
+
if (next && current && next.startUs <= current.endUs + 1e3) {
|
|
198
|
+
current = {
|
|
199
|
+
trackId,
|
|
200
|
+
startUs: current.startUs,
|
|
201
|
+
endUs: Math.max(current.endUs, next.endUs),
|
|
202
|
+
reason: `${current.reason},${next.reason}`
|
|
203
|
+
};
|
|
204
|
+
} else {
|
|
205
|
+
if (current) {
|
|
206
|
+
merged.push(current);
|
|
207
|
+
}
|
|
208
|
+
current = next;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
if (current) {
|
|
212
|
+
merged.push(current);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return merged;
|
|
216
|
+
}
|
|
217
|
+
export {
|
|
218
|
+
resolveDirtyRanges
|
|
219
|
+
};
|
|
220
|
+
//# sourceMappingURL=dirty-range.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dirty-range.js","sources":["../../src/model/dirty-range.ts"],"sourcesContent":["import { CompositionModel } from './CompositionModel';\nimport { CompositionPatch, PatchOperation, DirtyRange, TimeUs } from './types';\n\nexport function resolveDirtyRanges(patch: CompositionPatch, model: CompositionModel): DirtyRange[] {\n const affectedClips = new Set<string>();\n const affectedTracks = new Set<string>();\n const affectedResources = new Set<string>();\n\n // Collect affected elements\n for (const op of patch.operations) {\n collectAffectedElements(op, model, affectedClips, affectedTracks, affectedResources);\n }\n\n // Calculate time ranges per track\n return calculateTimeRanges(affectedClips, affectedTracks, affectedResources, model);\n}\n\nfunction collectAffectedElements(\n op: PatchOperation,\n model: CompositionModel,\n affectedClips: Set<string>,\n affectedTracks: Set<string>,\n affectedResources: Set<string>\n): void {\n switch (op.type) {\n // Track-level operations affect all clips in the track\n case 'addTrack':\n case 'removeTrack':\n case 'updateTrack': {\n const trackOp = op as any;\n if (trackOp.trackId) {\n affectedTracks.add(trackOp.trackId);\n // Collect all clips in this track\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-level operations\n case 'addClip':\n case 'removeClip':\n case 'updateClip':\n case 'moveClip': {\n const clipOp = op as any;\n if (clipOp.clipId) {\n affectedClips.add(clipOp.clipId);\n }\n if (clipOp.trackId) {\n affectedTracks.add(clipOp.trackId);\n }\n if (clipOp.targetTrackId) {\n affectedTracks.add(clipOp.targetTrackId);\n }\n // Check for overlapping clips\n if (clipOp.clip) {\n collectOverlappingClips(\n model,\n clipOp.trackId,\n clipOp.clip.startUs || 0,\n (clipOp.clip.startUs || 0) + (clipOp.clip.durationUs || 0),\n affectedClips\n );\n }\n break;\n }\n\n // Resource changes affect all clips using that resource\n case 'addResource':\n case 'updateResource':\n case 'removeResource': {\n const resourceOp = op as any;\n affectedResources.add(resourceOp.resourceId);\n // Find all clips using this resource\n for (const track of model.tracks) {\n for (const clip of track.clips) {\n if (clip.resourceId === resourceOp.resourceId) {\n affectedClips.add(clip.id);\n affectedTracks.add(track.id);\n }\n }\n }\n break;\n }\n\n // Attachment operations\n case 'addAttachment':\n case 'updateAttachment':\n case 'removeAttachment': {\n const attachmentOp = op as any;\n if (attachmentOp.clipId) {\n affectedClips.add(attachmentOp.clipId);\n }\n if (attachmentOp.trackId) {\n affectedTracks.add(attachmentOp.trackId);\n }\n break;\n }\n\n // Transition operations\n case 'addTransition':\n case 'updateTransition':\n case 'removeTransition': {\n const transitionOp = op as any;\n if (transitionOp.clipId) {\n affectedClips.add(transitionOp.clipId);\n // Transitions might affect adjacent clips\n collectAdjacentClips(model, transitionOp.trackId, transitionOp.clipId, affectedClips);\n }\n if (transitionOp.trackId) {\n affectedTracks.add(transitionOp.trackId);\n }\n break;\n }\n\n // Effect operations\n case 'addEffect':\n case 'updateEffect':\n case 'removeEffect': {\n const effectOp = op as any;\n if (effectOp.targetType === 'track') {\n affectedTracks.add(effectOp.targetId);\n // Track effects affect all clips in the track\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') {\n affectedClips.add(effectOp.targetId);\n }\n break;\n }\n }\n}\n\nfunction collectOverlappingClips(\n model: CompositionModel,\n trackId: string,\n startUs: TimeUs,\n endUs: TimeUs,\n affectedClips: Set<string>\n): void {\n const track = model.findTrack(trackId);\n if (!track) return;\n\n // Use binary search to find overlapping clips efficiently\n const overlapping = model.getActiveClips(startUs, endUs);\n overlapping.forEach((clip) => affectedClips.add(clip.id));\n}\n\nfunction collectAdjacentClips(\n model: CompositionModel,\n trackId: string,\n clipId: string,\n affectedClips: Set<string>\n): void {\n const track = model.findTrack(trackId);\n if (!track) return;\n\n const clipIndex = track.clips.findIndex((c) => c.id === clipId);\n if (clipIndex === -1) return;\n\n // Add previous clip if exists\n const prevClip = track.clips[clipIndex - 1];\n if (clipIndex > 0 && prevClip) {\n affectedClips.add(prevClip.id);\n }\n\n // Add next clip if exists\n const nextClip = track.clips[clipIndex + 1];\n if (clipIndex < track.clips.length - 1 && nextClip) {\n affectedClips.add(nextClip.id);\n }\n}\n\nfunction calculateTimeRanges(\n affectedClips: Set<string>,\n affectedTracks: Set<string>,\n _affectedResources: Set<string>,\n model: CompositionModel\n): DirtyRange[] {\n const ranges: DirtyRange[] = [];\n const processedTracks = new Set<string>();\n\n // Process affected clips\n for (const clipId of affectedClips) {\n const clip = model.findClip(clipId);\n if (!clip) continue;\n\n // Find the track containing this clip\n for (const track of model.tracks) {\n if (track.clips.some((c) => c.id === clipId)) {\n if (!processedTracks.has(track.id)) {\n const range = calculateTrackDirtyRange(track.id, affectedClips, model);\n if (range) {\n ranges.push(range);\n processedTracks.add(track.id);\n }\n }\n break;\n }\n }\n }\n\n // Process tracks that were directly affected but haven't been processed yet\n for (const trackId of affectedTracks) {\n if (!processedTracks.has(trackId)) {\n const track = model.findTrack(trackId);\n if (track) {\n ranges.push({\n trackId,\n startUs: 0,\n endUs: model.getTrackDuration(trackId),\n reason: 'track_operation',\n });\n processedTracks.add(trackId);\n }\n }\n }\n\n return mergeRanges(ranges);\n}\n\nfunction calculateTrackDirtyRange(\n trackId: string,\n affectedClips: Set<string>,\n model: CompositionModel\n): DirtyRange | null {\n const track = model.findTrack(trackId);\n if (!track) return null;\n\n let minStartUs = Infinity;\n let maxEndUs = 0;\n let hasAffectedClips = false;\n\n for (const clip of track.clips) {\n if (affectedClips.has(clip.id)) {\n hasAffectedClips = true;\n minStartUs = Math.min(minStartUs, clip.startUs);\n maxEndUs = Math.max(maxEndUs, clip.startUs + clip.durationUs);\n }\n }\n\n if (!hasAffectedClips) return null;\n\n return {\n trackId,\n startUs: minStartUs,\n endUs: maxEndUs,\n reason: 'clips_affected',\n };\n}\n\nfunction mergeRanges(ranges: DirtyRange[]): DirtyRange[] {\n if (ranges.length <= 1) return ranges;\n\n // Group by trackId\n const trackGroups = new Map<string, DirtyRange[]>();\n for (const range of ranges) {\n const group = trackGroups.get(range.trackId) || [];\n group.push(range);\n trackGroups.set(range.trackId, group);\n }\n\n // Merge overlapping ranges within each track\n const merged: DirtyRange[] = [];\n for (const [trackId, trackRanges] of trackGroups) {\n trackRanges.sort((a, b) => a.startUs - b.startUs);\n\n let current = trackRanges[0];\n for (let i = 1; i < trackRanges.length; i++) {\n const next = trackRanges[i];\n // Merge if overlapping or adjacent (within 1ms)\n if (next && current && next.startUs <= current.endUs + 1000) {\n current = {\n trackId,\n startUs: current.startUs,\n endUs: Math.max(current.endUs, next.endUs),\n reason: `${current.reason},${next.reason}`,\n };\n } else {\n if (current) {\n merged.push(current);\n }\n current = next;\n }\n }\n if (current) {\n merged.push(current);\n }\n }\n\n return merged;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export * from './types';
|
|
2
|
+
export { CompositionModel } from './CompositionModel';
|
|
3
|
+
export { resolveDirtyRanges } from './dirty-range';
|
|
4
|
+
export { RcFrame } from './RcFrame';
|
|
5
|
+
export type { RcFrameMetadata } from './RcFrame';
|
|
6
|
+
export { applyPatch } from './patch';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/model/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,YAAY,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"patch.d.ts","sourceRoot":"","sources":["../../src/model/patch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,EACL,gBAAgB,EAQhB,UAAU,EAOX,MAAM,SAAS,CAAC;AAEjB,wBAAgB,UAAU,CAAC,KAAK,EAAE,gBAAgB,EAAE,KAAK,EAAE,gBAAgB,GAAG,UAAU,EAAE,CAQzF"}
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
import { resolveDirtyRanges } from "./dirty-range.js";
|
|
2
|
+
function applyPatch(model, patch) {
|
|
3
|
+
for (const op of patch.operations) {
|
|
4
|
+
applyOperation(model, op);
|
|
5
|
+
}
|
|
6
|
+
return resolveDirtyRanges(patch, model);
|
|
7
|
+
}
|
|
8
|
+
function applyOperation(model, op) {
|
|
9
|
+
switch (op.type) {
|
|
10
|
+
case "addTrack":
|
|
11
|
+
addTrack(model, op);
|
|
12
|
+
break;
|
|
13
|
+
case "removeTrack":
|
|
14
|
+
removeTrack(model, op);
|
|
15
|
+
break;
|
|
16
|
+
case "updateTrack":
|
|
17
|
+
updateTrack(model, op);
|
|
18
|
+
break;
|
|
19
|
+
case "addClip":
|
|
20
|
+
addClip(model, op);
|
|
21
|
+
break;
|
|
22
|
+
case "removeClip":
|
|
23
|
+
removeClip(model, op);
|
|
24
|
+
break;
|
|
25
|
+
case "updateClip":
|
|
26
|
+
updateClip(model, op);
|
|
27
|
+
break;
|
|
28
|
+
case "moveClip":
|
|
29
|
+
moveClip(model, op);
|
|
30
|
+
break;
|
|
31
|
+
case "addResource":
|
|
32
|
+
addResource(model, op);
|
|
33
|
+
break;
|
|
34
|
+
case "updateResource":
|
|
35
|
+
updateResource(model, op);
|
|
36
|
+
break;
|
|
37
|
+
case "removeResource":
|
|
38
|
+
removeResource(model, op);
|
|
39
|
+
break;
|
|
40
|
+
case "addAttachment":
|
|
41
|
+
addAttachment(model, op);
|
|
42
|
+
break;
|
|
43
|
+
case "updateAttachment":
|
|
44
|
+
updateAttachment(model, op);
|
|
45
|
+
break;
|
|
46
|
+
case "removeAttachment":
|
|
47
|
+
removeAttachment(model, op);
|
|
48
|
+
break;
|
|
49
|
+
case "addTransition":
|
|
50
|
+
case "updateTransition":
|
|
51
|
+
case "removeTransition":
|
|
52
|
+
handleTransition(model, op);
|
|
53
|
+
break;
|
|
54
|
+
case "addEffect":
|
|
55
|
+
case "updateEffect":
|
|
56
|
+
case "removeEffect":
|
|
57
|
+
handleEffect(model, op);
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function addTrack(model, op) {
|
|
62
|
+
if (!op.track) return;
|
|
63
|
+
const newTrack = {
|
|
64
|
+
id: op.track.id || `track_${Date.now()}`,
|
|
65
|
+
kind: op.track.kind || "video",
|
|
66
|
+
clips: op.track.clips || [],
|
|
67
|
+
effects: op.track.effects,
|
|
68
|
+
duckingRules: op.track.duckingRules
|
|
69
|
+
};
|
|
70
|
+
model.tracks.push(newTrack);
|
|
71
|
+
rebuildIndexes(model);
|
|
72
|
+
}
|
|
73
|
+
function removeTrack(model, op) {
|
|
74
|
+
if (!op.trackId) return;
|
|
75
|
+
const index = model.tracks.findIndex((t) => t.id === op.trackId);
|
|
76
|
+
if (index === -1) return;
|
|
77
|
+
model.tracks.splice(index, 1);
|
|
78
|
+
rebuildIndexes(model);
|
|
79
|
+
}
|
|
80
|
+
function updateTrack(model, op) {
|
|
81
|
+
if (!op.trackId || !op.track) return;
|
|
82
|
+
const track = model.findTrack(op.trackId);
|
|
83
|
+
if (!track) return;
|
|
84
|
+
Object.assign(track, op.track);
|
|
85
|
+
}
|
|
86
|
+
function addClip(model, op) {
|
|
87
|
+
const track = model.findTrack(op.trackId);
|
|
88
|
+
if (!track || !op.clip) return;
|
|
89
|
+
const newClip = {
|
|
90
|
+
id: op.clip.id || `clip_${Date.now()}`,
|
|
91
|
+
resourceId: op.clip.resourceId,
|
|
92
|
+
startUs: op.clip.startUs,
|
|
93
|
+
durationUs: op.clip.durationUs,
|
|
94
|
+
trimStartUs: op.clip.trimStartUs,
|
|
95
|
+
trimEndUs: op.clip.trimEndUs,
|
|
96
|
+
effects: op.clip.effects,
|
|
97
|
+
attachments: op.clip.attachments,
|
|
98
|
+
transitionIn: op.clip.transitionIn,
|
|
99
|
+
transitionOut: op.clip.transitionOut
|
|
100
|
+
};
|
|
101
|
+
const insertIndex = track.clips.findIndex((c) => c.startUs > newClip.startUs);
|
|
102
|
+
if (insertIndex === -1) {
|
|
103
|
+
track.clips.push(newClip);
|
|
104
|
+
} else {
|
|
105
|
+
track.clips.splice(insertIndex, 0, newClip);
|
|
106
|
+
}
|
|
107
|
+
rebuildIndexes(model);
|
|
108
|
+
}
|
|
109
|
+
function removeClip(model, op) {
|
|
110
|
+
const track = model.findTrack(op.trackId);
|
|
111
|
+
if (!track || !op.clipId) return;
|
|
112
|
+
const clipIndex = track.clips.findIndex((c) => c.id === op.clipId);
|
|
113
|
+
if (clipIndex === -1) return;
|
|
114
|
+
track.clips.splice(clipIndex, 1);
|
|
115
|
+
rebuildIndexes(model);
|
|
116
|
+
}
|
|
117
|
+
function updateClip(model, op) {
|
|
118
|
+
const clip = model.findClip(op.clipId);
|
|
119
|
+
if (!clip || !op.clip) return;
|
|
120
|
+
Object.assign(clip, op.clip);
|
|
121
|
+
if (op.clip.startUs !== void 0) {
|
|
122
|
+
const track = model.findTrack(op.trackId);
|
|
123
|
+
if (track) {
|
|
124
|
+
track.clips.sort((a, b) => a.startUs - b.startUs);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
function moveClip(model, op) {
|
|
129
|
+
if (!op.clipId || !op.targetTrackId) return;
|
|
130
|
+
const sourceTrack = model.findTrack(op.trackId);
|
|
131
|
+
const targetTrack = model.findTrack(op.targetTrackId);
|
|
132
|
+
const clip = model.findClip(op.clipId);
|
|
133
|
+
if (!sourceTrack || !targetTrack || !clip) return;
|
|
134
|
+
const clipIndex = sourceTrack.clips.findIndex((c) => c.id === op.clipId);
|
|
135
|
+
if (clipIndex === -1) return;
|
|
136
|
+
sourceTrack.clips.splice(clipIndex, 1);
|
|
137
|
+
if (op.targetStartUs !== void 0) {
|
|
138
|
+
clip.startUs = op.targetStartUs;
|
|
139
|
+
}
|
|
140
|
+
const insertIndex = targetTrack.clips.findIndex((c) => c.startUs > clip.startUs);
|
|
141
|
+
if (insertIndex === -1) {
|
|
142
|
+
targetTrack.clips.push(clip);
|
|
143
|
+
} else {
|
|
144
|
+
targetTrack.clips.splice(insertIndex, 0, clip);
|
|
145
|
+
}
|
|
146
|
+
rebuildIndexes(model);
|
|
147
|
+
}
|
|
148
|
+
function addResource(model, op) {
|
|
149
|
+
if (!op.resource) return;
|
|
150
|
+
const newResource = {
|
|
151
|
+
id: op.resourceId,
|
|
152
|
+
type: op.resource.type,
|
|
153
|
+
uri: op.resource.uri,
|
|
154
|
+
metadata: op.resource.metadata,
|
|
155
|
+
state: op.resource.state || "pending"
|
|
156
|
+
};
|
|
157
|
+
model.resources.set(op.resourceId, newResource);
|
|
158
|
+
}
|
|
159
|
+
function updateResource(model, op) {
|
|
160
|
+
const resource = model.getResource(op.resourceId);
|
|
161
|
+
if (!resource || !op.resource) return;
|
|
162
|
+
Object.assign(resource, op.resource);
|
|
163
|
+
}
|
|
164
|
+
function removeResource(model, op) {
|
|
165
|
+
if (!model.resources.has(op.resourceId)) return;
|
|
166
|
+
model.resources.delete(op.resourceId);
|
|
167
|
+
}
|
|
168
|
+
function addAttachment(model, op) {
|
|
169
|
+
const clip = model.findClip(op.clipId);
|
|
170
|
+
if (!clip || !op.attachment) return;
|
|
171
|
+
if (!clip.attachments) {
|
|
172
|
+
clip.attachments = [];
|
|
173
|
+
}
|
|
174
|
+
const newAttachment = {
|
|
175
|
+
id: op.attachment.id || `attachment_${Date.now()}`,
|
|
176
|
+
kind: op.attachment.kind,
|
|
177
|
+
startUs: op.attachment.startUs,
|
|
178
|
+
durationUs: op.attachment.durationUs,
|
|
179
|
+
data: op.attachment.data
|
|
180
|
+
};
|
|
181
|
+
clip.attachments.push(newAttachment);
|
|
182
|
+
}
|
|
183
|
+
function updateAttachment(model, op) {
|
|
184
|
+
const clip = model.findClip(op.clipId);
|
|
185
|
+
if (!clip || !clip.attachments || !op.attachmentId || !op.attachment) return;
|
|
186
|
+
const attachment = clip.attachments.find((a) => a.id === op.attachmentId);
|
|
187
|
+
if (!attachment) return;
|
|
188
|
+
Object.assign(attachment, op.attachment);
|
|
189
|
+
}
|
|
190
|
+
function removeAttachment(model, op) {
|
|
191
|
+
const clip = model.findClip(op.clipId);
|
|
192
|
+
if (!clip || !clip.attachments || !op.attachmentId) return;
|
|
193
|
+
const attachmentIndex = clip.attachments.findIndex((a) => a.id === op.attachmentId);
|
|
194
|
+
if (attachmentIndex === -1) return;
|
|
195
|
+
clip.attachments.splice(attachmentIndex, 1);
|
|
196
|
+
}
|
|
197
|
+
function handleTransition(model, op) {
|
|
198
|
+
const clip = model.findClip(op.clipId);
|
|
199
|
+
if (!clip) return;
|
|
200
|
+
if (op.position === "in") {
|
|
201
|
+
if (op.type === "removeTransition") {
|
|
202
|
+
clip.transitionIn = void 0;
|
|
203
|
+
} else {
|
|
204
|
+
clip.transitionIn = op.transition;
|
|
205
|
+
}
|
|
206
|
+
} else {
|
|
207
|
+
if (op.type === "removeTransition") {
|
|
208
|
+
clip.transitionOut = void 0;
|
|
209
|
+
} else {
|
|
210
|
+
clip.transitionOut = op.transition;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
function handleEffect(model, op) {
|
|
215
|
+
if (op.targetType === "track") {
|
|
216
|
+
const track = model.findTrack(op.targetId);
|
|
217
|
+
if (!track) return;
|
|
218
|
+
if (!track.effects) track.effects = [];
|
|
219
|
+
if (op.type === "addEffect" && op.effect) {
|
|
220
|
+
track.effects.push(op.effect);
|
|
221
|
+
} else if (op.type === "removeEffect" && op.effectId) {
|
|
222
|
+
const index = track.effects.findIndex((e) => e.id === op.effectId);
|
|
223
|
+
if (index !== -1) track.effects.splice(index, 1);
|
|
224
|
+
} else if (op.type === "updateEffect" && op.effectId && op.effect) {
|
|
225
|
+
const effect = track.effects.find((e) => e.id === op.effectId);
|
|
226
|
+
if (effect) Object.assign(effect, op.effect);
|
|
227
|
+
}
|
|
228
|
+
} else {
|
|
229
|
+
const clip = model.findClip(op.targetId);
|
|
230
|
+
if (!clip) return;
|
|
231
|
+
if (!clip.effects) clip.effects = [];
|
|
232
|
+
if (op.type === "addEffect" && op.effect) {
|
|
233
|
+
clip.effects.push(op.effect);
|
|
234
|
+
} else if (op.type === "removeEffect" && op.effectId) {
|
|
235
|
+
const index = clip.effects.findIndex((e) => e.id === op.effectId);
|
|
236
|
+
if (index !== -1) clip.effects.splice(index, 1);
|
|
237
|
+
} else if (op.type === "updateEffect" && op.effectId && op.effect) {
|
|
238
|
+
const effect = clip.effects.find((e) => e.id === op.effectId);
|
|
239
|
+
if (effect) Object.assign(effect, op.effect);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
function rebuildIndexes(model) {
|
|
244
|
+
model.buildIndexes();
|
|
245
|
+
model.durationUs = model.calculateDuration();
|
|
246
|
+
}
|
|
247
|
+
export {
|
|
248
|
+
applyPatch
|
|
249
|
+
};
|
|
250
|
+
//# sourceMappingURL=patch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"patch.js","sources":["../../src/model/patch.ts"],"sourcesContent":["import { CompositionModel } from './CompositionModel';\nimport { resolveDirtyRanges } from './dirty-range';\nimport {\n CompositionPatch,\n PatchOperation,\n TrackOperation,\n ClipOperation,\n ResourceOperation,\n AttachmentOperation,\n TransitionOperation,\n EffectOperation,\n DirtyRange,\n Track,\n Clip,\n Resource,\n Attachment,\n Transition,\n Effect,\n} from './types';\n\nexport function applyPatch(model: CompositionModel, patch: CompositionPatch): DirtyRange[] {\n // Apply all operations first\n for (const op of patch.operations) {\n applyOperation(model, op);\n }\n\n // Then calculate dirty ranges using resolveDirtyRanges\n return resolveDirtyRanges(patch, model);\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 rebuildIndexes(model);\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 rebuildIndexes(model);\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}\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 const newClip: Clip = {\n id: op.clip.id || `clip_${Date.now()}`,\n resourceId: op.clip.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 };\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 rebuildIndexes(model);\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 track.clips.splice(clipIndex, 1);\n rebuildIndexes(model);\n}\n\nfunction updateClip(model: CompositionModel, op: ClipOperation): void {\n const clip = model.findClip(op.clipId!);\n if (!clip || !op.clip) return;\n\n Object.assign(clip, op.clip);\n\n // Re-sort if startUs changed\n if (op.clip.startUs !== undefined) {\n const track = model.findTrack(op.trackId);\n if (track) {\n track.clips.sort((a, b) => a.startUs - b.startUs);\n }\n }\n}\n\nfunction 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 // 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\n// Helper functions\nfunction rebuildIndexes(model: CompositionModel): void {\n // Trigger index rebuild in CompositionModel\n (model as any).buildIndexes();\n model.durationUs = (model as any).calculateDuration();\n}\n"],"names":[],"mappings":"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"}
|