@meframe/core 0.0.3 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Meframe.d.ts +16 -7
- package/dist/Meframe.d.ts.map +1 -1
- package/dist/Meframe.js +75 -90
- package/dist/Meframe.js.map +1 -1
- package/dist/cache/CacheManager.d.ts +28 -11
- package/dist/cache/CacheManager.d.ts.map +1 -1
- package/dist/cache/CacheManager.js +93 -30
- package/dist/cache/CacheManager.js.map +1 -1
- package/dist/cache/L2Cache.d.ts +31 -2
- package/dist/cache/L2Cache.d.ts.map +1 -1
- package/dist/cache/L2Cache.js +245 -44
- package/dist/cache/L2Cache.js.map +1 -1
- package/dist/cache/l1/VideoL1Cache.d.ts +3 -3
- package/dist/cache/l1/VideoL1Cache.d.ts.map +1 -1
- package/dist/cache/l1/VideoL1Cache.js +13 -8
- package/dist/cache/l1/VideoL1Cache.js.map +1 -1
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +2 -1
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/types.d.ts +3 -0
- package/dist/config/types.d.ts.map +1 -1
- package/dist/controllers/PlaybackController.d.ts +7 -8
- package/dist/controllers/PlaybackController.d.ts.map +1 -1
- package/dist/controllers/PlaybackController.js +56 -76
- package/dist/controllers/PlaybackController.js.map +1 -1
- package/dist/controllers/PreRenderService.d.ts +21 -4
- package/dist/controllers/PreRenderService.d.ts.map +1 -1
- package/dist/controllers/PreRenderService.js +67 -5
- package/dist/controllers/PreRenderService.js.map +1 -1
- package/dist/controllers/types.d.ts +2 -3
- package/dist/controllers/types.d.ts.map +1 -1
- package/dist/event/events.d.ts +1 -4
- package/dist/event/events.d.ts.map +1 -1
- package/dist/event/events.js.map +1 -1
- package/dist/model/CompositionModel.d.ts +2 -1
- package/dist/model/CompositionModel.d.ts.map +1 -1
- package/dist/model/CompositionModel.js +3 -1
- package/dist/model/CompositionModel.js.map +1 -1
- package/dist/model/patch.d.ts +6 -2
- package/dist/model/patch.d.ts.map +1 -1
- package/dist/model/patch.js +76 -2
- package/dist/model/patch.js.map +1 -1
- package/dist/model/types.d.ts +1 -0
- package/dist/model/types.d.ts.map +1 -1
- package/dist/node_modules/.pnpm/mp4-muxer@5.2.2/node_modules/mp4-muxer/build/mp4-muxer.js +1858 -0
- package/dist/node_modules/.pnpm/mp4-muxer@5.2.2/node_modules/mp4-muxer/build/mp4-muxer.js.map +1 -0
- package/dist/orchestrator/ClipSessionManager.d.ts +1 -2
- package/dist/orchestrator/ClipSessionManager.d.ts.map +1 -1
- package/dist/orchestrator/ClipSessionManager.js +1 -0
- package/dist/orchestrator/ClipSessionManager.js.map +1 -1
- package/dist/orchestrator/CompositionPlanner.d.ts +8 -7
- package/dist/orchestrator/CompositionPlanner.d.ts.map +1 -1
- package/dist/orchestrator/CompositionPlanner.js +33 -56
- package/dist/orchestrator/CompositionPlanner.js.map +1 -1
- package/dist/orchestrator/Orchestrator.d.ts +9 -2
- package/dist/orchestrator/Orchestrator.d.ts.map +1 -1
- package/dist/orchestrator/Orchestrator.js +100 -50
- package/dist/orchestrator/Orchestrator.js.map +1 -1
- package/dist/orchestrator/VideoClipSession.d.ts +14 -9
- package/dist/orchestrator/VideoClipSession.d.ts.map +1 -1
- package/dist/orchestrator/VideoClipSession.js +108 -85
- package/dist/orchestrator/VideoClipSession.js.map +1 -1
- package/dist/orchestrator/types.d.ts +1 -0
- package/dist/orchestrator/types.d.ts.map +1 -1
- package/dist/stages/compose/GlobalAudioSession.d.ts +34 -1
- package/dist/stages/compose/GlobalAudioSession.d.ts.map +1 -1
- package/dist/stages/compose/GlobalAudioSession.js +149 -5
- package/dist/stages/compose/GlobalAudioSession.js.map +1 -1
- package/dist/stages/compose/VideoComposer.d.ts +1 -0
- package/dist/stages/compose/VideoComposer.d.ts.map +1 -1
- package/dist/stages/demux/MP4Demuxer.d.ts.map +1 -1
- package/dist/stages/encode/AudioChunkEncoder.d.ts +2 -1
- package/dist/stages/encode/AudioChunkEncoder.d.ts.map +1 -1
- package/dist/stages/encode/AudioChunkEncoder.js +41 -0
- package/dist/stages/encode/AudioChunkEncoder.js.map +1 -0
- package/dist/stages/encode/BaseEncoder.d.ts +7 -3
- package/dist/stages/encode/BaseEncoder.d.ts.map +1 -1
- package/dist/stages/encode/BaseEncoder.js +173 -0
- package/dist/stages/encode/BaseEncoder.js.map +1 -0
- package/dist/stages/encode/ClipEncoderManager.d.ts +64 -0
- package/dist/stages/encode/ClipEncoderManager.d.ts.map +1 -0
- package/dist/stages/encode/index.d.ts +1 -1
- package/dist/stages/encode/index.d.ts.map +1 -1
- package/dist/stages/load/ResourceLoader.d.ts +22 -1
- package/dist/stages/load/ResourceLoader.d.ts.map +1 -1
- package/dist/stages/load/ResourceLoader.js +80 -29
- package/dist/stages/load/ResourceLoader.js.map +1 -1
- package/dist/stages/load/TaskManager.d.ts +1 -1
- package/dist/stages/load/TaskManager.d.ts.map +1 -1
- package/dist/stages/load/TaskManager.js +3 -2
- package/dist/stages/load/TaskManager.js.map +1 -1
- package/dist/stages/load/types.d.ts +4 -2
- package/dist/stages/load/types.d.ts.map +1 -1
- package/dist/stages/mux/MP4Muxer.d.ts +19 -38
- package/dist/stages/mux/MP4Muxer.d.ts.map +1 -1
- package/dist/stages/mux/MP4Muxer.js +60 -0
- package/dist/stages/mux/MP4Muxer.js.map +1 -0
- package/dist/stages/mux/MuxManager.d.ts +27 -0
- package/dist/stages/mux/MuxManager.d.ts.map +1 -0
- package/dist/stages/mux/MuxManager.js +148 -0
- package/dist/stages/mux/MuxManager.js.map +1 -0
- package/dist/stages/mux/index.d.ts +1 -0
- package/dist/stages/mux/index.d.ts.map +1 -1
- package/dist/stages/mux/types.d.ts +1 -0
- package/dist/stages/mux/types.d.ts.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/worker/WorkerPool.d.ts +2 -0
- package/dist/worker/WorkerPool.d.ts.map +1 -1
- package/dist/worker/WorkerPool.js +6 -5
- package/dist/worker/WorkerPool.js.map +1 -1
- package/dist/worker/types.d.ts +1 -4
- package/dist/worker/types.d.ts.map +1 -1
- package/dist/worker/types.js +0 -3
- package/dist/worker/types.js.map +1 -1
- package/dist/worker/worker-event-whitelist.d.ts.map +1 -1
- package/dist/workers/MP4Demuxer.js +7049 -6
- package/dist/workers/MP4Demuxer.js.map +1 -1
- package/dist/workers/WorkerChannel.js +0 -3
- package/dist/workers/WorkerChannel.js.map +1 -1
- package/dist/workers/stages/compose/video-compose.worker.js +126 -83
- package/dist/workers/stages/compose/video-compose.worker.js.map +1 -1
- package/dist/workers/stages/decode/decode.worker.js +25 -16
- package/dist/workers/stages/decode/decode.worker.js.map +1 -1
- package/dist/workers/stages/demux/audio-demux.worker.js +4 -4
- package/dist/workers/stages/demux/audio-demux.worker.js.map +1 -1
- package/dist/workers/stages/demux/video-demux.worker.js +9 -7
- package/dist/workers/stages/demux/video-demux.worker.js.map +1 -1
- package/dist/workers/stages/encode/encode.worker.js +191 -195
- package/dist/workers/stages/encode/encode.worker.js.map +1 -1
- package/package.json +2 -1
- package/dist/controllers/PreviewHandle.d.ts +0 -25
- package/dist/controllers/PreviewHandle.d.ts.map +0 -1
- package/dist/controllers/PreviewHandle.js +0 -45
- package/dist/controllers/PreviewHandle.js.map +0 -1
- package/dist/model/dirty-range.js +0 -220
- package/dist/model/dirty-range.js.map +0 -1
- package/dist/stages/encode/EncoderPool.d.ts +0 -28
- package/dist/stages/encode/EncoderPool.d.ts.map +0 -1
- package/dist/workers/mp4box.all.js +0 -7049
- package/dist/workers/mp4box.all.js.map +0 -1
- package/dist/workers/stages/mux/mux.worker.js +0 -501
- package/dist/workers/stages/mux/mux.worker.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClipEncoderManager.d.ts","sourceRoot":"","sources":["../../../src/stages/encode/ClipEncoderManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAEtE;;;;;;;;;;;GAWG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,aAAa,CAAwC;IAC7D,OAAO,CAAC,aAAa,CAAwC;IAC7D,OAAO,CAAC,kBAAkB,CAAgB;IAC1C,OAAO,CAAC,kBAAkB,CAAgB;IAC1C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;gBAEzB,WAAW,SAAI;IAI3B;;;OAGG;IACG,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAyB7F;;OAEG;IACG,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAwB7F;;OAEG;IACG,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAcpD;;OAEG;IACG,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAcpD;;OAEG;IACG,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAInD;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAc/B;;OAEG;IACH,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAI/B;;OAEG;IACH,QAAQ;;;;;;;CAST"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { VideoChunkEncoder } from './VideoChunkEncoder';
|
|
2
2
|
export { AudioChunkEncoder } from './AudioChunkEncoder';
|
|
3
3
|
export { BaseEncoder } from './BaseEncoder';
|
|
4
|
-
export {
|
|
4
|
+
export { ClipEncoderManager } from './ClipEncoderManager';
|
|
5
5
|
export * from './types';
|
|
6
6
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/stages/encode/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/stages/encode/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,cAAc,SAAS,CAAC"}
|
|
@@ -21,8 +21,29 @@ export declare class ResourceLoader {
|
|
|
21
21
|
private handleModelSet;
|
|
22
22
|
private enqueueLoad;
|
|
23
23
|
private processQueue;
|
|
24
|
+
/**
|
|
25
|
+
* Start loading a resource
|
|
26
|
+
* Handles state management (loading → ready/error) for all resource types
|
|
27
|
+
*/
|
|
24
28
|
private startLoad;
|
|
25
|
-
|
|
29
|
+
/**
|
|
30
|
+
* Load text-based resources (json, text)
|
|
31
|
+
* Just download the content - state management is handled by startLoad()
|
|
32
|
+
*/
|
|
33
|
+
private loadTextResource;
|
|
34
|
+
/**
|
|
35
|
+
* Load image resource: fetch blob → create ImageBitmap → transfer to worker
|
|
36
|
+
* Note: Images don't need streaming (typically < 5MB)
|
|
37
|
+
*/
|
|
38
|
+
private loadImageBitmap;
|
|
39
|
+
/**
|
|
40
|
+
* Fetch resource as blob (for images, json, etc.)
|
|
41
|
+
*/
|
|
42
|
+
private fetchBlob;
|
|
43
|
+
/**
|
|
44
|
+
* Transfer ImageBitmap to VideoComposeWorker
|
|
45
|
+
*/
|
|
46
|
+
private transferImageToWorker;
|
|
26
47
|
private transferToDemuxWorker;
|
|
27
48
|
private updateResourceState;
|
|
28
49
|
fetch(resourceId?: string, options?: ResourceLoadOptions): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ResourceLoader.d.ts","sourceRoot":"","sources":["../../../src/stages/load/ResourceLoader.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,mBAAmB,EAAE,QAAQ,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAQlG,qBAAa,cAAc;IACzB,OAAO,CAAC,YAAY,CAAC,CAAe;IACpC,OAAO,CAAC,KAAK,CAAC,CAAmB;IACjC,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,aAAa,CAAC,CAAgB;IACtC,OAAO,CAAC,QAAQ,CAAC,CAA4B;IAC7C,OAAO,CAAC,aAAa,CAAC,CAAyD;IAC/E,OAAO,CAAC,iBAAiB,CAA0B;gBAEvC,OAAO,CAAC,EAAE,qBAAqB;IAa3C;;OAEG;IACH,IAAI,CAAC,YAAY,EAAE,YAAY,GAAG,IAAI;IAWtC;;OAEG;IACH,MAAM,IAAI,IAAI;IAMd,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,WAAW;
|
|
1
|
+
{"version":3,"file":"ResourceLoader.d.ts","sourceRoot":"","sources":["../../../src/stages/load/ResourceLoader.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,mBAAmB,EAAE,QAAQ,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAQlG,qBAAa,cAAc;IACzB,OAAO,CAAC,YAAY,CAAC,CAAe;IACpC,OAAO,CAAC,KAAK,CAAC,CAAmB;IACjC,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,aAAa,CAAC,CAAgB;IACtC,OAAO,CAAC,QAAQ,CAAC,CAA4B;IAC7C,OAAO,CAAC,aAAa,CAAC,CAAyD;IAC/E,OAAO,CAAC,iBAAiB,CAA0B;gBAEvC,OAAO,CAAC,EAAE,qBAAqB;IAa3C;;OAEG;IACH,IAAI,CAAC,YAAY,EAAE,YAAY,GAAG,IAAI;IAWtC;;OAEG;IACH,MAAM,IAAI,IAAI;IAMd,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,WAAW;IAcnB,OAAO,CAAC,YAAY;IAQpB;;;OAGG;YACW,SAAS;IAiCvB;;;OAGG;YACW,gBAAgB;IAM9B;;;OAGG;YACW,eAAe;IAc7B;;OAEG;YACW,SAAS;IAUvB;;OAEG;YACW,qBAAqB;YAyBrB,qBAAqB;IAuBnC,OAAO,CAAC,mBAAmB;IAkBrB,KAAK,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAc9E,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAKhC,KAAK,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAOzB,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAoB9E,IAAI,WAAW,IAAI,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAEvC;IAED,IAAI,SAAS,IAAI,QAAQ,EAAE,CAE1B;IAED,OAAO,IAAI,IAAI;CAKhB"}
|
|
@@ -46,15 +46,11 @@ class ResourceLoader {
|
|
|
46
46
|
handleModelSet(model) {
|
|
47
47
|
this.model = model;
|
|
48
48
|
}
|
|
49
|
-
enqueueLoad(resource, priority = "normal",
|
|
49
|
+
enqueueLoad(resource, priority = "normal", sessionId, trackId) {
|
|
50
50
|
if (this.taskManager.hasActiveTask(resource.id)) {
|
|
51
51
|
return;
|
|
52
52
|
}
|
|
53
|
-
|
|
54
|
-
this.loadNonStreamingResource(resource);
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
this.taskManager.enqueue(resource, priority, clipId);
|
|
53
|
+
this.taskManager.enqueue(resource, priority, sessionId, trackId);
|
|
58
54
|
this.processQueue();
|
|
59
55
|
}
|
|
60
56
|
processQueue() {
|
|
@@ -64,18 +60,26 @@ class ResourceLoader {
|
|
|
64
60
|
this.startLoad(task);
|
|
65
61
|
}
|
|
66
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* Start loading a resource
|
|
65
|
+
* Handles state management (loading → ready/error) for all resource types
|
|
66
|
+
*/
|
|
67
67
|
async startLoad(task) {
|
|
68
68
|
this.taskManager.activateTask(task);
|
|
69
69
|
try {
|
|
70
70
|
this.updateResourceState(task.resourceId, "loading");
|
|
71
71
|
task.controller = new AbortController();
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
72
|
+
if (task.resource.type === "image") {
|
|
73
|
+
await this.loadImageBitmap(task);
|
|
74
|
+
} else if (task.resource.type === "video" || task.resource.type === "audio") {
|
|
75
|
+
const stream = await this.streamFactory.createRegularStream(task);
|
|
76
|
+
if (!stream) {
|
|
77
|
+
throw new Error(`Failed to create stream for ${task.resourceId}`);
|
|
78
|
+
}
|
|
79
|
+
task.stream = stream;
|
|
78
80
|
await this.transferToDemuxWorker(task);
|
|
81
|
+
} else if (task.resource.type === "json" || task.resource.type === "text") {
|
|
82
|
+
await this.loadTextResource(task);
|
|
79
83
|
}
|
|
80
84
|
this.updateResourceState(task.resourceId, "ready");
|
|
81
85
|
} catch (error) {
|
|
@@ -86,33 +90,75 @@ class ResourceLoader {
|
|
|
86
90
|
this.processQueue();
|
|
87
91
|
}
|
|
88
92
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
93
|
+
/**
|
|
94
|
+
* Load text-based resources (json, text)
|
|
95
|
+
* Just download the content - state management is handled by startLoad()
|
|
96
|
+
*/
|
|
97
|
+
async loadTextResource(task) {
|
|
98
|
+
await this.fetchBlob(task.resource.uri, task.controller.signal);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Load image resource: fetch blob → create ImageBitmap → transfer to worker
|
|
102
|
+
* Note: Images don't need streaming (typically < 5MB)
|
|
103
|
+
*/
|
|
104
|
+
async loadImageBitmap(task) {
|
|
105
|
+
const blob = await this.fetchBlob(task.resource.uri, task.controller.signal);
|
|
106
|
+
const imageBitmap = await createImageBitmap(blob, {
|
|
107
|
+
premultiplyAlpha: "premultiply",
|
|
108
|
+
colorSpaceConversion: "default",
|
|
109
|
+
imageOrientation: "from-image"
|
|
110
|
+
});
|
|
111
|
+
await this.transferImageToWorker(task, imageBitmap);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Fetch resource as blob (for images, json, etc.)
|
|
115
|
+
*/
|
|
116
|
+
async fetchBlob(uri, signal) {
|
|
117
|
+
const response = await fetch(uri, { signal });
|
|
118
|
+
if (!response.ok) {
|
|
119
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
99
120
|
}
|
|
121
|
+
return response.blob();
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Transfer ImageBitmap to VideoComposeWorker
|
|
125
|
+
*/
|
|
126
|
+
async transferImageToWorker(task, imageBitmap) {
|
|
127
|
+
if (!this.orchestrator) return;
|
|
128
|
+
if (!task.sessionId) {
|
|
129
|
+
throw new Error(
|
|
130
|
+
`[ResourceLoader] sessionId required for resource ${task.resourceId}. In Clip-based architecture, use fetch(resourceId, { sessionId })`
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
const composeWorker = await this.orchestrator.workers.get("videoCompose", task.sessionId, {
|
|
134
|
+
lazy: true
|
|
135
|
+
});
|
|
136
|
+
await composeWorker.send(
|
|
137
|
+
"receive_image",
|
|
138
|
+
{
|
|
139
|
+
resourceId: task.resourceId,
|
|
140
|
+
sessionId: task.sessionId,
|
|
141
|
+
imageBitmap
|
|
142
|
+
},
|
|
143
|
+
{ transfer: [imageBitmap] }
|
|
144
|
+
);
|
|
100
145
|
}
|
|
101
146
|
async transferToDemuxWorker(task) {
|
|
102
147
|
if (!task.stream || !this.orchestrator) return;
|
|
103
|
-
if (!task.
|
|
148
|
+
if (!task.sessionId) {
|
|
104
149
|
throw new Error(
|
|
105
|
-
`[ResourceLoader]
|
|
150
|
+
`[ResourceLoader] sessionId required for resource ${task.resourceId}. In Clip-based architecture, use fetch(resourceId, { sessionId })`
|
|
106
151
|
);
|
|
107
152
|
}
|
|
108
153
|
const workerType = task.resource.type === "video" ? "videoDemux" : "audioDemux";
|
|
109
|
-
const demuxWorker = await this.orchestrator.workers.get(workerType, task.
|
|
154
|
+
const demuxWorker = await this.orchestrator.workers.get(workerType, task.sessionId, {
|
|
110
155
|
lazy: true
|
|
111
156
|
});
|
|
112
157
|
await demuxWorker.sendStream(task.stream, {
|
|
113
|
-
|
|
158
|
+
sessionId: task.sessionId,
|
|
114
159
|
...task.metadata,
|
|
115
|
-
...task.range && { range: task.range }
|
|
160
|
+
...task.range && { range: task.range },
|
|
161
|
+
...task.trackId && { trackId: task.trackId }
|
|
116
162
|
});
|
|
117
163
|
}
|
|
118
164
|
updateResourceState(resourceId, state) {
|
|
@@ -140,7 +186,7 @@ class ResourceLoader {
|
|
|
140
186
|
console.warn(`Resource ${resourceId} not found in model`);
|
|
141
187
|
return;
|
|
142
188
|
}
|
|
143
|
-
this.enqueueLoad(resource, options?.priority || "normal", options?.
|
|
189
|
+
this.enqueueLoad(resource, options?.priority || "normal", options?.sessionId, options?.trackId);
|
|
144
190
|
}
|
|
145
191
|
cancel(resourceId) {
|
|
146
192
|
this.taskManager.cancelTask(resourceId);
|
|
@@ -159,7 +205,12 @@ class ResourceLoader {
|
|
|
159
205
|
}
|
|
160
206
|
const pausedTask = this.taskManager.getActiveTask(resourceId);
|
|
161
207
|
if (pausedTask?.pausedAt !== void 0) {
|
|
162
|
-
this.enqueueLoad(
|
|
208
|
+
this.enqueueLoad(
|
|
209
|
+
resource,
|
|
210
|
+
options?.priority || "normal",
|
|
211
|
+
options?.sessionId,
|
|
212
|
+
options?.trackId
|
|
213
|
+
);
|
|
163
214
|
} else {
|
|
164
215
|
await this.fetch(resourceId, options);
|
|
165
216
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ResourceLoader.js","sources":["../../../src/stages/load/ResourceLoader.ts"],"sourcesContent":["import type { Resource, CompositionModel } from '../../model';\nimport type { Orchestrator, ResourceLoadOptions, LoadTask, ResourceLoaderOptions } from './types';\nimport { TaskManager } from './TaskManager';\nimport { StreamFactory } from './StreamFactory';\nimport { EventHandlers } from './EventHandlers';\nimport { EventPayloadMap, MeframeEvent } from '../../event/events';\nimport { EventBus } from '../../event/EventBus';\nimport { WindowByteRangeResolver } from './WindowByteRangeResolver';\n\nexport class ResourceLoader {\n private orchestrator?: Orchestrator;\n private model?: CompositionModel;\n private taskManager: TaskManager;\n private streamFactory: StreamFactory;\n private eventHandlers?: EventHandlers;\n private eventBus?: EventBus<EventPayloadMap>;\n private onStateChange?: (resourceId: string, state: Resource['state']) => void;\n private byteRangeResolver: WindowByteRangeResolver;\n\n constructor(options?: ResourceLoaderOptions) {\n const maxConcurrent = options?.config?.maxConcurrent ?? 4;\n this.taskManager = new TaskManager(maxConcurrent);\n this.streamFactory = new StreamFactory(options?.onProgress, options?.config);\n this.eventBus = options?.eventBus;\n this.onStateChange = options?.onStateChange;\n this.byteRangeResolver = new WindowByteRangeResolver();\n\n if (options?.orchestrator) {\n this.bind(options.orchestrator);\n }\n }\n\n /**\n * Bind to Orchestrator event system\n */\n bind(orchestrator: Orchestrator): void {\n this.unbind();\n this.orchestrator = orchestrator;\n\n this.eventHandlers = new EventHandlers(\n orchestrator,\n (resourceId) => this.cancel(resourceId),\n (model) => this.handleModelSet(model)\n );\n }\n\n /**\n * Unbind from Orchestrator\n */\n unbind(): void {\n this.eventHandlers?.dispose();\n this.eventHandlers = undefined;\n this.orchestrator = undefined;\n }\n\n private handleModelSet(model: CompositionModel): void {\n this.model = model;\n }\n\n private enqueueLoad(\n resource: Resource,\n priority: 'high' | 'normal' | 'low' = 'normal',\n clipId?: string\n ): void {\n if (this.taskManager.hasActiveTask(resource.id)) {\n return;\n }\n\n if (resource.type === 'json' || resource.type === 'text') {\n this.loadNonStreamingResource(resource);\n return;\n }\n\n this.taskManager.enqueue(resource, priority, clipId);\n this.processQueue();\n }\n\n private processQueue(): void {\n while (this.taskManager.canProcess) {\n const task = this.taskManager.getNextTask();\n if (!task) break;\n this.startLoad(task);\n }\n }\n\n private async startLoad(task: LoadTask): Promise<void> {\n this.taskManager.activateTask(task);\n\n try {\n this.updateResourceState(task.resourceId, 'loading');\n task.controller = new AbortController();\n\n // const metadata = await this.streamFactory.fetchMetadata(\n // task.resource.uri,\n // task.controller.signal\n // );\n\n // if (metadata) {\n // task.metadata = metadata;\n // task.totalBytes = metadata.contentLength;\n // }\n\n // let stream =\n // metadata?.acceptRanges && task.pausedAt !== undefined\n // ? this.streamFactory.createResumableStream(task)\n // : await this.streamFactory.createRegularStream(task);\n\n const stream = await this.streamFactory.createRegularStream(task);\n\n if (!stream) {\n throw new Error(`Failed to create stream for ${task.resourceId}`);\n }\n\n task.stream = stream;\n\n if (task.resource.type === 'video' || task.resource.type === 'audio') {\n await this.transferToDemuxWorker(task);\n }\n this.updateResourceState(task.resourceId, 'ready');\n } catch (error) {\n task.error = error as Error;\n this.updateResourceState(task.resourceId, 'error');\n } finally {\n this.taskManager.completeTask(task.resourceId);\n this.processQueue();\n }\n }\n\n private async loadNonStreamingResource(resource: Resource): Promise<void> {\n try {\n this.updateResourceState(resource.id, 'loading');\n const response = await fetch(resource.uri);\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n this.updateResourceState(resource.id, 'ready');\n } catch {\n this.updateResourceState(resource.id, 'error');\n }\n }\n\n private async transferToDemuxWorker(task: LoadTask): Promise<void> {\n if (!task.stream || !this.orchestrator) return;\n\n if (!task.clipId) {\n throw new Error(\n `[ResourceLoader] clipId required for resource ${task.resourceId}. ` +\n `In Clip-based architecture, use fetch(resourceId, { clipId })`\n );\n }\n\n const workerType = task.resource.type === 'video' ? 'videoDemux' : 'audioDemux';\n const demuxWorker = await this.orchestrator.workers.get(workerType, task.clipId, {\n lazy: true,\n });\n\n await demuxWorker.sendStream(task.stream, {\n clipId: task.clipId,\n ...task.metadata,\n ...(task.range && { range: task.range }),\n });\n }\n\n private updateResourceState(resourceId: string, state: Resource['state']): void {\n const resource = this.model?.resources.get(resourceId);\n if (resource) {\n const oldState = resource.state;\n resource.state = state;\n if (this.orchestrator) {\n this.eventBus?.emit(MeframeEvent.ResourceStageChange, {\n type: MeframeEvent.ResourceStageChange,\n resourceId,\n oldState,\n newState: state,\n });\n }\n }\n\n this.onStateChange?.(resourceId, state);\n }\n\n async fetch(resourceId?: string, options?: ResourceLoadOptions): Promise<void> {\n if (!resourceId) {\n return;\n }\n\n const resource = this.model?.resources.get(resourceId);\n if (!resource) {\n console.warn(`Resource ${resourceId} not found in model`);\n return;\n }\n\n this.enqueueLoad(resource, options?.priority || 'normal', options?.clipId);\n }\n\n cancel(resourceId: string): void {\n this.taskManager.cancelTask(resourceId);\n this.processQueue();\n }\n\n pause(resourceId: string): void {\n const task = this.taskManager.getActiveTask(resourceId);\n if (task) {\n task.controller?.abort();\n }\n }\n\n async resume(resourceId: string, options?: ResourceLoadOptions): Promise<void> {\n const resource = this.model?.getResource(resourceId);\n if (!resource) {\n throw new Error(`Resource ${resourceId} not found`);\n }\n\n const pausedTask = this.taskManager.getActiveTask(resourceId);\n\n if (pausedTask?.pausedAt !== undefined) {\n this.enqueueLoad(resource, options?.priority || 'normal', options?.clipId);\n } else {\n await this.fetch(resourceId, options);\n }\n }\n\n get activeTasks(): Map<string, LoadTask> {\n return this.taskManager.activeTasks;\n }\n\n get taskQueue(): LoadTask[] {\n return this.taskManager.taskQueue;\n }\n\n dispose(): void {\n this.taskManager.clear();\n this.byteRangeResolver.dispose();\n this.unbind();\n }\n}\n"],"names":[],"mappings":";;;;;AASO,MAAM,eAAe;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAER,YAAY,SAAiC;AAC3C,UAAM,gBAAgB,SAAS,QAAQ,iBAAiB;AACxD,SAAK,cAAc,IAAI,YAAY,aAAa;AAChD,SAAK,gBAAgB,IAAI,cAAc,SAAS,YAAY,SAAS,MAAM;AAC3E,SAAK,WAAW,SAAS;AACzB,SAAK,gBAAgB,SAAS;AAC9B,SAAK,oBAAoB,IAAI,wBAAA;AAE7B,QAAI,SAAS,cAAc;AACzB,WAAK,KAAK,QAAQ,YAAY;AAAA,IAChC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,KAAK,cAAkC;AACrC,SAAK,OAAA;AACL,SAAK,eAAe;AAEpB,SAAK,gBAAgB,IAAI;AAAA,MACvB;AAAA,MACA,CAAC,eAAe,KAAK,OAAO,UAAU;AAAA,MACtC,CAAC,UAAU,KAAK,eAAe,KAAK;AAAA,IAAA;AAAA,EAExC;AAAA;AAAA;AAAA;AAAA,EAKA,SAAe;AACb,SAAK,eAAe,QAAA;AACpB,SAAK,gBAAgB;AACrB,SAAK,eAAe;AAAA,EACtB;AAAA,EAEQ,eAAe,OAA+B;AACpD,SAAK,QAAQ;AAAA,EACf;AAAA,EAEQ,YACN,UACA,WAAsC,UACtC,QACM;AACN,QAAI,KAAK,YAAY,cAAc,SAAS,EAAE,GAAG;AAC/C;AAAA,IACF;AAEA,QAAI,SAAS,SAAS,UAAU,SAAS,SAAS,QAAQ;AACxD,WAAK,yBAAyB,QAAQ;AACtC;AAAA,IACF;AAEA,SAAK,YAAY,QAAQ,UAAU,UAAU,MAAM;AACnD,SAAK,aAAA;AAAA,EACP;AAAA,EAEQ,eAAqB;AAC3B,WAAO,KAAK,YAAY,YAAY;AAClC,YAAM,OAAO,KAAK,YAAY,YAAA;AAC9B,UAAI,CAAC,KAAM;AACX,WAAK,UAAU,IAAI;AAAA,IACrB;AAAA,EACF;AAAA,EAEA,MAAc,UAAU,MAA+B;AACrD,SAAK,YAAY,aAAa,IAAI;AAElC,QAAI;AACF,WAAK,oBAAoB,KAAK,YAAY,SAAS;AACnD,WAAK,aAAa,IAAI,gBAAA;AAiBtB,YAAM,SAAS,MAAM,KAAK,cAAc,oBAAoB,IAAI;AAEhE,UAAI,CAAC,QAAQ;AACX,cAAM,IAAI,MAAM,+BAA+B,KAAK,UAAU,EAAE;AAAA,MAClE;AAEA,WAAK,SAAS;AAEd,UAAI,KAAK,SAAS,SAAS,WAAW,KAAK,SAAS,SAAS,SAAS;AACpE,cAAM,KAAK,sBAAsB,IAAI;AAAA,MACvC;AACA,WAAK,oBAAoB,KAAK,YAAY,OAAO;AAAA,IACnD,SAAS,OAAO;AACd,WAAK,QAAQ;AACb,WAAK,oBAAoB,KAAK,YAAY,OAAO;AAAA,IACnD,UAAA;AACE,WAAK,YAAY,aAAa,KAAK,UAAU;AAC7C,WAAK,aAAA;AAAA,IACP;AAAA,EACF;AAAA,EAEA,MAAc,yBAAyB,UAAmC;AACxE,QAAI;AACF,WAAK,oBAAoB,SAAS,IAAI,SAAS;AAC/C,YAAM,WAAW,MAAM,MAAM,SAAS,GAAG;AACzC,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,IAAI,MAAM,QAAQ,SAAS,MAAM,KAAK,SAAS,UAAU,EAAE;AAAA,MACnE;AACA,WAAK,oBAAoB,SAAS,IAAI,OAAO;AAAA,IAC/C,QAAQ;AACN,WAAK,oBAAoB,SAAS,IAAI,OAAO;AAAA,IAC/C;AAAA,EACF;AAAA,EAEA,MAAc,sBAAsB,MAA+B;AACjE,QAAI,CAAC,KAAK,UAAU,CAAC,KAAK,aAAc;AAExC,QAAI,CAAC,KAAK,QAAQ;AAChB,YAAM,IAAI;AAAA,QACR,iDAAiD,KAAK,UAAU;AAAA,MAAA;AAAA,IAGpE;AAEA,UAAM,aAAa,KAAK,SAAS,SAAS,UAAU,eAAe;AACnE,UAAM,cAAc,MAAM,KAAK,aAAa,QAAQ,IAAI,YAAY,KAAK,QAAQ;AAAA,MAC/E,MAAM;AAAA,IAAA,CACP;AAED,UAAM,YAAY,WAAW,KAAK,QAAQ;AAAA,MACxC,QAAQ,KAAK;AAAA,MACb,GAAG,KAAK;AAAA,MACR,GAAI,KAAK,SAAS,EAAE,OAAO,KAAK,MAAA;AAAA,IAAM,CACvC;AAAA,EACH;AAAA,EAEQ,oBAAoB,YAAoB,OAAgC;AAC9E,UAAM,WAAW,KAAK,OAAO,UAAU,IAAI,UAAU;AACrD,QAAI,UAAU;AACZ,YAAM,WAAW,SAAS;AAC1B,eAAS,QAAQ;AACjB,UAAI,KAAK,cAAc;AACrB,aAAK,UAAU,KAAK,aAAa,qBAAqB;AAAA,UACpD,MAAM,aAAa;AAAA,UACnB;AAAA,UACA;AAAA,UACA,UAAU;AAAA,QAAA,CACX;AAAA,MACH;AAAA,IACF;AAEA,SAAK,gBAAgB,YAAY,KAAK;AAAA,EACxC;AAAA,EAEA,MAAM,MAAM,YAAqB,SAA8C;AAC7E,QAAI,CAAC,YAAY;AACf;AAAA,IACF;AAEA,UAAM,WAAW,KAAK,OAAO,UAAU,IAAI,UAAU;AACrD,QAAI,CAAC,UAAU;AACb,cAAQ,KAAK,YAAY,UAAU,qBAAqB;AACxD;AAAA,IACF;AAEA,SAAK,YAAY,UAAU,SAAS,YAAY,UAAU,SAAS,MAAM;AAAA,EAC3E;AAAA,EAEA,OAAO,YAA0B;AAC/B,SAAK,YAAY,WAAW,UAAU;AACtC,SAAK,aAAA;AAAA,EACP;AAAA,EAEA,MAAM,YAA0B;AAC9B,UAAM,OAAO,KAAK,YAAY,cAAc,UAAU;AACtD,QAAI,MAAM;AACR,WAAK,YAAY,MAAA;AAAA,IACnB;AAAA,EACF;AAAA,EAEA,MAAM,OAAO,YAAoB,SAA8C;AAC7E,UAAM,WAAW,KAAK,OAAO,YAAY,UAAU;AACnD,QAAI,CAAC,UAAU;AACb,YAAM,IAAI,MAAM,YAAY,UAAU,YAAY;AAAA,IACpD;AAEA,UAAM,aAAa,KAAK,YAAY,cAAc,UAAU;AAE5D,QAAI,YAAY,aAAa,QAAW;AACtC,WAAK,YAAY,UAAU,SAAS,YAAY,UAAU,SAAS,MAAM;AAAA,IAC3E,OAAO;AACL,YAAM,KAAK,MAAM,YAAY,OAAO;AAAA,IACtC;AAAA,EACF;AAAA,EAEA,IAAI,cAAqC;AACvC,WAAO,KAAK,YAAY;AAAA,EAC1B;AAAA,EAEA,IAAI,YAAwB;AAC1B,WAAO,KAAK,YAAY;AAAA,EAC1B;AAAA,EAEA,UAAgB;AACd,SAAK,YAAY,MAAA;AACjB,SAAK,kBAAkB,QAAA;AACvB,SAAK,OAAA;AAAA,EACP;AACF;"}
|
|
1
|
+
{"version":3,"file":"ResourceLoader.js","sources":["../../../src/stages/load/ResourceLoader.ts"],"sourcesContent":["import type { Resource, CompositionModel } from '../../model';\nimport type { Orchestrator, ResourceLoadOptions, LoadTask, ResourceLoaderOptions } from './types';\nimport { TaskManager } from './TaskManager';\nimport { StreamFactory } from './StreamFactory';\nimport { EventHandlers } from './EventHandlers';\nimport { EventPayloadMap, MeframeEvent } from '../../event/events';\nimport { EventBus } from '../../event/EventBus';\nimport { WindowByteRangeResolver } from './WindowByteRangeResolver';\n\nexport class ResourceLoader {\n private orchestrator?: Orchestrator;\n private model?: CompositionModel;\n private taskManager: TaskManager;\n private streamFactory: StreamFactory;\n private eventHandlers?: EventHandlers;\n private eventBus?: EventBus<EventPayloadMap>;\n private onStateChange?: (resourceId: string, state: Resource['state']) => void;\n private byteRangeResolver: WindowByteRangeResolver;\n\n constructor(options?: ResourceLoaderOptions) {\n const maxConcurrent = options?.config?.maxConcurrent ?? 4;\n this.taskManager = new TaskManager(maxConcurrent);\n this.streamFactory = new StreamFactory(options?.onProgress, options?.config);\n this.eventBus = options?.eventBus;\n this.onStateChange = options?.onStateChange;\n this.byteRangeResolver = new WindowByteRangeResolver();\n\n if (options?.orchestrator) {\n this.bind(options.orchestrator);\n }\n }\n\n /**\n * Bind to Orchestrator event system\n */\n bind(orchestrator: Orchestrator): void {\n this.unbind();\n this.orchestrator = orchestrator;\n\n this.eventHandlers = new EventHandlers(\n orchestrator,\n (resourceId) => this.cancel(resourceId),\n (model) => this.handleModelSet(model)\n );\n }\n\n /**\n * Unbind from Orchestrator\n */\n unbind(): void {\n this.eventHandlers?.dispose();\n this.eventHandlers = undefined;\n this.orchestrator = undefined;\n }\n\n private handleModelSet(model: CompositionModel): void {\n this.model = model;\n }\n\n private enqueueLoad(\n resource: Resource,\n priority: 'high' | 'normal' | 'low' = 'normal',\n sessionId?: string,\n trackId?: string\n ): void {\n if (this.taskManager.hasActiveTask(resource.id)) {\n return;\n }\n\n this.taskManager.enqueue(resource, priority, sessionId, trackId);\n this.processQueue();\n }\n\n private processQueue(): void {\n while (this.taskManager.canProcess) {\n const task = this.taskManager.getNextTask();\n if (!task) break;\n this.startLoad(task);\n }\n }\n\n /**\n * Start loading a resource\n * Handles state management (loading → ready/error) for all resource types\n */\n private async startLoad(task: LoadTask): Promise<void> {\n this.taskManager.activateTask(task);\n\n try {\n this.updateResourceState(task.resourceId, 'loading');\n task.controller = new AbortController();\n\n // Route to different handlers based on resource type\n // Note: Each handler only deals with data, state is managed here\n if (task.resource.type === 'image') {\n await this.loadImageBitmap(task);\n } else if (task.resource.type === 'video' || task.resource.type === 'audio') {\n const stream = await this.streamFactory.createRegularStream(task);\n if (!stream) {\n throw new Error(`Failed to create stream for ${task.resourceId}`);\n }\n task.stream = stream;\n await this.transferToDemuxWorker(task);\n } else if (task.resource.type === 'json' || task.resource.type === 'text') {\n await this.loadTextResource(task);\n }\n\n // Unified state update for all resource types\n this.updateResourceState(task.resourceId, 'ready');\n } catch (error) {\n task.error = error as Error;\n this.updateResourceState(task.resourceId, 'error');\n } finally {\n this.taskManager.completeTask(task.resourceId);\n this.processQueue();\n }\n }\n\n /**\n * Load text-based resources (json, text)\n * Just download the content - state management is handled by startLoad()\n */\n private async loadTextResource(task: LoadTask): Promise<void> {\n await this.fetchBlob(task.resource.uri, task.controller!.signal);\n // For json/text, just verify we can download it\n // Future: could parse and validate json here if needed\n }\n\n /**\n * Load image resource: fetch blob → create ImageBitmap → transfer to worker\n * Note: Images don't need streaming (typically < 5MB)\n */\n private async loadImageBitmap(task: LoadTask): Promise<void> {\n const blob = await this.fetchBlob(task.resource.uri, task.controller!.signal);\n\n // Create ImageBitmap in main thread, then transfer to worker\n // Note: In Worker context, ImageBitmap is the only way to create VideoFrame from image data\n const imageBitmap = await createImageBitmap(blob, {\n premultiplyAlpha: 'premultiply',\n colorSpaceConversion: 'default',\n imageOrientation: 'from-image',\n });\n\n await this.transferImageToWorker(task, imageBitmap);\n }\n\n /**\n * Fetch resource as blob (for images, json, etc.)\n */\n private async fetchBlob(uri: string, signal: AbortSignal): Promise<Blob> {\n const response = await fetch(uri, { signal });\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n return response.blob();\n }\n\n /**\n * Transfer ImageBitmap to VideoComposeWorker\n */\n private async transferImageToWorker(task: LoadTask, imageBitmap: ImageBitmap): Promise<void> {\n if (!this.orchestrator) return;\n\n if (!task.sessionId) {\n throw new Error(\n `[ResourceLoader] sessionId required for resource ${task.resourceId}. ` +\n `In Clip-based architecture, use fetch(resourceId, { sessionId })`\n );\n }\n\n const composeWorker = await this.orchestrator.workers.get('videoCompose', task.sessionId, {\n lazy: true,\n });\n\n await composeWorker.send(\n 'receive_image',\n {\n resourceId: task.resourceId,\n sessionId: task.sessionId,\n imageBitmap,\n },\n { transfer: [imageBitmap] }\n );\n }\n\n private async transferToDemuxWorker(task: LoadTask): Promise<void> {\n if (!task.stream || !this.orchestrator) return;\n\n if (!task.sessionId) {\n throw new Error(\n `[ResourceLoader] sessionId required for resource ${task.resourceId}. ` +\n `In Clip-based architecture, use fetch(resourceId, { sessionId })`\n );\n }\n\n const workerType = task.resource.type === 'video' ? 'videoDemux' : 'audioDemux';\n const demuxWorker = await this.orchestrator.workers.get(workerType, task.sessionId, {\n lazy: true,\n });\n\n await demuxWorker.sendStream(task.stream, {\n sessionId: task.sessionId,\n ...task.metadata,\n ...(task.range && { range: task.range }),\n ...(task.trackId && { trackId: task.trackId }),\n });\n }\n\n private updateResourceState(resourceId: string, state: Resource['state']): void {\n const resource = this.model?.resources.get(resourceId);\n if (resource) {\n const oldState = resource.state;\n resource.state = state;\n if (this.orchestrator) {\n this.eventBus?.emit(MeframeEvent.ResourceStageChange, {\n type: MeframeEvent.ResourceStageChange,\n resourceId,\n oldState,\n newState: state,\n });\n }\n }\n\n this.onStateChange?.(resourceId, state);\n }\n\n async fetch(resourceId?: string, options?: ResourceLoadOptions): Promise<void> {\n if (!resourceId) {\n return;\n }\n\n const resource = this.model?.resources.get(resourceId);\n if (!resource) {\n console.warn(`Resource ${resourceId} not found in model`);\n return;\n }\n\n this.enqueueLoad(resource, options?.priority || 'normal', options?.sessionId, options?.trackId);\n }\n\n cancel(resourceId: string): void {\n this.taskManager.cancelTask(resourceId);\n this.processQueue();\n }\n\n pause(resourceId: string): void {\n const task = this.taskManager.getActiveTask(resourceId);\n if (task) {\n task.controller?.abort();\n }\n }\n\n async resume(resourceId: string, options?: ResourceLoadOptions): Promise<void> {\n const resource = this.model?.getResource(resourceId);\n if (!resource) {\n throw new Error(`Resource ${resourceId} not found`);\n }\n\n const pausedTask = this.taskManager.getActiveTask(resourceId);\n\n if (pausedTask?.pausedAt !== undefined) {\n this.enqueueLoad(\n resource,\n options?.priority || 'normal',\n options?.sessionId,\n options?.trackId\n );\n } else {\n await this.fetch(resourceId, options);\n }\n }\n\n get activeTasks(): Map<string, LoadTask> {\n return this.taskManager.activeTasks;\n }\n\n get taskQueue(): LoadTask[] {\n return this.taskManager.taskQueue;\n }\n\n dispose(): void {\n this.taskManager.clear();\n this.byteRangeResolver.dispose();\n this.unbind();\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -17,7 +17,7 @@ export declare class TaskManager {
|
|
|
17
17
|
/**
|
|
18
18
|
* Create and enqueue a new task
|
|
19
19
|
*/
|
|
20
|
-
enqueue(resource: Resource, priority?: 'high' | 'normal' | 'low',
|
|
20
|
+
enqueue(resource: Resource, priority?: 'high' | 'normal' | 'low', sessionId?: string, trackId?: string): LoadTask;
|
|
21
21
|
/**
|
|
22
22
|
* Get next task from queue if under concurrent limit
|
|
23
23
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TaskManager.d.ts","sourceRoot":"","sources":["../../../src/stages/load/TaskManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C;;GAEG;AACH,qBAAa,WAAW;IACtB,WAAW,wBAA+B;IAC1C,SAAS,EAAE,QAAQ,EAAE,CAAM;IAC3B,OAAO,CAAC,eAAe,CAAK;IAC5B,OAAO,CAAC,aAAa,CAAS;gBAElB,aAAa,GAAE,MAAU;IAIrC;;OAEG;IACH,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO;IAI1C;;OAEG;IACH,OAAO,CACL,QAAQ,EAAE,QAAQ,EAClB,QAAQ,GAAE,MAAM,GAAG,QAAQ,GAAG,KAAgB,EAC9C,MAAM,CAAC,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"TaskManager.d.ts","sourceRoot":"","sources":["../../../src/stages/load/TaskManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C;;GAEG;AACH,qBAAa,WAAW;IACtB,WAAW,wBAA+B;IAC1C,SAAS,EAAE,QAAQ,EAAE,CAAM;IAC3B,OAAO,CAAC,eAAe,CAAK;IAC5B,OAAO,CAAC,aAAa,CAAS;gBAElB,aAAa,GAAE,MAAU;IAIrC;;OAEG;IACH,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO;IAI1C;;OAEG;IACH,OAAO,CACL,QAAQ,EAAE,QAAQ,EAClB,QAAQ,GAAE,MAAM,GAAG,QAAQ,GAAG,KAAgB,EAC9C,SAAS,CAAC,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,MAAM,GACf,QAAQ;IAsBX;;OAEG;IACH,WAAW,IAAI,QAAQ,GAAG,IAAI;IAQ9B;;OAEG;IACH,YAAY,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI;IAKlC;;OAEG;IACH,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAOtC;;OAEG;IACH,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO;IAkBvC;;OAEG;IACH,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS;IAIvD;;OAEG;IACH,IAAI,UAAU,IAAI,OAAO,CAExB;IAED;;OAEG;IACH,KAAK,IAAI,IAAI;CAUd"}
|
|
@@ -15,7 +15,7 @@ class TaskManager {
|
|
|
15
15
|
/**
|
|
16
16
|
* Create and enqueue a new task
|
|
17
17
|
*/
|
|
18
|
-
enqueue(resource, priority = "normal",
|
|
18
|
+
enqueue(resource, priority = "normal", sessionId, trackId) {
|
|
19
19
|
const task = {
|
|
20
20
|
resourceId: resource.id,
|
|
21
21
|
resource,
|
|
@@ -23,7 +23,8 @@ class TaskManager {
|
|
|
23
23
|
totalBytes: 0,
|
|
24
24
|
startTime: Date.now(),
|
|
25
25
|
priority,
|
|
26
|
-
|
|
26
|
+
sessionId,
|
|
27
|
+
trackId
|
|
27
28
|
};
|
|
28
29
|
if (priority === "high") {
|
|
29
30
|
this.taskQueue.unshift(task);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TaskManager.js","sources":["../../../src/stages/load/TaskManager.ts"],"sourcesContent":["import type { LoadTask } from './types';\nimport type { Resource } from '../../model';\n\n/**\n * Manages resource loading tasks and queue\n */\nexport class TaskManager {\n activeTasks = new Map<string, LoadTask>();\n taskQueue: LoadTask[] = [];\n private concurrentCount = 0;\n private maxConcurrent: number;\n\n constructor(maxConcurrent: number = 4) {\n this.maxConcurrent = maxConcurrent;\n }\n\n /**\n * Check if a resource is already being loaded\n */\n hasActiveTask(resourceId: string): boolean {\n return this.activeTasks.has(resourceId);\n }\n\n /**\n * Create and enqueue a new task\n */\n enqueue(\n resource: Resource,\n priority: 'high' | 'normal' | 'low' = 'normal',\n
|
|
1
|
+
{"version":3,"file":"TaskManager.js","sources":["../../../src/stages/load/TaskManager.ts"],"sourcesContent":["import type { LoadTask } from './types';\nimport type { Resource } from '../../model';\n\n/**\n * Manages resource loading tasks and queue\n */\nexport class TaskManager {\n activeTasks = new Map<string, LoadTask>();\n taskQueue: LoadTask[] = [];\n private concurrentCount = 0;\n private maxConcurrent: number;\n\n constructor(maxConcurrent: number = 4) {\n this.maxConcurrent = maxConcurrent;\n }\n\n /**\n * Check if a resource is already being loaded\n */\n hasActiveTask(resourceId: string): boolean {\n return this.activeTasks.has(resourceId);\n }\n\n /**\n * Create and enqueue a new task\n */\n enqueue(\n resource: Resource,\n priority: 'high' | 'normal' | 'low' = 'normal',\n sessionId?: string,\n trackId?: string\n ): LoadTask {\n const task: LoadTask = {\n resourceId: resource.id,\n resource,\n bytesLoaded: 0,\n totalBytes: 0,\n startTime: Date.now(),\n priority,\n sessionId,\n trackId,\n };\n\n // Add to queue based on priority\n if (priority === 'high') {\n this.taskQueue.unshift(task);\n } else {\n this.taskQueue.push(task);\n }\n\n return task;\n }\n\n /**\n * Get next task from queue if under concurrent limit\n */\n getNextTask(): LoadTask | null {\n if (this.taskQueue.length === 0 || this.concurrentCount >= this.maxConcurrent) {\n return null;\n }\n\n return this.taskQueue.shift() || null;\n }\n\n /**\n * Mark task as active\n */\n activateTask(task: LoadTask): void {\n this.activeTasks.set(task.resourceId, task);\n this.concurrentCount++;\n }\n\n /**\n * Mark task as completed\n */\n completeTask(resourceId: string): void {\n if (this.activeTasks.has(resourceId)) {\n this.activeTasks.delete(resourceId);\n this.concurrentCount--;\n }\n }\n\n /**\n * Cancel a task\n */\n cancelTask(resourceId: string): boolean {\n const task = this.activeTasks.get(resourceId);\n if (task) {\n task.controller?.abort();\n this.completeTask(resourceId);\n return true;\n }\n\n // Also remove from queue\n const index = this.taskQueue.findIndex((t) => t.resourceId === resourceId);\n if (index >= 0) {\n this.taskQueue.splice(index, 1);\n return true;\n }\n\n return false;\n }\n\n /**\n * Find an active task\n */\n getActiveTask(resourceId: string): LoadTask | undefined {\n return this.activeTasks.get(resourceId);\n }\n\n /**\n * Check if can process more tasks\n */\n get canProcess(): boolean {\n return this.concurrentCount < this.maxConcurrent;\n }\n\n /**\n * Clear all tasks\n */\n clear(): void {\n // Cancel all active tasks\n for (const task of this.activeTasks.values()) {\n task.controller?.abort();\n }\n\n this.activeTasks.clear();\n this.taskQueue = [];\n this.concurrentCount = 0;\n }\n}\n"],"names":[],"mappings":"AAMO,MAAM,YAAY;AAAA,EACvB,kCAAkB,IAAA;AAAA,EAClB,YAAwB,CAAA;AAAA,EAChB,kBAAkB;AAAA,EAClB;AAAA,EAER,YAAY,gBAAwB,GAAG;AACrC,SAAK,gBAAgB;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc,YAA6B;AACzC,WAAO,KAAK,YAAY,IAAI,UAAU;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA,EAKA,QACE,UACA,WAAsC,UACtC,WACA,SACU;AACV,UAAM,OAAiB;AAAA,MACrB,YAAY,SAAS;AAAA,MACrB;AAAA,MACA,aAAa;AAAA,MACb,YAAY;AAAA,MACZ,WAAW,KAAK,IAAA;AAAA,MAChB;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAIF,QAAI,aAAa,QAAQ;AACvB,WAAK,UAAU,QAAQ,IAAI;AAAA,IAC7B,OAAO;AACL,WAAK,UAAU,KAAK,IAAI;AAAA,IAC1B;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,cAA+B;AAC7B,QAAI,KAAK,UAAU,WAAW,KAAK,KAAK,mBAAmB,KAAK,eAAe;AAC7E,aAAO;AAAA,IACT;AAEA,WAAO,KAAK,UAAU,MAAA,KAAW;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,MAAsB;AACjC,SAAK,YAAY,IAAI,KAAK,YAAY,IAAI;AAC1C,SAAK;AAAA,EACP;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,YAA0B;AACrC,QAAI,KAAK,YAAY,IAAI,UAAU,GAAG;AACpC,WAAK,YAAY,OAAO,UAAU;AAClC,WAAK;AAAA,IACP;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW,YAA6B;AACtC,UAAM,OAAO,KAAK,YAAY,IAAI,UAAU;AAC5C,QAAI,MAAM;AACR,WAAK,YAAY,MAAA;AACjB,WAAK,aAAa,UAAU;AAC5B,aAAO;AAAA,IACT;AAGA,UAAM,QAAQ,KAAK,UAAU,UAAU,CAAC,MAAM,EAAE,eAAe,UAAU;AACzE,QAAI,SAAS,GAAG;AACd,WAAK,UAAU,OAAO,OAAO,CAAC;AAC9B,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc,YAA0C;AACtD,WAAO,KAAK,YAAY,IAAI,UAAU;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,aAAsB;AACxB,WAAO,KAAK,kBAAkB,KAAK;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA,EAKA,QAAc;AAEZ,eAAW,QAAQ,KAAK,YAAY,OAAA,GAAU;AAC5C,WAAK,YAAY,MAAA;AAAA,IACnB;AAEA,SAAK,YAAY,MAAA;AACjB,SAAK,YAAY,CAAA;AACjB,SAAK,kBAAkB;AAAA,EACzB;AACF;"}
|
|
@@ -26,7 +26,8 @@ export interface ResourceLoadOptions {
|
|
|
26
26
|
start: number;
|
|
27
27
|
end: number;
|
|
28
28
|
};
|
|
29
|
-
|
|
29
|
+
sessionId?: string;
|
|
30
|
+
trackId?: string;
|
|
30
31
|
}
|
|
31
32
|
export interface ClipLoadOptions {
|
|
32
33
|
clipId: string;
|
|
@@ -67,7 +68,8 @@ export interface LoadTask {
|
|
|
67
68
|
start: number;
|
|
68
69
|
end: number;
|
|
69
70
|
};
|
|
70
|
-
|
|
71
|
+
sessionId?: string;
|
|
72
|
+
trackId?: string;
|
|
71
73
|
}
|
|
72
74
|
export interface ResourceLoaderOptions {
|
|
73
75
|
orchestrator?: Orchestrator;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/stages/load/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAGrD,MAAM,WAAW,YAAY;IAC3B,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,GAAG,IAAI,CAAC;IACtD,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,GAAG,IAAI,CAAC;IACvD,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,IAAI,CAAC;IACrC,OAAO,EAAE;QACP,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;KAC7E,CAAC;CACH;AAGD,MAAM,WAAW,YAAY;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAGD,MAAM,WAAW,mBAAmB;IAClC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACrC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/stages/load/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,44 +1,25 @@
|
|
|
1
|
-
import { MuxConfig, MuxTrack } from './types';
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
2
|
+
* MP4Muxer - MP4 container multiplexer using mp4-muxer library
|
|
3
|
+
* Supports video and audio track export
|
|
6
4
|
*/
|
|
7
5
|
export declare class MP4Muxer {
|
|
8
|
-
private
|
|
9
|
-
|
|
10
|
-
private
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
private
|
|
22
|
-
|
|
23
|
-
|
|
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
|
-
*/
|
|
6
|
+
private muxer;
|
|
7
|
+
private firstVideoChunk;
|
|
8
|
+
private firstAudioChunk;
|
|
9
|
+
private videoChunkMeta;
|
|
10
|
+
private audioChunkMeta;
|
|
11
|
+
constructor(config: {
|
|
12
|
+
width: number;
|
|
13
|
+
height: number;
|
|
14
|
+
fps: number;
|
|
15
|
+
fastStart?: false | 'in-memory' | 'fragmented';
|
|
16
|
+
videoChunkMeta?: any;
|
|
17
|
+
audioChunkMeta?: any;
|
|
18
|
+
});
|
|
19
|
+
private videoChunkCount;
|
|
20
|
+
writeVideoChunk(chunk: EncodedVideoChunk): void;
|
|
21
|
+
private audioChunkCount;
|
|
22
|
+
writeAudioChunk(chunk: EncodedAudioChunk): void;
|
|
37
23
|
finalize(): Blob;
|
|
38
|
-
/**
|
|
39
|
-
* Clear output chunks (after they've been consumed)
|
|
40
|
-
*/
|
|
41
|
-
clearOutputChunks(): void;
|
|
42
|
-
destroy(): void;
|
|
43
24
|
}
|
|
44
25
|
//# sourceMappingURL=MP4Muxer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MP4Muxer.d.ts","sourceRoot":"","sources":["../../../src/stages/mux/MP4Muxer.ts"],"names":[],"mappings":"AAEA
|
|
1
|
+
{"version":3,"file":"MP4Muxer.d.ts","sourceRoot":"","sources":["../../../src/stages/mux/MP4Muxer.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,KAAK,CAA2B;IACxC,OAAO,CAAC,eAAe,CAAQ;IAC/B,OAAO,CAAC,eAAe,CAAQ;IAC/B,OAAO,CAAC,cAAc,CAAa;IACnC,OAAO,CAAC,cAAc,CAAa;gBAEvB,MAAM,EAAE;QAClB,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,EAAE,MAAM,CAAC;QACZ,SAAS,CAAC,EAAE,KAAK,GAAG,WAAW,GAAG,YAAY,CAAC;QAC/C,cAAc,CAAC,EAAE,GAAG,CAAC;QACrB,cAAc,CAAC,EAAE,GAAG,CAAC;KACtB;IA4BD,OAAO,CAAC,eAAe,CAAK;IAE5B,eAAe,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI;IAW/C,OAAO,CAAC,eAAe,CAAK;IAE5B,eAAe,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI;IAW/C,QAAQ,IAAI,IAAI;CAKjB"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { ArrayBufferTarget, Muxer } from "../../node_modules/.pnpm/mp4-muxer@5.2.2/node_modules/mp4-muxer/build/mp4-muxer.js";
|
|
2
|
+
class MP4Muxer {
|
|
3
|
+
muxer;
|
|
4
|
+
firstVideoChunk = true;
|
|
5
|
+
firstAudioChunk = true;
|
|
6
|
+
videoChunkMeta = null;
|
|
7
|
+
audioChunkMeta = null;
|
|
8
|
+
constructor(config) {
|
|
9
|
+
this.videoChunkMeta = config.videoChunkMeta;
|
|
10
|
+
this.audioChunkMeta = config.audioChunkMeta;
|
|
11
|
+
const muxerConfig = {
|
|
12
|
+
target: new ArrayBufferTarget(),
|
|
13
|
+
video: {
|
|
14
|
+
codec: "avc",
|
|
15
|
+
width: config.width,
|
|
16
|
+
height: config.height,
|
|
17
|
+
frameRate: config.fps
|
|
18
|
+
},
|
|
19
|
+
fastStart: config.fastStart ?? "in-memory",
|
|
20
|
+
firstTimestampBehavior: "strict"
|
|
21
|
+
};
|
|
22
|
+
if (this.audioChunkMeta) {
|
|
23
|
+
muxerConfig.audio = {
|
|
24
|
+
codec: "aac",
|
|
25
|
+
sampleRate: this.audioChunkMeta.sampleRate || 48e3,
|
|
26
|
+
numberOfChannels: this.audioChunkMeta.numberOfChannels || 2
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
this.muxer = new Muxer(muxerConfig);
|
|
30
|
+
}
|
|
31
|
+
videoChunkCount = 0;
|
|
32
|
+
writeVideoChunk(chunk) {
|
|
33
|
+
let meta;
|
|
34
|
+
if (this.firstVideoChunk && chunk.type === "key" && this.videoChunkMeta) {
|
|
35
|
+
meta = { decoderConfig: this.videoChunkMeta };
|
|
36
|
+
this.firstVideoChunk = false;
|
|
37
|
+
}
|
|
38
|
+
this.videoChunkCount++;
|
|
39
|
+
this.muxer.addVideoChunk(chunk, meta);
|
|
40
|
+
}
|
|
41
|
+
audioChunkCount = 0;
|
|
42
|
+
writeAudioChunk(chunk) {
|
|
43
|
+
let meta;
|
|
44
|
+
if (this.firstAudioChunk && this.audioChunkMeta) {
|
|
45
|
+
meta = { decoderConfig: this.audioChunkMeta };
|
|
46
|
+
this.firstAudioChunk = false;
|
|
47
|
+
}
|
|
48
|
+
this.audioChunkCount++;
|
|
49
|
+
this.muxer.addAudioChunk(chunk, meta);
|
|
50
|
+
}
|
|
51
|
+
finalize() {
|
|
52
|
+
this.muxer.finalize();
|
|
53
|
+
const buffer = this.muxer.target.buffer;
|
|
54
|
+
return new Blob([buffer], { type: "video/mp4" });
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
export {
|
|
58
|
+
MP4Muxer
|
|
59
|
+
};
|
|
60
|
+
//# sourceMappingURL=MP4Muxer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MP4Muxer.js","sources":["../../../src/stages/mux/MP4Muxer.ts"],"sourcesContent":["import { Muxer, ArrayBufferTarget } from 'mp4-muxer';\n\n/**\n * MP4Muxer - MP4 container multiplexer using mp4-muxer library\n * Supports video and audio track export\n */\nexport class MP4Muxer {\n private muxer: Muxer<ArrayBufferTarget>;\n private firstVideoChunk = true;\n private firstAudioChunk = true;\n private videoChunkMeta: any = null;\n private audioChunkMeta: any = null;\n\n constructor(config: {\n width: number;\n height: number;\n fps: number;\n fastStart?: false | 'in-memory' | 'fragmented';\n videoChunkMeta?: any;\n audioChunkMeta?: any;\n }) {\n this.videoChunkMeta = config.videoChunkMeta;\n this.audioChunkMeta = config.audioChunkMeta;\n\n const muxerConfig: any = {\n target: new ArrayBufferTarget(),\n video: {\n codec: 'avc',\n width: config.width,\n height: config.height,\n frameRate: config.fps,\n },\n fastStart: config.fastStart ?? 'in-memory',\n firstTimestampBehavior: 'strict',\n };\n\n // Add audio configuration if provided\n if (this.audioChunkMeta) {\n muxerConfig.audio = {\n codec: 'aac',\n sampleRate: this.audioChunkMeta.sampleRate || 48000,\n numberOfChannels: this.audioChunkMeta.numberOfChannels || 2,\n };\n }\n\n this.muxer = new Muxer(muxerConfig);\n }\n\n private videoChunkCount = 0;\n\n writeVideoChunk(chunk: EncodedVideoChunk): void {\n let meta: EncodedVideoChunkMetadata | undefined;\n if (this.firstVideoChunk && chunk.type === 'key' && this.videoChunkMeta) {\n meta = { decoderConfig: this.videoChunkMeta };\n this.firstVideoChunk = false;\n }\n\n this.videoChunkCount++;\n this.muxer.addVideoChunk(chunk, meta);\n }\n\n private audioChunkCount = 0;\n\n writeAudioChunk(chunk: EncodedAudioChunk): void {\n let meta: EncodedAudioChunkMetadata | undefined;\n if (this.firstAudioChunk && this.audioChunkMeta) {\n meta = { decoderConfig: this.audioChunkMeta };\n this.firstAudioChunk = false;\n }\n\n this.audioChunkCount++;\n this.muxer.addAudioChunk(chunk, meta);\n }\n\n finalize(): Blob {\n this.muxer.finalize();\n const buffer = (this.muxer.target as ArrayBufferTarget).buffer;\n return new Blob([buffer], { type: 'video/mp4' });\n }\n}\n"],"names":[],"mappings":";AAMO,MAAM,SAAS;AAAA,EACZ;AAAA,EACA,kBAAkB;AAAA,EAClB,kBAAkB;AAAA,EAClB,iBAAsB;AAAA,EACtB,iBAAsB;AAAA,EAE9B,YAAY,QAOT;AACD,SAAK,iBAAiB,OAAO;AAC7B,SAAK,iBAAiB,OAAO;AAE7B,UAAM,cAAmB;AAAA,MACvB,QAAQ,IAAI,kBAAA;AAAA,MACZ,OAAO;AAAA,QACL,OAAO;AAAA,QACP,OAAO,OAAO;AAAA,QACd,QAAQ,OAAO;AAAA,QACf,WAAW,OAAO;AAAA,MAAA;AAAA,MAEpB,WAAW,OAAO,aAAa;AAAA,MAC/B,wBAAwB;AAAA,IAAA;AAI1B,QAAI,KAAK,gBAAgB;AACvB,kBAAY,QAAQ;AAAA,QAClB,OAAO;AAAA,QACP,YAAY,KAAK,eAAe,cAAc;AAAA,QAC9C,kBAAkB,KAAK,eAAe,oBAAoB;AAAA,MAAA;AAAA,IAE9D;AAEA,SAAK,QAAQ,IAAI,MAAM,WAAW;AAAA,EACpC;AAAA,EAEQ,kBAAkB;AAAA,EAE1B,gBAAgB,OAAgC;AAC9C,QAAI;AACJ,QAAI,KAAK,mBAAmB,MAAM,SAAS,SAAS,KAAK,gBAAgB;AACvE,aAAO,EAAE,eAAe,KAAK,eAAA;AAC7B,WAAK,kBAAkB;AAAA,IACzB;AAEA,SAAK;AACL,SAAK,MAAM,cAAc,OAAO,IAAI;AAAA,EACtC;AAAA,EAEQ,kBAAkB;AAAA,EAE1B,gBAAgB,OAAgC;AAC9C,QAAI;AACJ,QAAI,KAAK,mBAAmB,KAAK,gBAAgB;AAC/C,aAAO,EAAE,eAAe,KAAK,eAAA;AAC7B,WAAK,kBAAkB;AAAA,IACzB;AAEA,SAAK;AACL,SAAK,MAAM,cAAc,OAAO,IAAI;AAAA,EACtC;AAAA,EAEA,WAAiB;AACf,SAAK,MAAM,SAAA;AACX,UAAM,SAAU,KAAK,MAAM,OAA6B;AACxD,WAAO,IAAI,KAAK,CAAC,MAAM,GAAG,EAAE,MAAM,aAAa;AAAA,EACjD;AACF;"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { CompositionModel } from '../../model/CompositionModel';
|
|
2
|
+
import { ExportOptions } from '../../types';
|
|
3
|
+
import { GlobalAudioSession } from '../compose/GlobalAudioSession';
|
|
4
|
+
import { CacheManager } from '../../cache/CacheManager';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* MuxManager: Main thread muxing service
|
|
8
|
+
* Reads encoded chunks from L2 cache and muxes into final video file
|
|
9
|
+
*/
|
|
10
|
+
export declare class MuxManager {
|
|
11
|
+
private cacheManager;
|
|
12
|
+
private audioSession;
|
|
13
|
+
private audioEncoderConfig;
|
|
14
|
+
private audioEncodedStream;
|
|
15
|
+
private audioFirstChunk;
|
|
16
|
+
constructor(cacheManager: CacheManager, audioSession: GlobalAudioSession, audioEncoderConfig: AudioEncoderConfig);
|
|
17
|
+
export(model: CompositionModel, options: ExportOptions): Promise<Blob>;
|
|
18
|
+
/**
|
|
19
|
+
* Get audio chunk metadata by reading first chunk from encoder
|
|
20
|
+
* Caches the stream and first chunk for later use
|
|
21
|
+
*/
|
|
22
|
+
private getAudioChunkMeta;
|
|
23
|
+
private writeVideoChunks;
|
|
24
|
+
private writeAudioChunks;
|
|
25
|
+
private checkL2Coverage;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=MuxManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MuxManager.d.ts","sourceRoot":"","sources":["../../../src/stages/mux/MuxManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAEnE,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEpD;;;GAGG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,kBAAkB,CAAqB;IAC/C,OAAO,CAAC,kBAAkB,CAAkD;IAC5E,OAAO,CAAC,eAAe,CAAkC;gBAGvD,YAAY,EAAE,YAAY,EAC1B,YAAY,EAAE,kBAAkB,EAChC,kBAAkB,EAAE,kBAAkB;IAOlC,MAAM,CAAC,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IA+C5E;;;OAGG;YACW,iBAAiB;YAoCjB,gBAAgB;YAmChB,gBAAgB;YA6BhB,eAAe;CAkB9B"}
|