@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,47 @@
|
|
|
1
|
+
import { Resource } from '../../model';
|
|
2
|
+
|
|
3
|
+
type TrackSample = {
|
|
4
|
+
timeUs: number;
|
|
5
|
+
byteOffset: number;
|
|
6
|
+
byteSize: number;
|
|
7
|
+
isKey: boolean;
|
|
8
|
+
};
|
|
9
|
+
type TrackIndex = {
|
|
10
|
+
trackId: number;
|
|
11
|
+
timescale: number;
|
|
12
|
+
samples: TrackSample[];
|
|
13
|
+
};
|
|
14
|
+
interface ResolverOptions {
|
|
15
|
+
maxMoovBytes?: number;
|
|
16
|
+
maxInitialFetchBytes?: number;
|
|
17
|
+
}
|
|
18
|
+
export interface ByteRange {
|
|
19
|
+
byteStart: number;
|
|
20
|
+
byteEnd: number;
|
|
21
|
+
alignedToKeyframe: boolean;
|
|
22
|
+
}
|
|
23
|
+
interface ResolverState {
|
|
24
|
+
resource: Resource;
|
|
25
|
+
status: 'pending' | 'ready' | 'failed';
|
|
26
|
+
promise: Promise<void>;
|
|
27
|
+
trackIndex?: TrackIndex;
|
|
28
|
+
error?: Error;
|
|
29
|
+
}
|
|
30
|
+
export declare class WindowByteRangeResolver {
|
|
31
|
+
private maxMoovBytes;
|
|
32
|
+
private initialFetchBytes;
|
|
33
|
+
private states;
|
|
34
|
+
constructor(options?: ResolverOptions);
|
|
35
|
+
ensureReady(resource: Resource): Promise<void>;
|
|
36
|
+
resolveWindow(resourceId: string, startUs: number, endUs: number): ByteRange | null;
|
|
37
|
+
getStatus(resourceId: string): ResolverState['status'] | undefined;
|
|
38
|
+
dispose(): void;
|
|
39
|
+
private buildIndex;
|
|
40
|
+
private createTrackIndex;
|
|
41
|
+
private findStartSampleIndex;
|
|
42
|
+
private findEndSampleIndex;
|
|
43
|
+
private binarySearch;
|
|
44
|
+
private resolveSampleByteOffset;
|
|
45
|
+
}
|
|
46
|
+
export {};
|
|
47
|
+
//# sourceMappingURL=WindowByteRangeResolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WindowByteRangeResolver.d.ts","sourceRoot":"","sources":["../../../src/stages/load/WindowByteRangeResolver.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,KAAK,WAAW,GAAG;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,KAAK,UAAU,GAAG;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,WAAW,EAAE,CAAC;CACxB,CAAC;AAEF,UAAU,eAAe;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,EAAE,OAAO,CAAC;CAC5B;AAED,UAAU,aAAa;IACrB,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE,SAAS,GAAG,OAAO,GAAG,QAAQ,CAAC;IACvC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAKD,qBAAa,uBAAuB;IAClC,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,MAAM,CAAoC;gBAEtC,OAAO,CAAC,EAAE,eAAe;IAKrC,WAAW,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAgC9C,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAyCnF,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,aAAa,CAAC,QAAQ,CAAC,GAAG,SAAS;IAIlE,OAAO,IAAI,IAAI;YAID,UAAU;IAyFxB,OAAO,CAAC,gBAAgB;IAwCxB,OAAO,CAAC,oBAAoB;IAwB5B,OAAO,CAAC,kBAAkB;IAiB1B,OAAO,CAAC,YAAY;IA6BpB,OAAO,CAAC,uBAAuB;CA8ChC"}
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import "../../node_modules/.pnpm/mp4box@0.5.4/node_modules/mp4box/dist/mp4box.all.js";
|
|
2
|
+
import { __exports as mp4box_all } from "../../_virtual/mp4box.all.js";
|
|
3
|
+
const DEFAULT_MAX_MOOV_BYTES = 4 * 1024 * 1024;
|
|
4
|
+
const DEFAULT_INITIAL_FETCH_BYTES = 1024 * 1024;
|
|
5
|
+
class WindowByteRangeResolver {
|
|
6
|
+
maxMoovBytes;
|
|
7
|
+
initialFetchBytes;
|
|
8
|
+
states = /* @__PURE__ */ new Map();
|
|
9
|
+
constructor(options) {
|
|
10
|
+
this.maxMoovBytes = options?.maxMoovBytes ?? DEFAULT_MAX_MOOV_BYTES;
|
|
11
|
+
this.initialFetchBytes = options?.maxInitialFetchBytes ?? DEFAULT_INITIAL_FETCH_BYTES;
|
|
12
|
+
}
|
|
13
|
+
ensureReady(resource) {
|
|
14
|
+
if (!resource.id) {
|
|
15
|
+
return Promise.reject(new Error("Resource id missing"));
|
|
16
|
+
}
|
|
17
|
+
const existing = this.states.get(resource.id);
|
|
18
|
+
if (existing) {
|
|
19
|
+
if (existing.status === "failed") {
|
|
20
|
+
return Promise.reject(existing.error ?? new Error("Resolver failed"));
|
|
21
|
+
}
|
|
22
|
+
return existing.promise;
|
|
23
|
+
}
|
|
24
|
+
const promise = this.buildIndex(resource).catch((error) => {
|
|
25
|
+
const state = this.states.get(resource.id);
|
|
26
|
+
if (state) {
|
|
27
|
+
state.status = "failed";
|
|
28
|
+
state.error = error instanceof Error ? error : new Error(String(error));
|
|
29
|
+
}
|
|
30
|
+
throw error;
|
|
31
|
+
});
|
|
32
|
+
this.states.set(resource.id, {
|
|
33
|
+
resource,
|
|
34
|
+
status: "pending",
|
|
35
|
+
promise
|
|
36
|
+
});
|
|
37
|
+
return promise;
|
|
38
|
+
}
|
|
39
|
+
resolveWindow(resourceId, startUs, endUs) {
|
|
40
|
+
const state = this.states.get(resourceId);
|
|
41
|
+
if (!state || state.status !== "ready" || !state.trackIndex) {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
const { samples } = state.trackIndex;
|
|
45
|
+
if (!samples.length) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
const startSampleIndex = this.findStartSampleIndex(samples, startUs);
|
|
49
|
+
const endSampleIndex = this.findEndSampleIndex(samples, endUs, startSampleIndex);
|
|
50
|
+
if (startSampleIndex < 0 || endSampleIndex < 0) {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
const startSample = samples[startSampleIndex];
|
|
54
|
+
const endSample = samples[endSampleIndex];
|
|
55
|
+
if (!startSample || !endSample) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
const alignedToKeyframe = startSample.isKey;
|
|
59
|
+
const byteStart = startSample.byteOffset;
|
|
60
|
+
const byteEnd = endSample.byteOffset + endSample.byteSize - 1;
|
|
61
|
+
if (Number.isNaN(byteStart) || Number.isNaN(byteEnd) || byteEnd < byteStart) {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
byteStart,
|
|
66
|
+
byteEnd,
|
|
67
|
+
alignedToKeyframe
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
getStatus(resourceId) {
|
|
71
|
+
return this.states.get(resourceId)?.status;
|
|
72
|
+
}
|
|
73
|
+
dispose() {
|
|
74
|
+
this.states.clear();
|
|
75
|
+
}
|
|
76
|
+
async buildIndex(resource) {
|
|
77
|
+
if (!resource.uri) {
|
|
78
|
+
throw new Error(`Resource ${resource.id} missing uri`);
|
|
79
|
+
}
|
|
80
|
+
const mp4boxFile = mp4box_all.createFile();
|
|
81
|
+
const buffers = [];
|
|
82
|
+
let totalFetched = 0;
|
|
83
|
+
let readyInfo;
|
|
84
|
+
let trackIndex;
|
|
85
|
+
const readyPromise = new Promise((resolve, reject) => {
|
|
86
|
+
mp4boxFile.onReady = (info) => {
|
|
87
|
+
readyInfo = info;
|
|
88
|
+
resolve();
|
|
89
|
+
};
|
|
90
|
+
mp4boxFile.onError = (error) => {
|
|
91
|
+
reject(error instanceof Error ? error : new Error(String(error)));
|
|
92
|
+
};
|
|
93
|
+
});
|
|
94
|
+
while (totalFetched < this.maxMoovBytes) {
|
|
95
|
+
const chunkSize = Math.min(
|
|
96
|
+
this.initialFetchBytes * Math.pow(2, buffers.length),
|
|
97
|
+
this.maxMoovBytes - totalFetched
|
|
98
|
+
);
|
|
99
|
+
const rangeStart = totalFetched;
|
|
100
|
+
const rangeEnd = totalFetched + chunkSize - 1;
|
|
101
|
+
const response = await fetch(resource.uri, {
|
|
102
|
+
headers: {
|
|
103
|
+
Range: `bytes=${rangeStart}-${rangeEnd}`
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
if (!response.ok) {
|
|
107
|
+
throw new Error(`Failed to fetch range ${rangeStart}-${rangeEnd}: HTTP ${response.status}`);
|
|
108
|
+
}
|
|
109
|
+
const buffer = await response.arrayBuffer();
|
|
110
|
+
buffer.fileStart = rangeStart;
|
|
111
|
+
totalFetched += buffer.byteLength;
|
|
112
|
+
buffers.push(buffer);
|
|
113
|
+
mp4boxFile.appendBuffer(buffer);
|
|
114
|
+
try {
|
|
115
|
+
await readyPromise;
|
|
116
|
+
break;
|
|
117
|
+
} catch (error) {
|
|
118
|
+
if (totalFetched >= this.maxMoovBytes) {
|
|
119
|
+
throw error;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (readyInfo) {
|
|
124
|
+
for (const track of readyInfo.tracks ?? []) {
|
|
125
|
+
const extractionOptions = {
|
|
126
|
+
rapAlignment: false,
|
|
127
|
+
keepSamples: true
|
|
128
|
+
};
|
|
129
|
+
const totalSamples = track?.samples?.length ?? track?.sample_count;
|
|
130
|
+
if (typeof totalSamples === "number" && Number.isFinite(totalSamples) && totalSamples > 0) {
|
|
131
|
+
extractionOptions.nbSamples = totalSamples;
|
|
132
|
+
}
|
|
133
|
+
mp4boxFile.setExtractionOptions(track.id, null, extractionOptions);
|
|
134
|
+
}
|
|
135
|
+
mp4boxFile.start();
|
|
136
|
+
mp4boxFile.flush();
|
|
137
|
+
trackIndex = this.createTrackIndex(mp4boxFile, readyInfo);
|
|
138
|
+
}
|
|
139
|
+
if (!trackIndex) {
|
|
140
|
+
throw new Error("Failed to build track index");
|
|
141
|
+
}
|
|
142
|
+
const state = this.states.get(resource.id);
|
|
143
|
+
if (state) {
|
|
144
|
+
state.status = "ready";
|
|
145
|
+
state.trackIndex = trackIndex;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
createTrackIndex(mp4boxFile, info) {
|
|
149
|
+
const videoTrack = info.tracks?.find((track) => track.type === "video");
|
|
150
|
+
if (!videoTrack) {
|
|
151
|
+
throw new Error("No video track found");
|
|
152
|
+
}
|
|
153
|
+
const timescale = videoTrack.timescale || 9e4;
|
|
154
|
+
const trackId = videoTrack.id;
|
|
155
|
+
let samples = mp4boxFile.getTrackSamples?.(trackId) ?? [];
|
|
156
|
+
if ((!samples || samples.length === 0) && typeof mp4boxFile.getTrackById === "function") {
|
|
157
|
+
const fullTrack = mp4boxFile.getTrackById(trackId);
|
|
158
|
+
if (fullTrack?.samples?.length) {
|
|
159
|
+
samples = fullTrack.samples;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
const indexedSamples = (samples ?? []).map((sample, index) => {
|
|
163
|
+
const sampleByteOffset = this.resolveSampleByteOffset(mp4boxFile, trackId, sample, index);
|
|
164
|
+
const timeUs = Math.round(sample.cts * 1e6 / timescale);
|
|
165
|
+
return {
|
|
166
|
+
timeUs,
|
|
167
|
+
byteOffset: sampleByteOffset,
|
|
168
|
+
byteSize: sample.size,
|
|
169
|
+
isKey: Boolean(sample.is_sync)
|
|
170
|
+
};
|
|
171
|
+
});
|
|
172
|
+
return {
|
|
173
|
+
trackId,
|
|
174
|
+
timescale,
|
|
175
|
+
samples: indexedSamples
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
findStartSampleIndex(samples, targetUs) {
|
|
179
|
+
if (!samples.length) {
|
|
180
|
+
return 0;
|
|
181
|
+
}
|
|
182
|
+
let index = this.binarySearch(samples, targetUs, (sample, time) => sample.timeUs - time);
|
|
183
|
+
if (index < 0) {
|
|
184
|
+
index = ~index;
|
|
185
|
+
if (index >= samples.length) {
|
|
186
|
+
index = samples.length - 1;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
while (index > 0) {
|
|
190
|
+
const current = samples[index];
|
|
191
|
+
if (!current || current.isKey) {
|
|
192
|
+
break;
|
|
193
|
+
}
|
|
194
|
+
index -= 1;
|
|
195
|
+
}
|
|
196
|
+
return index;
|
|
197
|
+
}
|
|
198
|
+
findEndSampleIndex(samples, targetUs, startIndex) {
|
|
199
|
+
if (!samples.length) {
|
|
200
|
+
return 0;
|
|
201
|
+
}
|
|
202
|
+
let index = Math.min(Math.max(startIndex, 0), samples.length - 1);
|
|
203
|
+
while (index + 1 < samples.length) {
|
|
204
|
+
const nextSample = samples[index + 1];
|
|
205
|
+
if (!nextSample || nextSample.timeUs > targetUs) {
|
|
206
|
+
break;
|
|
207
|
+
}
|
|
208
|
+
index += 1;
|
|
209
|
+
}
|
|
210
|
+
return index;
|
|
211
|
+
}
|
|
212
|
+
binarySearch(samples, targetUs, compare) {
|
|
213
|
+
let low = 0;
|
|
214
|
+
let high = samples.length - 1;
|
|
215
|
+
while (low <= high) {
|
|
216
|
+
const mid = Math.floor((low + high) / 2);
|
|
217
|
+
const sample = samples[mid];
|
|
218
|
+
if (!sample) {
|
|
219
|
+
break;
|
|
220
|
+
}
|
|
221
|
+
const cmp = compare(sample, targetUs);
|
|
222
|
+
if (cmp === 0) {
|
|
223
|
+
return mid;
|
|
224
|
+
}
|
|
225
|
+
if (cmp < 0) {
|
|
226
|
+
low = mid + 1;
|
|
227
|
+
} else {
|
|
228
|
+
high = mid - 1;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return ~low;
|
|
232
|
+
}
|
|
233
|
+
resolveSampleByteOffset(mp4boxFile, trackId, sample, sampleIndex) {
|
|
234
|
+
if (typeof sample.position === "number" && Number.isFinite(sample.position)) {
|
|
235
|
+
return sample.position;
|
|
236
|
+
}
|
|
237
|
+
const trak = mp4boxFile.getTrackById?.(trackId);
|
|
238
|
+
if (!trak) {
|
|
239
|
+
return NaN;
|
|
240
|
+
}
|
|
241
|
+
const chunkRefs = trak?.samples;
|
|
242
|
+
const chunkIndex = sample.chunk_index ?? sample.chunk_index_in_trak ?? sample.chunkIndex;
|
|
243
|
+
const chunkOffset = typeof chunkIndex === "number" ? trak?.stco?.chunk_offsets?.[chunkIndex] : void 0;
|
|
244
|
+
if (typeof chunkOffset === "number" && Number.isFinite(chunkOffset)) {
|
|
245
|
+
const offsetInChunk = typeof sample.offset === "number" ? sample.offset : 0;
|
|
246
|
+
return chunkOffset + offsetInChunk;
|
|
247
|
+
}
|
|
248
|
+
if (Array.isArray(chunkRefs) && chunkIndex >= 0 && chunkIndex < chunkRefs.length) {
|
|
249
|
+
const chunk = chunkRefs[chunkIndex];
|
|
250
|
+
if (chunk && typeof chunk.offset === "number") {
|
|
251
|
+
return chunk.offset;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
if (sample.fileStart && typeof sample.fileStart === "number") {
|
|
255
|
+
return sample.fileStart;
|
|
256
|
+
}
|
|
257
|
+
const positions = mp4boxFile.getTrackSamplePositions?.(trackId);
|
|
258
|
+
if (Array.isArray(positions) && sampleIndex < positions.length) {
|
|
259
|
+
const pos = positions[sampleIndex];
|
|
260
|
+
if (typeof pos === "number") {
|
|
261
|
+
return pos;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
return NaN;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
export {
|
|
268
|
+
WindowByteRangeResolver
|
|
269
|
+
};
|
|
270
|
+
//# sourceMappingURL=WindowByteRangeResolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WindowByteRangeResolver.js","sources":["../../../src/stages/load/WindowByteRangeResolver.ts"],"sourcesContent":["import * as MP4Box from 'mp4box';\nimport type { MP4BoxFile } from 'mp4box';\nimport type { Resource } from '../../model';\n\ntype TrackSample = {\n timeUs: number;\n byteOffset: number;\n byteSize: number;\n isKey: boolean;\n};\n\ntype TrackIndex = {\n trackId: number;\n timescale: number;\n samples: TrackSample[];\n};\n\ninterface ResolverOptions {\n maxMoovBytes?: number;\n maxInitialFetchBytes?: number;\n}\n\nexport interface ByteRange {\n byteStart: number;\n byteEnd: number;\n alignedToKeyframe: boolean;\n}\n\ninterface ResolverState {\n resource: Resource;\n status: 'pending' | 'ready' | 'failed';\n promise: Promise<void>;\n trackIndex?: TrackIndex;\n error?: Error;\n}\n\nconst DEFAULT_MAX_MOOV_BYTES = 4 * 1024 * 1024;\nconst DEFAULT_INITIAL_FETCH_BYTES = 1024 * 1024;\n\nexport class WindowByteRangeResolver {\n private maxMoovBytes: number;\n private initialFetchBytes: number;\n private states = new Map<string, ResolverState>();\n\n constructor(options?: ResolverOptions) {\n this.maxMoovBytes = options?.maxMoovBytes ?? DEFAULT_MAX_MOOV_BYTES;\n this.initialFetchBytes = options?.maxInitialFetchBytes ?? DEFAULT_INITIAL_FETCH_BYTES;\n }\n\n ensureReady(resource: Resource): Promise<void> {\n // console.log('>>>>>>>>>>>>>> ensureReady', resource.id, resource.type, resource.state);\n if (!resource.id) {\n return Promise.reject(new Error('Resource id missing'));\n }\n\n const existing = this.states.get(resource.id);\n if (existing) {\n if (existing.status === 'failed') {\n return Promise.reject(existing.error ?? new Error('Resolver failed'));\n }\n return existing.promise;\n }\n\n const promise = this.buildIndex(resource).catch((error) => {\n const state = this.states.get(resource.id);\n if (state) {\n state.status = 'failed';\n state.error = error instanceof Error ? error : new Error(String(error));\n }\n throw error;\n });\n\n this.states.set(resource.id, {\n resource,\n status: 'pending',\n promise,\n });\n\n return promise;\n }\n\n resolveWindow(resourceId: string, startUs: number, endUs: number): ByteRange | null {\n const state = this.states.get(resourceId);\n if (!state || state.status !== 'ready' || !state.trackIndex) {\n return null;\n }\n\n const { samples } = state.trackIndex;\n // console.log('>>>>>>>>>>>>>> resolveWindow samples length', samples[0], state);\n if (!samples.length) {\n return null;\n }\n\n const startSampleIndex = this.findStartSampleIndex(samples, startUs);\n const endSampleIndex = this.findEndSampleIndex(samples, endUs, startSampleIndex);\n\n if (startSampleIndex < 0 || endSampleIndex < 0) {\n return null;\n }\n\n const startSample = samples[startSampleIndex];\n const endSample = samples[endSampleIndex];\n\n if (!startSample || !endSample) {\n return null;\n }\n\n const alignedToKeyframe = startSample.isKey;\n const byteStart = startSample.byteOffset;\n const byteEnd = endSample.byteOffset + endSample.byteSize - 1;\n\n if (Number.isNaN(byteStart) || Number.isNaN(byteEnd) || byteEnd < byteStart) {\n return null;\n }\n\n return {\n byteStart,\n byteEnd,\n alignedToKeyframe,\n };\n }\n\n getStatus(resourceId: string): ResolverState['status'] | undefined {\n return this.states.get(resourceId)?.status;\n }\n\n dispose(): void {\n this.states.clear();\n }\n\n private async buildIndex(resource: Resource): Promise<void> {\n if (!resource.uri) {\n throw new Error(`Resource ${resource.id} missing uri`);\n }\n\n const mp4boxFile = MP4Box.createFile();\n const buffers: ArrayBuffer[] = [];\n let totalFetched = 0;\n let readyInfo: any | undefined;\n let trackIndex: TrackIndex | undefined;\n\n const readyPromise = new Promise<void>((resolve, reject) => {\n mp4boxFile.onReady = (info: any) => {\n readyInfo = info;\n resolve();\n };\n\n mp4boxFile.onError = (error: any) => {\n reject(error instanceof Error ? error : new Error(String(error)));\n };\n });\n\n while (totalFetched < this.maxMoovBytes) {\n const chunkSize = Math.min(\n this.initialFetchBytes * Math.pow(2, buffers.length),\n this.maxMoovBytes - totalFetched\n );\n const rangeStart = totalFetched;\n const rangeEnd = totalFetched + chunkSize - 1;\n\n const response = await fetch(resource.uri, {\n headers: {\n Range: `bytes=${rangeStart}-${rangeEnd}`,\n },\n });\n\n if (!response.ok) {\n throw new Error(`Failed to fetch range ${rangeStart}-${rangeEnd}: HTTP ${response.status}`);\n }\n\n const buffer = await response.arrayBuffer();\n (buffer as ArrayBuffer & { fileStart?: number }).fileStart = rangeStart;\n totalFetched += buffer.byteLength;\n buffers.push(buffer);\n\n mp4boxFile.appendBuffer(buffer);\n\n try {\n await readyPromise;\n break;\n } catch (error) {\n if (totalFetched >= this.maxMoovBytes) {\n throw error;\n }\n }\n }\n\n if (readyInfo) {\n for (const track of readyInfo.tracks ?? []) {\n const extractionOptions: Record<string, unknown> = {\n rapAlignment: false,\n keepSamples: true,\n };\n\n const totalSamples = (track as any)?.samples?.length ?? (track as any)?.sample_count;\n if (typeof totalSamples === 'number' && Number.isFinite(totalSamples) && totalSamples > 0) {\n extractionOptions.nbSamples = totalSamples;\n }\n\n mp4boxFile.setExtractionOptions(track.id, null, extractionOptions);\n }\n\n mp4boxFile.start();\n mp4boxFile.flush();\n\n trackIndex = this.createTrackIndex(mp4boxFile, readyInfo);\n }\n\n if (!trackIndex) {\n throw new Error('Failed to build track index');\n }\n\n const state = this.states.get(resource.id!);\n if (state) {\n state.status = 'ready';\n state.trackIndex = trackIndex;\n }\n }\n\n private createTrackIndex(mp4boxFile: MP4BoxFile, info: any): TrackIndex {\n const videoTrack = info.tracks?.find((track: any) => track.type === 'video');\n if (!videoTrack) {\n throw new Error('No video track found');\n }\n\n const timescale = videoTrack.timescale || 90000;\n const trackId = videoTrack.id;\n let samples = mp4boxFile.getTrackSamples?.(trackId) ?? [];\n\n if (\n (!samples || samples.length === 0) &&\n typeof (mp4boxFile as any).getTrackById === 'function'\n ) {\n const fullTrack = (mp4boxFile as any).getTrackById(trackId);\n if (fullTrack?.samples?.length) {\n samples = fullTrack.samples;\n }\n }\n\n // console.log('>>>>>>>>>>>>>> createTrackIndex samples length', samples[0]);\n\n const indexedSamples: TrackSample[] = (samples ?? []).map((sample: any, index: number) => {\n const sampleByteOffset = this.resolveSampleByteOffset(mp4boxFile, trackId, sample, index);\n const timeUs = Math.round((sample.cts * 1_000_000) / timescale);\n return {\n timeUs,\n byteOffset: sampleByteOffset,\n byteSize: sample.size,\n isKey: Boolean(sample.is_sync),\n };\n });\n\n return {\n trackId,\n timescale,\n samples: indexedSamples,\n };\n }\n\n private findStartSampleIndex(samples: TrackSample[], targetUs: number): number {\n if (!samples.length) {\n return 0;\n }\n\n let index = this.binarySearch(samples, targetUs, (sample, time) => sample.timeUs - time);\n if (index < 0) {\n index = ~index;\n if (index >= samples.length) {\n index = samples.length - 1;\n }\n }\n\n while (index > 0) {\n const current = samples[index];\n if (!current || current.isKey) {\n break;\n }\n index -= 1;\n }\n\n return index;\n }\n\n private findEndSampleIndex(samples: TrackSample[], targetUs: number, startIndex: number): number {\n if (!samples.length) {\n return 0;\n }\n\n let index = Math.min(Math.max(startIndex, 0), samples.length - 1);\n while (index + 1 < samples.length) {\n const nextSample = samples[index + 1];\n if (!nextSample || nextSample.timeUs > targetUs) {\n break;\n }\n index += 1;\n }\n\n return index;\n }\n\n private binarySearch(\n samples: TrackSample[],\n targetUs: number,\n compare: (sample: TrackSample, targetUs: number) => number\n ): number {\n let low = 0;\n let high = samples.length - 1;\n\n while (low <= high) {\n const mid = Math.floor((low + high) / 2);\n const sample = samples[mid];\n if (!sample) {\n break;\n }\n const cmp = compare(sample, targetUs);\n\n if (cmp === 0) {\n return mid;\n }\n if (cmp < 0) {\n low = mid + 1;\n } else {\n high = mid - 1;\n }\n }\n\n return ~low;\n }\n\n private resolveSampleByteOffset(\n mp4boxFile: MP4BoxFile,\n trackId: number,\n sample: any,\n sampleIndex: number\n ): number {\n if (typeof sample.position === 'number' && Number.isFinite(sample.position)) {\n return sample.position;\n }\n\n const trak = (mp4boxFile as any).getTrackById?.(trackId);\n if (!trak) {\n return NaN;\n }\n\n const chunkRefs = trak?.samples as any[] | undefined;\n const chunkIndex = sample.chunk_index ?? sample.chunk_index_in_trak ?? sample.chunkIndex;\n const chunkOffset =\n typeof chunkIndex === 'number' ? trak?.stco?.chunk_offsets?.[chunkIndex] : undefined;\n\n if (typeof chunkOffset === 'number' && Number.isFinite(chunkOffset)) {\n const offsetInChunk = typeof sample.offset === 'number' ? sample.offset : 0;\n return chunkOffset + offsetInChunk;\n }\n\n if (Array.isArray(chunkRefs) && chunkIndex >= 0 && chunkIndex < chunkRefs.length) {\n const chunk = chunkRefs[chunkIndex];\n if (chunk && typeof chunk.offset === 'number') {\n return chunk.offset;\n }\n }\n\n if (sample.fileStart && typeof sample.fileStart === 'number') {\n return sample.fileStart;\n }\n\n const positions = (mp4boxFile as any).getTrackSamplePositions?.(trackId);\n if (Array.isArray(positions) && sampleIndex < positions.length) {\n const pos = positions[sampleIndex];\n if (typeof pos === 'number') {\n return pos;\n }\n }\n\n return NaN;\n }\n}\n"],"names":["MP4Box.createFile"],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resource Loaders Module
|
|
3
|
+
* First stage in the processing pipeline
|
|
4
|
+
*/
|
|
5
|
+
export { ResourceLoader } from './ResourceLoader';
|
|
6
|
+
export { TaskManager } from './TaskManager';
|
|
7
|
+
export { StreamFactory } from './StreamFactory';
|
|
8
|
+
export { EventHandlers } from './EventHandlers';
|
|
9
|
+
export { WindowByteRangeResolver } from './WindowByteRangeResolver';
|
|
10
|
+
export * from './types';
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/stages/load/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACpE,cAAc,SAAS,CAAC"}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { Resource } from '../../model';
|
|
2
|
+
import { Clip } from '../../model/types';
|
|
3
|
+
import { EventPayloadMap } from '../../event/events';
|
|
4
|
+
import { EventBus } from '../../event/EventBus';
|
|
5
|
+
|
|
6
|
+
export interface Orchestrator {
|
|
7
|
+
on(event: string, handler: (data: any) => void): void;
|
|
8
|
+
off(event: string, handler: (data: any) => void): void;
|
|
9
|
+
emit(event: string, data: any): void;
|
|
10
|
+
workers: {
|
|
11
|
+
get(type: string, id?: string, options?: Record<string, any>): Promise<any>;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export interface LoaderConfig {
|
|
15
|
+
highWaterMark?: number;
|
|
16
|
+
maxConcurrent?: number;
|
|
17
|
+
chunkSize?: number;
|
|
18
|
+
retryCount?: number;
|
|
19
|
+
retryDelay?: number;
|
|
20
|
+
}
|
|
21
|
+
export interface ResourceLoadOptions {
|
|
22
|
+
signal?: AbortSignal;
|
|
23
|
+
priority?: 'high' | 'normal' | 'low';
|
|
24
|
+
resumable?: boolean;
|
|
25
|
+
range?: {
|
|
26
|
+
start: number;
|
|
27
|
+
end: number;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export interface ClipLoadOptions {
|
|
31
|
+
clipId: string;
|
|
32
|
+
resourceId: string;
|
|
33
|
+
trimStartUs?: number;
|
|
34
|
+
durationUs?: number;
|
|
35
|
+
priority?: 'high' | 'normal' | 'low';
|
|
36
|
+
}
|
|
37
|
+
export interface LoadProgress {
|
|
38
|
+
resourceId: string;
|
|
39
|
+
bytesLoaded: number;
|
|
40
|
+
totalBytes: number;
|
|
41
|
+
percentage: number;
|
|
42
|
+
speed: number;
|
|
43
|
+
estimatedTimeRemaining: number;
|
|
44
|
+
}
|
|
45
|
+
export interface StreamMetadata {
|
|
46
|
+
url: string;
|
|
47
|
+
contentLength: number;
|
|
48
|
+
acceptRanges: boolean;
|
|
49
|
+
contentType?: string;
|
|
50
|
+
lastModified?: string;
|
|
51
|
+
etag?: string;
|
|
52
|
+
}
|
|
53
|
+
export interface LoadTask {
|
|
54
|
+
resourceId: string;
|
|
55
|
+
resource: Resource;
|
|
56
|
+
stream?: ReadableStream<Uint8Array>;
|
|
57
|
+
controller?: AbortController;
|
|
58
|
+
metadata?: StreamMetadata;
|
|
59
|
+
bytesLoaded: number;
|
|
60
|
+
totalBytes: number;
|
|
61
|
+
startTime: number;
|
|
62
|
+
priority: 'high' | 'normal' | 'low';
|
|
63
|
+
pausedAt?: number;
|
|
64
|
+
error?: Error;
|
|
65
|
+
range?: {
|
|
66
|
+
start: number;
|
|
67
|
+
end: number;
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
export interface ResourceLoaderOptions {
|
|
71
|
+
orchestrator?: Orchestrator;
|
|
72
|
+
eventBus?: EventBus<EventPayloadMap>;
|
|
73
|
+
config?: LoaderConfig;
|
|
74
|
+
onProgress?: (progress: LoadProgress) => void;
|
|
75
|
+
onStateChange?: (resourceId: string, state: Resource['state']) => void;
|
|
76
|
+
}
|
|
77
|
+
export interface LoaderWorkerMessage {
|
|
78
|
+
type: 'load' | 'pause' | 'resume' | 'cancel' | 'getStatus';
|
|
79
|
+
resourceId: string;
|
|
80
|
+
resource?: Resource;
|
|
81
|
+
options?: ResourceLoadOptions;
|
|
82
|
+
}
|
|
83
|
+
export interface LoaderWorkerResponse {
|
|
84
|
+
type: 'stream' | 'progress' | 'complete' | 'error' | 'state';
|
|
85
|
+
resourceId: string;
|
|
86
|
+
stream?: ReadableStream<Uint8Array>;
|
|
87
|
+
progress?: LoadProgress;
|
|
88
|
+
error?: Error;
|
|
89
|
+
state?: Resource['state'];
|
|
90
|
+
}
|
|
91
|
+
export type LoaderWindowPriority = 'seek' | 'playback' | 'prerender' | 'background';
|
|
92
|
+
export type LoaderWindowSource = 'playback' | 'seek' | 'prerender' | 'background';
|
|
93
|
+
export interface LoaderWindowRequest {
|
|
94
|
+
clipId: string;
|
|
95
|
+
resourceId: string;
|
|
96
|
+
source: LoaderWindowSource;
|
|
97
|
+
targetTimeUs: number;
|
|
98
|
+
windowStartUs: number;
|
|
99
|
+
windowEndUs: number;
|
|
100
|
+
byteStart?: number;
|
|
101
|
+
byteEnd?: number;
|
|
102
|
+
priority: LoaderWindowPriority;
|
|
103
|
+
dedupeKey: string;
|
|
104
|
+
alignedToKeyframe?: boolean;
|
|
105
|
+
}
|
|
106
|
+
export interface LoaderWindowTask {
|
|
107
|
+
clip: Clip;
|
|
108
|
+
resource: Resource;
|
|
109
|
+
request: LoaderWindowRequest;
|
|
110
|
+
attempts: number;
|
|
111
|
+
state: LoaderWindowState;
|
|
112
|
+
bytesFetched: number;
|
|
113
|
+
enqueuedAt: number;
|
|
114
|
+
startedAt?: number;
|
|
115
|
+
}
|
|
116
|
+
export interface LoaderWindowQueueEntry {
|
|
117
|
+
task: LoaderWindowTask;
|
|
118
|
+
enqueuedAt: number;
|
|
119
|
+
}
|
|
120
|
+
export interface LoaderWindowQueueSnapshot {
|
|
121
|
+
clipId: string;
|
|
122
|
+
priority: LoaderWindowPriority;
|
|
123
|
+
state: LoaderWindowState;
|
|
124
|
+
attempts: number;
|
|
125
|
+
enqueuedAt: number;
|
|
126
|
+
windowStartUs: number;
|
|
127
|
+
windowEndUs: number;
|
|
128
|
+
}
|
|
129
|
+
export interface WindowTaskContext {
|
|
130
|
+
task: LoaderWindowTask;
|
|
131
|
+
abortController: AbortController;
|
|
132
|
+
fetchPromise: Promise<void>;
|
|
133
|
+
abortReason?: 'cancelled' | 'stall' | 'dispose' | 'error';
|
|
134
|
+
}
|
|
135
|
+
export type LoaderWindowState = 'pending' | 'fetching' | 'streaming' | 'completed' | 'failed';
|
|
136
|
+
export interface LoaderWindowConfig {
|
|
137
|
+
maxInflightPerClip: number;
|
|
138
|
+
maxInflight: number;
|
|
139
|
+
chunkSize: number;
|
|
140
|
+
}
|
|
141
|
+
export interface LoaderWindowRuntimeConfig {
|
|
142
|
+
maxInflightPerClip: number;
|
|
143
|
+
maxInflight: number;
|
|
144
|
+
chunkSize: number;
|
|
145
|
+
stallTimeoutMs: number;
|
|
146
|
+
retry: {
|
|
147
|
+
maxAttempts: number;
|
|
148
|
+
baseDelayMs: number;
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
export interface LoaderWindowMetrics {
|
|
152
|
+
dispatched: number;
|
|
153
|
+
completed: number;
|
|
154
|
+
failed: number;
|
|
155
|
+
retries: number;
|
|
156
|
+
stall: number;
|
|
157
|
+
rangeResolved: number;
|
|
158
|
+
rangeUnavailable: number;
|
|
159
|
+
}
|
|
160
|
+
export interface LoaderWindowMetricsSnapshot extends LoaderWindowMetrics {
|
|
161
|
+
inflight: number;
|
|
162
|
+
queued: number;
|
|
163
|
+
}
|
|
164
|
+
export interface LoaderWindowEventPayload {
|
|
165
|
+
clipId: string;
|
|
166
|
+
windowStartUs: number;
|
|
167
|
+
windowEndUs: number;
|
|
168
|
+
priority: LoaderWindowPriority;
|
|
169
|
+
requestId: string;
|
|
170
|
+
metrics: LoaderWindowMetricsSnapshot;
|
|
171
|
+
bytesFetched?: number;
|
|
172
|
+
bytesWritten?: number;
|
|
173
|
+
durationMs?: number;
|
|
174
|
+
reason?: string;
|
|
175
|
+
retryCount?: number;
|
|
176
|
+
}
|
|
177
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/stages/load/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { MuxConfig, MuxTrack } from './types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* MP4 Muxer - Multiplex encoded chunks into MP4 container
|
|
5
|
+
* Terminal stage that consumes encoded chunks and produces MP4 file
|
|
6
|
+
*/
|
|
7
|
+
export declare class MP4Muxer {
|
|
8
|
+
private mp4boxFile;
|
|
9
|
+
tracks: Map<number, MuxTrack>;
|
|
10
|
+
private mp4Tracks;
|
|
11
|
+
outputChunks: Uint8Array[];
|
|
12
|
+
get totalBytesWritten(): number;
|
|
13
|
+
isFinalized: boolean;
|
|
14
|
+
private config;
|
|
15
|
+
constructor(config?: MuxConfig);
|
|
16
|
+
private setupHandlers;
|
|
17
|
+
private initializeTracks;
|
|
18
|
+
private addTrack;
|
|
19
|
+
private configureFragmentedTrack;
|
|
20
|
+
private createVideoTrackOptions;
|
|
21
|
+
private createAudioTrackOptions;
|
|
22
|
+
/**
|
|
23
|
+
* Write video chunk to muxer
|
|
24
|
+
*/
|
|
25
|
+
writeVideoChunk(chunk: EncodedVideoChunk, trackId?: number): void;
|
|
26
|
+
/**
|
|
27
|
+
* Write audio chunk to muxer
|
|
28
|
+
*/
|
|
29
|
+
writeAudioChunk(chunk: EncodedAudioChunk, trackId?: number): void;
|
|
30
|
+
/**
|
|
31
|
+
* Flush pending samples
|
|
32
|
+
*/
|
|
33
|
+
flush(): void;
|
|
34
|
+
/**
|
|
35
|
+
* Finalize and get the output
|
|
36
|
+
*/
|
|
37
|
+
finalize(): Blob;
|
|
38
|
+
/**
|
|
39
|
+
* Clear output chunks (after they've been consumed)
|
|
40
|
+
*/
|
|
41
|
+
clearOutputChunks(): void;
|
|
42
|
+
destroy(): void;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=MP4Muxer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MP4Muxer.d.ts","sourceRoot":"","sources":["../../../src/stages/mux/MP4Muxer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAqBnD;;;GAGG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,UAAU,CAAM;IACxB,MAAM,wBAA+B;IACrC,OAAO,CAAC,SAAS,CAA6B;IAG9C,YAAY,EAAE,UAAU,EAAE,CAAM;IAGhC,IAAI,iBAAiB,IAAI,MAAM,CAE9B;IAGD,WAAW,UAAS;IAEpB,OAAO,CAAC,MAAM,CAAY;gBAEd,MAAM,GAAE,SAAgC;IAOpD,OAAO,CAAC,aAAa;IA6BrB,OAAO,CAAC,gBAAgB;IA+BxB,OAAO,CAAC,QAAQ;IA0BhB,OAAO,CAAC,wBAAwB;IAsChC,OAAO,CAAC,uBAAuB;IAqC/B,OAAO,CAAC,uBAAuB;IAuC/B;;OAEG;IACH,eAAe,CAAC,KAAK,EAAE,iBAAiB,EAAE,OAAO,GAAE,MAAU,GAAG,IAAI;IAkCpE;;OAEG;IACH,eAAe,CAAC,KAAK,EAAE,iBAAiB,EAAE,OAAO,GAAE,MAAU,GAAG,IAAI;IAgCpE;;OAEG;IACH,KAAK,IAAI,IAAI;IAMb;;OAEG;IACH,QAAQ,IAAI,IAAI;IAuBhB;;OAEG;IACH,iBAAiB,IAAI,IAAI;IAIzB,OAAO,IAAI,IAAI;CAOhB"}
|