@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
|
@@ -1,18 +1,23 @@
|
|
|
1
1
|
import { WorkerPool } from '../worker/WorkerPool';
|
|
2
2
|
import { CacheManager } from '../cache/CacheManager';
|
|
3
3
|
import { CompositionModel } from '../model';
|
|
4
|
-
import { DirtyRange } from './types';
|
|
5
4
|
import { CompositionPlanner, ClipUpdateResult } from './CompositionPlanner';
|
|
6
5
|
import { BaseWorker } from '../worker/BaseWorker';
|
|
7
6
|
import { WorkerType } from '../worker/types';
|
|
8
7
|
|
|
9
8
|
interface VideoClipSessionCallbacks {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
onComposedStreamReady(stream: ReadableStream<VideoFrame>, fps: number): void;
|
|
10
|
+
onEncodedStreamReady(stream: ReadableStream<{
|
|
11
|
+
chunk: EncodedVideoChunk;
|
|
12
|
+
metadata: EncodedVideoChunkMetadata;
|
|
13
|
+
}>, track: 'video' | 'audio'): void;
|
|
14
|
+
onStreamDisposed?(): void;
|
|
15
|
+
onPipelineReady?(): Promise<void>;
|
|
13
16
|
}
|
|
14
17
|
interface VideoClipSessionConfig {
|
|
15
18
|
clipId: string;
|
|
19
|
+
sessionId?: string;
|
|
20
|
+
forL2Only?: boolean;
|
|
16
21
|
planner: CompositionPlanner;
|
|
17
22
|
workerPool: WorkerPool;
|
|
18
23
|
cacheManager: CacheManager;
|
|
@@ -22,6 +27,7 @@ interface VideoClipSessionConfig {
|
|
|
22
27
|
}
|
|
23
28
|
export declare class VideoClipSession {
|
|
24
29
|
private readonly clipId;
|
|
30
|
+
private readonly sessionId;
|
|
25
31
|
private readonly planner;
|
|
26
32
|
private readonly workerPool;
|
|
27
33
|
private readonly cacheManager;
|
|
@@ -45,20 +51,19 @@ export declare class VideoClipSession {
|
|
|
45
51
|
deactivate(): Promise<void>;
|
|
46
52
|
dispose(): Promise<void>;
|
|
47
53
|
handlePlannerUpdate(update: ClipUpdateResult): Promise<void>;
|
|
48
|
-
requestReplay(range: DirtyRange): Promise<void>;
|
|
49
54
|
get visualWorkerHandle(): BaseWorker | null;
|
|
50
55
|
private getClip;
|
|
51
56
|
private getResource;
|
|
52
57
|
private ensureInstructions;
|
|
53
|
-
private
|
|
58
|
+
private setupImagePipeline;
|
|
59
|
+
private connectImagePipeline;
|
|
60
|
+
private setupVideoPipeline;
|
|
54
61
|
private acquireWorkers;
|
|
55
62
|
private connectVideoPipeline;
|
|
56
63
|
private installInstructions;
|
|
57
64
|
private restartPipeline;
|
|
58
65
|
private releasePipeline;
|
|
59
|
-
|
|
60
|
-
private invalidateRanges;
|
|
61
|
-
private syncDirtyRanges;
|
|
66
|
+
invalidateClipCache(): Promise<void>;
|
|
62
67
|
}
|
|
63
68
|
export {};
|
|
64
69
|
//# sourceMappingURL=VideoClipSession.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VideoClipSession.d.ts","sourceRoot":"","sources":["../../src/orchestrator/VideoClipSession.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,KAAK,EAAE,gBAAgB,EAAQ,MAAM,UAAU,CAAC;AACvD,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"VideoClipSession.d.ts","sourceRoot":"","sources":["../../src/orchestrator/VideoClipSession.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
class VideoClipSession {
|
|
2
2
|
clipId;
|
|
3
|
+
sessionId;
|
|
3
4
|
planner;
|
|
4
5
|
workerPool;
|
|
5
6
|
cacheManager;
|
|
@@ -22,6 +23,7 @@ class VideoClipSession {
|
|
|
22
23
|
}
|
|
23
24
|
constructor(config) {
|
|
24
25
|
this.clipId = config.clipId;
|
|
26
|
+
this.sessionId = config.sessionId ?? config.clipId;
|
|
25
27
|
this.planner = config.planner;
|
|
26
28
|
this.workerPool = config.workerPool;
|
|
27
29
|
this.cacheManager = config.cacheManager;
|
|
@@ -33,20 +35,23 @@ class VideoClipSession {
|
|
|
33
35
|
if (this.isActive || this.isDisposed) return;
|
|
34
36
|
const clip = this.getClip();
|
|
35
37
|
const resource = this.getResource();
|
|
36
|
-
if (!clip || !resource
|
|
38
|
+
if (!clip || !resource) {
|
|
37
39
|
return;
|
|
38
40
|
}
|
|
39
|
-
|
|
41
|
+
if (resource.type === "video") {
|
|
42
|
+
await this.setupVideoPipeline(clip, resource);
|
|
43
|
+
} else if (resource.type === "image") {
|
|
44
|
+
await this.setupImagePipeline(clip);
|
|
45
|
+
}
|
|
40
46
|
await this.ensureInstructions(clip);
|
|
41
47
|
this.isActive = true;
|
|
42
48
|
if (this.callbacks.onPipelineReady) {
|
|
43
|
-
await this.callbacks.onPipelineReady(
|
|
49
|
+
await this.callbacks.onPipelineReady();
|
|
44
50
|
}
|
|
45
51
|
}
|
|
46
52
|
async deactivate() {
|
|
47
53
|
if (!this.isActive || this.isDisposed) return;
|
|
48
54
|
this.isActive = false;
|
|
49
|
-
await this.invalidateClipCache();
|
|
50
55
|
await this.releasePipeline();
|
|
51
56
|
}
|
|
52
57
|
async dispose() {
|
|
@@ -69,31 +74,14 @@ class VideoClipSession {
|
|
|
69
74
|
}
|
|
70
75
|
const clip = this.getClip();
|
|
71
76
|
const resource = this.getResource();
|
|
72
|
-
if (!clip || !resource || resource.type !== "video") {
|
|
77
|
+
if (!clip || !resource || resource.type !== "video" && resource.type !== "image") {
|
|
73
78
|
return;
|
|
74
79
|
}
|
|
75
|
-
if (
|
|
80
|
+
if (this.isActive) {
|
|
81
|
+
await this.restartPipeline(clip, resource, instructions);
|
|
82
|
+
} else {
|
|
76
83
|
await this.activate();
|
|
77
84
|
}
|
|
78
|
-
if (update.type === "pipelineChange") {
|
|
79
|
-
await this.restartPipeline(clip, resource, instructions, update.dirtyRanges);
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
|
-
await this.installInstructions(instructions, update.dirtyRanges, {
|
|
83
|
-
expectCacheInvalidation: false,
|
|
84
|
-
triggerSync: update.type !== "instructionOnly"
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
async requestReplay(range) {
|
|
88
|
-
if (this.isDisposed || !this.isActive || !this.visualWorker || !this.instructionContext) {
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
await this.cacheManager.invalidateRange(range.startUs, range.endUs, this.clipId);
|
|
92
|
-
await this.visualWorker.send("sync_clip", {
|
|
93
|
-
clipId: this.clipId,
|
|
94
|
-
revision: this.instructionContext.revision,
|
|
95
|
-
range
|
|
96
|
-
});
|
|
97
85
|
}
|
|
98
86
|
get visualWorkerHandle() {
|
|
99
87
|
return this.visualWorker;
|
|
@@ -106,33 +94,75 @@ class VideoClipSession {
|
|
|
106
94
|
if (!clip) return null;
|
|
107
95
|
return this.compositionModel.resources.get(clip.resourceId) || null;
|
|
108
96
|
}
|
|
109
|
-
async ensureInstructions(
|
|
97
|
+
async ensureInstructions(_clip) {
|
|
110
98
|
const instructions = this.planner.getInstructions(this.clipId);
|
|
111
99
|
if (!instructions) {
|
|
112
100
|
throw new Error(`No instructions for clip ${this.clipId}`);
|
|
113
101
|
}
|
|
114
|
-
await this.installInstructions(instructions
|
|
102
|
+
await this.installInstructions(instructions);
|
|
103
|
+
}
|
|
104
|
+
async setupImagePipeline(clip) {
|
|
105
|
+
await this.acquireWorkers(clip, false);
|
|
106
|
+
await this.connectImagePipeline();
|
|
107
|
+
}
|
|
108
|
+
async connectImagePipeline() {
|
|
109
|
+
if (!this.visualWorker || !this.encodeWorker) {
|
|
110
|
+
throw new Error("Pipeline workers not ready");
|
|
111
|
+
}
|
|
112
|
+
const sessionId = this.sessionId;
|
|
113
|
+
this.visualToEncodeChannel = new MessageChannel();
|
|
114
|
+
await this.visualWorker.send(
|
|
115
|
+
"connect",
|
|
116
|
+
{
|
|
117
|
+
direction: "downstream",
|
|
118
|
+
port: this.visualToEncodeChannel.port1,
|
|
119
|
+
streamType: "video",
|
|
120
|
+
sessionId
|
|
121
|
+
},
|
|
122
|
+
{ transfer: [this.visualToEncodeChannel.port1] }
|
|
123
|
+
);
|
|
124
|
+
await this.encodeWorker.send(
|
|
125
|
+
"connect",
|
|
115
126
|
{
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
127
|
+
direction: "upstream",
|
|
128
|
+
port: this.visualToEncodeChannel.port2,
|
|
129
|
+
streamType: "video",
|
|
130
|
+
sessionId
|
|
131
|
+
},
|
|
132
|
+
{ transfer: [this.visualToEncodeChannel.port2] }
|
|
133
|
+
);
|
|
134
|
+
this.visualWorker.receiveStream((stream) => {
|
|
135
|
+
const visualConfig = this.workerConfigs.videoCompose ?? {};
|
|
136
|
+
const fps = this.compositionModel.fps ?? visualConfig.fps ?? 30;
|
|
137
|
+
this.callbacks.onComposedStreamReady(stream, fps);
|
|
138
|
+
});
|
|
139
|
+
this.encodeWorker.receiveStream((stream, metadata) => {
|
|
140
|
+
if (metadata?.streamType === "encoded-video") {
|
|
141
|
+
this.callbacks.onEncodedStreamReady(
|
|
142
|
+
stream,
|
|
143
|
+
"video"
|
|
144
|
+
);
|
|
145
|
+
} else if (metadata?.streamType === "encoded-audio") {
|
|
146
|
+
this.callbacks.onEncodedStreamReady(
|
|
147
|
+
stream,
|
|
148
|
+
"audio"
|
|
149
|
+
);
|
|
121
150
|
}
|
|
122
|
-
|
|
151
|
+
});
|
|
123
152
|
}
|
|
124
|
-
async
|
|
125
|
-
await this.acquireWorkers(clip);
|
|
126
|
-
await this.connectVideoPipeline(
|
|
127
|
-
if (!this.visualWorker) {
|
|
128
|
-
throw new Error("Visual worker unavailable");
|
|
129
|
-
}
|
|
153
|
+
async setupVideoPipeline(clip, resource) {
|
|
154
|
+
await this.acquireWorkers(clip, true);
|
|
155
|
+
await this.connectVideoPipeline(resource.id);
|
|
130
156
|
}
|
|
131
|
-
async acquireWorkers(clip) {
|
|
132
|
-
|
|
133
|
-
|
|
157
|
+
async acquireWorkers(clip, isVideo) {
|
|
158
|
+
if (isVideo) {
|
|
159
|
+
this.decodeWorker = await this.workerPool.get("decode");
|
|
160
|
+
this.videoDemuxWorker = await this.workerPool.get("videoDemux", this.sessionId, {
|
|
161
|
+
lazy: true
|
|
162
|
+
});
|
|
163
|
+
}
|
|
134
164
|
this.encodeWorker = await this.workerPool.get("encode");
|
|
135
|
-
this.
|
|
165
|
+
this.visualWorker = await this.workerPool.get("videoCompose", this.sessionId, { lazy: true });
|
|
136
166
|
const visualConfig = this.workerConfigs.videoCompose ?? {};
|
|
137
167
|
const renderOverrides = this.compositionModel.renderConfig ?? {};
|
|
138
168
|
const timeline = {
|
|
@@ -147,11 +177,11 @@ class VideoClipSession {
|
|
|
147
177
|
config: { ...visualConfig, ...renderOverrides, timeline }
|
|
148
178
|
});
|
|
149
179
|
}
|
|
150
|
-
async connectVideoPipeline(
|
|
180
|
+
async connectVideoPipeline(resourceId) {
|
|
151
181
|
if (!this.visualWorker || !this.decodeWorker || !this.encodeWorker || !this.videoDemuxWorker) {
|
|
152
182
|
throw new Error("Pipeline workers not ready");
|
|
153
183
|
}
|
|
154
|
-
const
|
|
184
|
+
const sessionId = this.sessionId;
|
|
155
185
|
this.visualToEncodeChannel = new MessageChannel();
|
|
156
186
|
await this.visualWorker.send(
|
|
157
187
|
"connect",
|
|
@@ -159,7 +189,7 @@ class VideoClipSession {
|
|
|
159
189
|
direction: "downstream",
|
|
160
190
|
port: this.visualToEncodeChannel.port1,
|
|
161
191
|
streamType: "video",
|
|
162
|
-
|
|
192
|
+
sessionId
|
|
163
193
|
},
|
|
164
194
|
{ transfer: [this.visualToEncodeChannel.port1] }
|
|
165
195
|
);
|
|
@@ -169,7 +199,7 @@ class VideoClipSession {
|
|
|
169
199
|
direction: "upstream",
|
|
170
200
|
port: this.visualToEncodeChannel.port2,
|
|
171
201
|
streamType: "video",
|
|
172
|
-
|
|
202
|
+
sessionId
|
|
173
203
|
},
|
|
174
204
|
{ transfer: [this.visualToEncodeChannel.port2] }
|
|
175
205
|
);
|
|
@@ -180,7 +210,7 @@ class VideoClipSession {
|
|
|
180
210
|
direction: "downstream",
|
|
181
211
|
port: this.decodeToVisualChannel.port1,
|
|
182
212
|
streamType: "video",
|
|
183
|
-
|
|
213
|
+
sessionId
|
|
184
214
|
},
|
|
185
215
|
{ transfer: [this.decodeToVisualChannel.port1] }
|
|
186
216
|
);
|
|
@@ -190,7 +220,7 @@ class VideoClipSession {
|
|
|
190
220
|
direction: "upstream",
|
|
191
221
|
port: this.decodeToVisualChannel.port2,
|
|
192
222
|
streamType: "video",
|
|
193
|
-
|
|
223
|
+
sessionId
|
|
194
224
|
},
|
|
195
225
|
{ transfer: [this.decodeToVisualChannel.port2] }
|
|
196
226
|
);
|
|
@@ -201,7 +231,7 @@ class VideoClipSession {
|
|
|
201
231
|
direction: "downstream",
|
|
202
232
|
port: this.demuxToDecodeChannel.port1,
|
|
203
233
|
streamType: "video",
|
|
204
|
-
|
|
234
|
+
sessionId
|
|
205
235
|
},
|
|
206
236
|
{ transfer: [this.demuxToDecodeChannel.port1] }
|
|
207
237
|
);
|
|
@@ -211,7 +241,7 @@ class VideoClipSession {
|
|
|
211
241
|
direction: "upstream",
|
|
212
242
|
port: this.demuxToDecodeChannel.port2,
|
|
213
243
|
streamType: "video",
|
|
214
|
-
|
|
244
|
+
sessionId
|
|
215
245
|
},
|
|
216
246
|
{ transfer: [this.demuxToDecodeChannel.port2] }
|
|
217
247
|
);
|
|
@@ -219,43 +249,51 @@ class VideoClipSession {
|
|
|
219
249
|
await this.videoDemuxWorker.send("configure", {
|
|
220
250
|
initial: true,
|
|
221
251
|
resourceId,
|
|
222
|
-
|
|
252
|
+
sessionId,
|
|
223
253
|
config: demuxConfig
|
|
224
254
|
});
|
|
225
255
|
this.visualWorker.receiveStream((stream) => {
|
|
226
256
|
const visualConfig = this.workerConfigs.videoCompose ?? {};
|
|
227
257
|
const fps = this.compositionModel.fps ?? visualConfig.fps ?? 30;
|
|
228
|
-
this.callbacks.
|
|
258
|
+
this.callbacks.onComposedStreamReady(stream, fps);
|
|
259
|
+
});
|
|
260
|
+
this.encodeWorker.receiveStream((stream, metadata) => {
|
|
261
|
+
if (metadata?.streamType === "video") {
|
|
262
|
+
this.callbacks.onEncodedStreamReady(
|
|
263
|
+
stream,
|
|
264
|
+
"video"
|
|
265
|
+
);
|
|
266
|
+
} else if (metadata?.streamType === "audio") {
|
|
267
|
+
this.callbacks.onEncodedStreamReady(
|
|
268
|
+
stream,
|
|
269
|
+
"audio"
|
|
270
|
+
);
|
|
271
|
+
}
|
|
229
272
|
});
|
|
230
273
|
}
|
|
231
|
-
async installInstructions(instructions
|
|
274
|
+
async installInstructions(instructions) {
|
|
232
275
|
this.instructionContext = {
|
|
233
276
|
revision: instructions.revision,
|
|
234
277
|
instructions,
|
|
235
278
|
status: instructions.status
|
|
236
279
|
};
|
|
237
|
-
if (options?.expectCacheInvalidation) {
|
|
238
|
-
await this.invalidateRanges(dirtyRanges);
|
|
239
|
-
}
|
|
240
280
|
if (this.visualWorker) {
|
|
241
281
|
await this.visualWorker.send("install_instructions", instructions);
|
|
242
282
|
}
|
|
243
|
-
if (options?.triggerSync) {
|
|
244
|
-
await this.syncDirtyRanges(dirtyRanges, instructions.revision);
|
|
245
|
-
}
|
|
246
283
|
}
|
|
247
|
-
async restartPipeline(clip, resource, instructions
|
|
284
|
+
async restartPipeline(clip, resource, instructions) {
|
|
248
285
|
await this.releasePipeline();
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
}
|
|
286
|
+
if (resource.type === "video") {
|
|
287
|
+
await this.setupVideoPipeline(clip, resource);
|
|
288
|
+
} else if (resource.type === "image") {
|
|
289
|
+
await this.setupImagePipeline(clip);
|
|
290
|
+
}
|
|
291
|
+
await this.installInstructions(instructions);
|
|
254
292
|
}
|
|
255
293
|
async releasePipeline() {
|
|
256
294
|
if (this.visualWorker && this.instructionContext) {
|
|
257
295
|
await this.visualWorker.notify("dispose_clip", {
|
|
258
|
-
|
|
296
|
+
sessionId: this.sessionId,
|
|
259
297
|
revision: this.instructionContext.revision
|
|
260
298
|
});
|
|
261
299
|
}
|
|
@@ -269,15 +307,15 @@ class VideoClipSession {
|
|
|
269
307
|
this.decodeToVisualChannel = null;
|
|
270
308
|
this.demuxToDecodeChannel = null;
|
|
271
309
|
if (this.visualStream && this.callbacks.onStreamDisposed) {
|
|
272
|
-
this.callbacks.onStreamDisposed(
|
|
310
|
+
this.callbacks.onStreamDisposed();
|
|
273
311
|
}
|
|
274
312
|
this.visualStream = null;
|
|
275
313
|
if (this.videoDemuxWorker) {
|
|
276
|
-
this.workerPool.terminate("videoDemux", this.
|
|
314
|
+
this.workerPool.terminate("videoDemux", this.sessionId);
|
|
277
315
|
this.videoDemuxWorker = null;
|
|
278
316
|
}
|
|
279
317
|
if (this.visualWorker) {
|
|
280
|
-
this.workerPool.terminate("videoCompose", this.
|
|
318
|
+
this.workerPool.terminate("videoCompose", this.sessionId);
|
|
281
319
|
this.visualWorker = null;
|
|
282
320
|
}
|
|
283
321
|
this.decodeWorker = null;
|
|
@@ -286,21 +324,6 @@ class VideoClipSession {
|
|
|
286
324
|
async invalidateClipCache() {
|
|
287
325
|
await this.cacheManager.invalidateClip(this.clipId);
|
|
288
326
|
}
|
|
289
|
-
async invalidateRanges(ranges) {
|
|
290
|
-
for (const range of ranges) {
|
|
291
|
-
await this.cacheManager.invalidateRange(range.startUs, range.endUs, this.clipId);
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
async syncDirtyRanges(ranges, revision) {
|
|
295
|
-
if (!this.visualWorker) return;
|
|
296
|
-
for (const range of ranges) {
|
|
297
|
-
await this.visualWorker.send("sync_clip", {
|
|
298
|
-
clipId: this.clipId,
|
|
299
|
-
revision,
|
|
300
|
-
range
|
|
301
|
-
});
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
327
|
}
|
|
305
328
|
export {
|
|
306
329
|
VideoClipSession
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VideoClipSession.js","sources":["../../src/orchestrator/VideoClipSession.ts"],"sourcesContent":["import type { WorkerPool } from '../worker/WorkerPool';\nimport type { CacheManager } from '../cache/CacheManager';\nimport type { CompositionModel, Clip } from '../model';\nimport type { DirtyRange } from './types';\nimport type { CompositionPlanner, ClipUpdateResult } from './CompositionPlanner';\nimport type { ClipInstructionSet } from '../stages/compose/instructions';\nimport type { BaseWorker } from '../worker/BaseWorker';\nimport type { WorkerType } from '../worker/types';\n\ninterface VideoClipSessionCallbacks {\n onStreamReady(clipId: string, stream: ReadableStream<VideoFrame>, fps: number): void;\n onStreamDisposed?(clipId: string): void;\n onPipelineReady?(clipId: string): Promise<void>;\n}\n\ninterface VideoClipSessionConfig {\n clipId: string;\n planner: CompositionPlanner;\n workerPool: WorkerPool;\n cacheManager: CacheManager;\n compositionModel: CompositionModel;\n workerConfigs: Record<WorkerType, any>;\n callbacks: VideoClipSessionCallbacks;\n}\n\ninterface InstructionContext {\n revision: number;\n instructions: ClipInstructionSet;\n status: ClipInstructionSet['status'];\n}\n\nexport class VideoClipSession {\n private readonly clipId: string;\n private readonly planner: CompositionPlanner;\n private readonly workerPool: WorkerPool;\n private readonly cacheManager: CacheManager;\n private readonly compositionModel: CompositionModel;\n private readonly workerConfigs: Record<WorkerType, any>;\n private readonly callbacks: VideoClipSessionCallbacks;\n\n private instructionContext: InstructionContext | null = null;\n private visualWorker: BaseWorker | null = null;\n private decodeWorker: BaseWorker | null = null;\n private encodeWorker: BaseWorker | null = null;\n private videoDemuxWorker: BaseWorker | null = null;\n private visualStream: ReadableStream<VideoFrame> | null = null;\n private visualToEncodeChannel: MessageChannel | null = null;\n private decodeToVisualChannel: MessageChannel | null = null;\n private demuxToDecodeChannel: MessageChannel | null = null;\n private isActive = false;\n private isDisposed = false;\n\n static async create(config: VideoClipSessionConfig): Promise<VideoClipSession> {\n return new VideoClipSession(config);\n }\n\n private constructor(config: VideoClipSessionConfig) {\n this.clipId = config.clipId;\n this.planner = config.planner;\n this.workerPool = config.workerPool;\n this.cacheManager = config.cacheManager;\n this.compositionModel = config.compositionModel;\n this.workerConfigs = config.workerConfigs;\n this.callbacks = config.callbacks;\n }\n\n async activate(): Promise<void> {\n if (this.isActive || this.isDisposed) return;\n\n const clip = this.getClip();\n const resource = this.getResource();\n if (!clip || !resource || resource.type !== 'video') {\n return;\n }\n\n await this.setupPipeline(clip, resource);\n await this.ensureInstructions(clip);\n\n this.isActive = true;\n\n // Notify that pipeline is ready - triggers resource loading\n if (this.callbacks.onPipelineReady) {\n await this.callbacks.onPipelineReady(this.clipId);\n }\n }\n\n async deactivate(): Promise<void> {\n if (!this.isActive || this.isDisposed) return;\n this.isActive = false;\n\n await this.invalidateClipCache();\n await this.releasePipeline();\n }\n\n async dispose(): Promise<void> {\n if (this.isDisposed) return;\n await this.deactivate();\n this.planner.releaseClip(this.clipId);\n this.isDisposed = true;\n }\n\n async handlePlannerUpdate(update: ClipUpdateResult): Promise<void> {\n if (this.isDisposed) {\n return;\n }\n\n if (update.type === 'remove') {\n await this.dispose();\n return;\n }\n\n const instructions = update.instructions;\n if (!instructions) {\n return;\n }\n\n const clip = this.getClip();\n const resource = this.getResource();\n if (!clip || !resource || resource.type !== 'video') {\n return;\n }\n\n if (!this.isActive) {\n await this.activate();\n }\n\n if (update.type === 'pipelineChange') {\n await this.restartPipeline(clip, resource, instructions, update.dirtyRanges);\n return;\n }\n\n await this.installInstructions(instructions, update.dirtyRanges, {\n expectCacheInvalidation: false,\n triggerSync: update.type !== 'instructionOnly',\n });\n }\n\n async requestReplay(range: DirtyRange): Promise<void> {\n if (this.isDisposed || !this.isActive || !this.visualWorker || !this.instructionContext) {\n return;\n }\n\n await this.cacheManager.invalidateRange(range.startUs, range.endUs, this.clipId);\n await this.visualWorker.send('sync_clip', {\n clipId: this.clipId,\n revision: this.instructionContext.revision,\n range,\n });\n }\n\n get visualWorkerHandle(): BaseWorker | null {\n return this.visualWorker;\n }\n\n private getClip(): Clip | null {\n return this.compositionModel?.findClip?.(this.clipId) ?? null;\n }\n\n private getResource() {\n const clip = this.getClip();\n if (!clip) return null;\n return this.compositionModel.resources.get(clip.resourceId) || null;\n }\n\n private async ensureInstructions(clip: Clip): Promise<void> {\n const instructions = this.planner.getInstructions(this.clipId);\n if (!instructions) {\n throw new Error(`No instructions for clip ${this.clipId}`);\n }\n\n await this.installInstructions(instructions, [\n {\n clipId: clip.id,\n trackId: clip.trackId || 'main',\n startUs: clip.startUs,\n endUs: clip.startUs + clip.durationUs,\n reason: 'initial-install',\n },\n ]);\n }\n\n private async setupPipeline(clip: Clip, resource: { id: string }): Promise<void> {\n await this.acquireWorkers(clip);\n await this.connectVideoPipeline(clip, resource.id);\n\n if (!this.visualWorker) {\n throw new Error('Visual worker unavailable');\n }\n\n // this.visualStream = await this.visualWorker.send<never, ReadableStream<VideoFrame>>(\n // 'get_stream'\n // );\n\n // if (this.visualStream) {\n // const visualConfig = this.workerConfigs.videoCompose ?? {};\n // const fps = this.compositionModel.fps ?? visualConfig.fps ?? 30;\n // this.callbacks.onStreamReady(this.clipId, this.visualStream, clip.trackId || 'main', fps);\n // }\n }\n\n private async acquireWorkers(clip: Clip): Promise<void> {\n this.visualWorker = await this.workerPool.get('videoCompose', clip.id, { lazy: true });\n this.decodeWorker = await this.workerPool.get('decode');\n this.encodeWorker = await this.workerPool.get('encode');\n this.videoDemuxWorker = await this.workerPool.get('videoDemux', clip.id, { lazy: true });\n\n const visualConfig = this.workerConfigs.videoCompose ?? {};\n const renderOverrides = this.compositionModel.renderConfig ?? {};\n const timeline = {\n clipId: clip.id,\n clipStartUs: clip.startUs,\n clipEndUs: clip.startUs + clip.durationUs,\n compositionFps: this.compositionModel.fps ?? visualConfig.fps ?? 30,\n };\n\n await this.visualWorker.send('configure', {\n initial: true,\n clipId: clip.id,\n config: { ...visualConfig, ...renderOverrides, timeline },\n });\n }\n\n private async connectVideoPipeline(clip: Clip, resourceId: string): Promise<void> {\n if (!this.visualWorker || !this.decodeWorker || !this.encodeWorker || !this.videoDemuxWorker) {\n throw new Error('Pipeline workers not ready');\n }\n\n const clipId = clip.id;\n\n this.visualToEncodeChannel = new MessageChannel();\n await this.visualWorker.send(\n 'connect',\n {\n direction: 'downstream',\n port: this.visualToEncodeChannel.port1,\n streamType: 'video',\n clipId,\n },\n { transfer: [this.visualToEncodeChannel.port1] }\n );\n await this.encodeWorker.send(\n 'connect',\n {\n direction: 'upstream',\n port: this.visualToEncodeChannel.port2,\n streamType: 'video',\n clipId,\n },\n { transfer: [this.visualToEncodeChannel.port2] }\n );\n\n this.decodeToVisualChannel = new MessageChannel();\n await this.decodeWorker.send(\n 'connect',\n {\n direction: 'downstream',\n port: this.decodeToVisualChannel.port1,\n streamType: 'video',\n clipId,\n },\n { transfer: [this.decodeToVisualChannel.port1] }\n );\n await this.visualWorker.send(\n 'connect',\n {\n direction: 'upstream',\n port: this.decodeToVisualChannel.port2,\n streamType: 'video',\n clipId,\n },\n { transfer: [this.decodeToVisualChannel.port2] }\n );\n\n this.demuxToDecodeChannel = new MessageChannel();\n await this.videoDemuxWorker.send(\n 'connect',\n {\n direction: 'downstream',\n port: this.demuxToDecodeChannel.port1,\n streamType: 'video',\n clipId,\n },\n { transfer: [this.demuxToDecodeChannel.port1] }\n );\n await this.decodeWorker.send(\n 'connect',\n {\n direction: 'upstream',\n port: this.demuxToDecodeChannel.port2,\n streamType: 'video',\n clipId,\n },\n { transfer: [this.demuxToDecodeChannel.port2] }\n );\n\n const demuxConfig = this.workerConfigs.videoDemux ?? {};\n await this.videoDemuxWorker.send('configure', {\n initial: true,\n resourceId,\n clipId,\n config: demuxConfig,\n });\n\n this.visualWorker.receiveStream((stream) => {\n const visualConfig = this.workerConfigs.videoCompose ?? {};\n const fps = this.compositionModel.fps ?? visualConfig.fps ?? 30;\n this.callbacks.onStreamReady(this.clipId, stream, fps);\n });\n }\n\n private async installInstructions(\n instructions: ClipInstructionSet,\n dirtyRanges: DirtyRange[],\n options?: { expectCacheInvalidation?: boolean; triggerSync?: boolean }\n ): Promise<void> {\n this.instructionContext = {\n revision: instructions.revision,\n instructions,\n status: instructions.status,\n };\n\n if (options?.expectCacheInvalidation) {\n await this.invalidateRanges(dirtyRanges);\n }\n\n if (this.visualWorker) {\n await this.visualWorker.send('install_instructions', instructions);\n }\n\n if (options?.triggerSync) {\n await this.syncDirtyRanges(dirtyRanges, instructions.revision);\n }\n }\n\n private async restartPipeline(\n clip: Clip,\n resource: { id: string },\n instructions: ClipInstructionSet,\n dirtyRanges: DirtyRange[]\n ): Promise<void> {\n await this.releasePipeline();\n await this.setupPipeline(clip, resource);\n await this.installInstructions(instructions, dirtyRanges, {\n expectCacheInvalidation: true,\n triggerSync: true,\n });\n }\n\n private async releasePipeline(): Promise<void> {\n if (this.visualWorker && this.instructionContext) {\n await this.visualWorker.notify('dispose_clip', {\n clipId: this.clipId,\n revision: this.instructionContext.revision,\n });\n }\n\n this.visualToEncodeChannel?.port1.close();\n this.visualToEncodeChannel?.port2.close();\n this.decodeToVisualChannel?.port1.close();\n this.decodeToVisualChannel?.port2.close();\n this.demuxToDecodeChannel?.port1.close();\n this.demuxToDecodeChannel?.port2.close();\n\n this.visualToEncodeChannel = null;\n this.decodeToVisualChannel = null;\n this.demuxToDecodeChannel = null;\n\n if (this.visualStream && this.callbacks.onStreamDisposed) {\n this.callbacks.onStreamDisposed(this.clipId);\n }\n this.visualStream = null;\n\n if (this.videoDemuxWorker) {\n this.workerPool.terminate('videoDemux', this.clipId);\n this.videoDemuxWorker = null;\n }\n\n if (this.visualWorker) {\n this.workerPool.terminate('videoCompose', this.clipId);\n this.visualWorker = null;\n }\n\n // Shared workers are not terminated here (decode / encode)\n this.decodeWorker = null;\n this.encodeWorker = null;\n }\n\n private async invalidateClipCache(): Promise<void> {\n await this.cacheManager.invalidateClip(this.clipId);\n }\n\n private async invalidateRanges(ranges: DirtyRange[]): Promise<void> {\n for (const range of ranges) {\n await this.cacheManager.invalidateRange(range.startUs, range.endUs, this.clipId);\n }\n }\n\n private async syncDirtyRanges(ranges: DirtyRange[], revision: number): Promise<void> {\n if (!this.visualWorker) return;\n\n for (const range of ranges) {\n await this.visualWorker.send('sync_clip', {\n clipId: this.clipId,\n revision,\n range,\n });\n }\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"VideoClipSession.js","sources":["../../src/orchestrator/VideoClipSession.ts"],"sourcesContent":["import type { WorkerPool } from '../worker/WorkerPool';\nimport type { CacheManager } from '../cache/CacheManager';\nimport type { CompositionModel, Clip } from '../model';\nimport type { CompositionPlanner, ClipUpdateResult } from './CompositionPlanner';\nimport type { ClipInstructionSet } from '../stages/compose/instructions';\nimport type { BaseWorker } from '../worker/BaseWorker';\nimport type { WorkerType } from '../worker/types';\n\ninterface VideoClipSessionCallbacks {\n onComposedStreamReady(stream: ReadableStream<VideoFrame>, fps: number): void;\n onEncodedStreamReady(\n stream: ReadableStream<{ chunk: EncodedVideoChunk; metadata: EncodedVideoChunkMetadata }>,\n track: 'video' | 'audio'\n ): void;\n onStreamDisposed?(): void;\n onPipelineReady?(): Promise<void>;\n}\n\ninterface VideoClipSessionConfig {\n clipId: string;\n sessionId?: string;\n forL2Only?: boolean;\n planner: CompositionPlanner;\n workerPool: WorkerPool;\n cacheManager: CacheManager;\n compositionModel: CompositionModel;\n workerConfigs: Record<WorkerType, any>;\n callbacks: VideoClipSessionCallbacks;\n}\n\ninterface InstructionContext {\n revision: number;\n instructions: ClipInstructionSet;\n status: ClipInstructionSet['status'];\n}\n\nexport class VideoClipSession {\n private readonly clipId: string;\n private readonly sessionId: string;\n private readonly planner: CompositionPlanner;\n private readonly workerPool: WorkerPool;\n private readonly cacheManager: CacheManager;\n private readonly compositionModel: CompositionModel;\n private readonly workerConfigs: Record<WorkerType, any>;\n private readonly callbacks: VideoClipSessionCallbacks;\n\n private instructionContext: InstructionContext | null = null;\n private visualWorker: BaseWorker | null = null;\n private decodeWorker: BaseWorker | null = null;\n private encodeWorker: BaseWorker | null = null;\n private videoDemuxWorker: BaseWorker | null = null;\n private visualStream: ReadableStream<VideoFrame> | null = null;\n private visualToEncodeChannel: MessageChannel | null = null;\n private decodeToVisualChannel: MessageChannel | null = null;\n private demuxToDecodeChannel: MessageChannel | null = null;\n private isActive = false;\n private isDisposed = false;\n\n static async create(config: VideoClipSessionConfig): Promise<VideoClipSession> {\n return new VideoClipSession(config);\n }\n\n private constructor(config: VideoClipSessionConfig) {\n this.clipId = config.clipId;\n this.sessionId = config.sessionId ?? config.clipId;\n this.planner = config.planner;\n this.workerPool = config.workerPool;\n this.cacheManager = config.cacheManager;\n this.compositionModel = config.compositionModel;\n this.workerConfigs = config.workerConfigs;\n this.callbacks = config.callbacks;\n }\n\n async activate(): Promise<void> {\n if (this.isActive || this.isDisposed) return;\n\n const clip = this.getClip();\n const resource = this.getResource();\n if (!clip || !resource) {\n return;\n }\n\n if (resource.type === 'video') {\n await this.setupVideoPipeline(clip, resource);\n } else if (resource.type === 'image') {\n await this.setupImagePipeline(clip);\n }\n\n await this.ensureInstructions(clip);\n\n this.isActive = true;\n\n // Notify that pipeline is ready - triggers resource loading\n if (this.callbacks.onPipelineReady) {\n await this.callbacks.onPipelineReady();\n }\n }\n\n async deactivate(): Promise<void> {\n if (!this.isActive || this.isDisposed) return;\n this.isActive = false;\n\n await this.releasePipeline();\n }\n\n async dispose(): Promise<void> {\n if (this.isDisposed) return;\n await this.deactivate();\n this.planner.releaseClip(this.clipId);\n this.isDisposed = true;\n }\n\n async handlePlannerUpdate(update: ClipUpdateResult): Promise<void> {\n if (this.isDisposed) {\n return;\n }\n\n if (update.type === 'remove') {\n await this.dispose();\n return;\n }\n\n const instructions = update.instructions;\n if (!instructions) {\n return;\n }\n\n const clip = this.getClip();\n const resource = this.getResource();\n if (!clip || !resource || (resource.type !== 'video' && resource.type !== 'image')) {\n return;\n }\n\n // Any update requires pipeline restart (stream is closed after cache eviction)\n if (this.isActive) {\n await this.restartPipeline(clip, resource, instructions);\n } else {\n await this.activate();\n }\n }\n\n get visualWorkerHandle(): BaseWorker | null {\n return this.visualWorker;\n }\n\n private getClip(): Clip | null {\n return this.compositionModel?.findClip?.(this.clipId) ?? null;\n }\n\n private getResource() {\n const clip = this.getClip();\n if (!clip) return null;\n return this.compositionModel.resources.get(clip.resourceId) || null;\n }\n\n private async ensureInstructions(_clip: Clip): Promise<void> {\n const instructions = this.planner.getInstructions(this.clipId);\n if (!instructions) {\n throw new Error(`No instructions for clip ${this.clipId}`);\n }\n await this.installInstructions(instructions);\n }\n\n private async setupImagePipeline(clip: Clip): Promise<void> {\n await this.acquireWorkers(clip, false);\n await this.connectImagePipeline();\n }\n\n private async connectImagePipeline(): Promise<void> {\n if (!this.visualWorker || !this.encodeWorker) {\n throw new Error('Pipeline workers not ready');\n }\n\n // Use sessionId for worker communication\n const sessionId = this.sessionId;\n\n this.visualToEncodeChannel = new MessageChannel();\n await this.visualWorker.send(\n 'connect',\n {\n direction: 'downstream',\n port: this.visualToEncodeChannel.port1,\n streamType: 'video',\n sessionId,\n },\n { transfer: [this.visualToEncodeChannel.port1] }\n );\n await this.encodeWorker.send(\n 'connect',\n {\n direction: 'upstream',\n port: this.visualToEncodeChannel.port2,\n streamType: 'video',\n sessionId,\n },\n { transfer: [this.visualToEncodeChannel.port2] }\n );\n\n this.visualWorker.receiveStream((stream) => {\n const visualConfig = this.workerConfigs.videoCompose ?? {};\n const fps = this.compositionModel.fps ?? visualConfig.fps ?? 30;\n this.callbacks.onComposedStreamReady(stream, fps);\n });\n\n // Receive encoded chunks from EncodeWorker and forward to callback\n this.encodeWorker.receiveStream((stream, metadata) => {\n if (metadata?.streamType === 'encoded-video') {\n this.callbacks.onEncodedStreamReady(\n stream as ReadableStream<{\n chunk: EncodedVideoChunk;\n metadata: EncodedVideoChunkMetadata;\n }>,\n 'video'\n );\n } else if (metadata?.streamType === 'encoded-audio') {\n this.callbacks.onEncodedStreamReady(\n stream as ReadableStream<{\n chunk: EncodedVideoChunk;\n metadata: EncodedVideoChunkMetadata;\n }>,\n 'audio'\n );\n }\n });\n }\n\n private async setupVideoPipeline(clip: Clip, resource: { id: string }): Promise<void> {\n await this.acquireWorkers(clip, true);\n await this.connectVideoPipeline(resource.id);\n }\n\n private async acquireWorkers(clip: Clip, isVideo: boolean): Promise<void> {\n if (isVideo) {\n this.decodeWorker = await this.workerPool.get('decode');\n this.videoDemuxWorker = await this.workerPool.get('videoDemux', this.sessionId, {\n lazy: true,\n });\n }\n\n this.encodeWorker = await this.workerPool.get('encode');\n this.visualWorker = await this.workerPool.get('videoCompose', this.sessionId, { lazy: true });\n\n const visualConfig = this.workerConfigs.videoCompose ?? {};\n const renderOverrides = this.compositionModel.renderConfig ?? {};\n const timeline = {\n clipId: clip.id,\n clipStartUs: clip.startUs,\n clipEndUs: clip.startUs + clip.durationUs,\n compositionFps: this.compositionModel.fps ?? visualConfig.fps ?? 30,\n };\n await this.visualWorker.send('configure', {\n initial: true,\n clipId: clip.id,\n config: { ...visualConfig, ...renderOverrides, timeline },\n });\n }\n\n private async connectVideoPipeline(resourceId: string): Promise<void> {\n if (!this.visualWorker || !this.decodeWorker || !this.encodeWorker || !this.videoDemuxWorker) {\n throw new Error('Pipeline workers not ready');\n }\n\n // Use sessionId for worker communication\n const sessionId = this.sessionId;\n\n this.visualToEncodeChannel = new MessageChannel();\n await this.visualWorker.send(\n 'connect',\n {\n direction: 'downstream',\n port: this.visualToEncodeChannel.port1,\n streamType: 'video',\n sessionId,\n },\n { transfer: [this.visualToEncodeChannel.port1] }\n );\n await this.encodeWorker.send(\n 'connect',\n {\n direction: 'upstream',\n port: this.visualToEncodeChannel.port2,\n streamType: 'video',\n sessionId,\n },\n { transfer: [this.visualToEncodeChannel.port2] }\n );\n\n this.decodeToVisualChannel = new MessageChannel();\n await this.decodeWorker.send(\n 'connect',\n {\n direction: 'downstream',\n port: this.decodeToVisualChannel.port1,\n streamType: 'video',\n sessionId,\n },\n { transfer: [this.decodeToVisualChannel.port1] }\n );\n await this.visualWorker.send(\n 'connect',\n {\n direction: 'upstream',\n port: this.decodeToVisualChannel.port2,\n streamType: 'video',\n sessionId,\n },\n { transfer: [this.decodeToVisualChannel.port2] }\n );\n\n this.demuxToDecodeChannel = new MessageChannel();\n await this.videoDemuxWorker.send(\n 'connect',\n {\n direction: 'downstream',\n port: this.demuxToDecodeChannel.port1,\n streamType: 'video',\n sessionId,\n },\n { transfer: [this.demuxToDecodeChannel.port1] }\n );\n await this.decodeWorker.send(\n 'connect',\n {\n direction: 'upstream',\n port: this.demuxToDecodeChannel.port2,\n streamType: 'video',\n sessionId,\n },\n { transfer: [this.demuxToDecodeChannel.port2] }\n );\n\n const demuxConfig = this.workerConfigs.videoDemux ?? {};\n await this.videoDemuxWorker.send('configure', {\n initial: true,\n resourceId,\n sessionId,\n config: demuxConfig,\n });\n\n this.visualWorker.receiveStream((stream) => {\n const visualConfig = this.workerConfigs.videoCompose ?? {};\n const fps = this.compositionModel.fps ?? visualConfig.fps ?? 30;\n this.callbacks.onComposedStreamReady(stream, fps);\n });\n\n // Receive encoded chunks from EncodeWorker and forward to callback\n this.encodeWorker.receiveStream((stream, metadata) => {\n if (metadata?.streamType === 'video') {\n this.callbacks.onEncodedStreamReady(\n stream as ReadableStream<{\n chunk: EncodedVideoChunk;\n metadata: EncodedVideoChunkMetadata;\n }>,\n 'video'\n );\n } else if (metadata?.streamType === 'audio') {\n this.callbacks.onEncodedStreamReady(\n stream as ReadableStream<{\n chunk: EncodedVideoChunk;\n metadata: EncodedVideoChunkMetadata;\n }>,\n 'audio'\n );\n }\n });\n }\n\n private async installInstructions(instructions: ClipInstructionSet): Promise<void> {\n this.instructionContext = {\n revision: instructions.revision,\n instructions,\n status: instructions.status,\n };\n\n if (this.visualWorker) {\n await this.visualWorker.send('install_instructions', instructions);\n }\n }\n\n private async restartPipeline(\n clip: Clip,\n resource: { id: string; type: string },\n instructions: ClipInstructionSet\n ): Promise<void> {\n await this.releasePipeline();\n\n if (resource.type === 'video') {\n await this.setupVideoPipeline(clip, resource);\n } else if (resource.type === 'image') {\n await this.setupImagePipeline(clip);\n }\n\n await this.installInstructions(instructions);\n }\n\n private async releasePipeline(): Promise<void> {\n if (this.visualWorker && this.instructionContext) {\n await this.visualWorker.notify('dispose_clip', {\n sessionId: this.sessionId,\n revision: this.instructionContext.revision,\n });\n }\n\n this.visualToEncodeChannel?.port1.close();\n this.visualToEncodeChannel?.port2.close();\n this.decodeToVisualChannel?.port1.close();\n this.decodeToVisualChannel?.port2.close();\n this.demuxToDecodeChannel?.port1.close();\n this.demuxToDecodeChannel?.port2.close();\n\n this.visualToEncodeChannel = null;\n this.decodeToVisualChannel = null;\n this.demuxToDecodeChannel = null;\n\n if (this.visualStream && this.callbacks.onStreamDisposed) {\n this.callbacks.onStreamDisposed();\n }\n this.visualStream = null;\n\n if (this.videoDemuxWorker) {\n this.workerPool.terminate('videoDemux', this.sessionId);\n this.videoDemuxWorker = null;\n }\n\n if (this.visualWorker) {\n this.workerPool.terminate('videoCompose', this.sessionId);\n this.visualWorker = null;\n }\n\n // Shared workers are not terminated here (decode / encode)\n this.decodeWorker = null;\n this.encodeWorker = null;\n }\n\n async invalidateClipCache(): Promise<void> {\n await this.cacheManager.invalidateClip(this.clipId);\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/orchestrator/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,gBAAgB,EAChB,oBAAoB,EACpB,gBAAgB,EAChB,MAAM,EACN,OAAO,EACR,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEhE;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE;QACZ,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,OAAO,CAAC;KACnB,CAAC;IACF,QAAQ,CAAC,EAAE,QAAQ,CAAC,eAAe,CAAC,CAAC;IACrC,UAAU,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/orchestrator/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,gBAAgB,EAChB,oBAAoB,EACpB,gBAAgB,EAChB,MAAM,EACN,OAAO,EACR,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEhE;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE;QACZ,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,OAAO,CAAC;KACnB,CAAC;IACF,QAAQ,CAAC,EAAE,QAAQ,CAAC,eAAe,CAAC,CAAC;IACrC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,IAAI,GAAG,KAAK,GAAG,MAAM,CAAC,CAAC;IACxE,QAAQ,CAAC,gBAAgB,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACnD,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC;IAEpC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,mBAAmB,CAAC,KAAK,EAAE,gBAAgB,GAAG,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnF,UAAU,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,aAAa,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChE,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IACnF,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,KAAK,IAAI,IAAI,CAAC;IACd,MAAM,IAAI,IAAI,CAAC;IACf,IAAI,IAAI,IAAI,CAAC;IACb,gBAAgB,IAAI,MAAM,CAAC;IAC3B,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC3C,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,GAAG,IAAI,CAAC;CAC7C;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB"}
|
|
@@ -7,11 +7,16 @@ import { EventPayloadMap } from '../../event/events';
|
|
|
7
7
|
import { CacheManager } from '../../cache/CacheManager';
|
|
8
8
|
|
|
9
9
|
interface AudioDataMessage {
|
|
10
|
-
|
|
10
|
+
sessionId: string;
|
|
11
11
|
audioData: AudioData;
|
|
12
12
|
clipStartUs: TimeUs;
|
|
13
13
|
clipDurationUs: TimeUs;
|
|
14
14
|
}
|
|
15
|
+
export interface AudioPlaybackInfo {
|
|
16
|
+
buffer: AudioBuffer;
|
|
17
|
+
offsetSeconds: number;
|
|
18
|
+
durationSeconds: number;
|
|
19
|
+
}
|
|
15
20
|
interface AudioSessionDeps {
|
|
16
21
|
cacheManager: CacheManager;
|
|
17
22
|
workers: WorkerPool;
|
|
@@ -28,9 +33,37 @@ export declare class GlobalAudioSession {
|
|
|
28
33
|
constructor(deps: AudioSessionDeps);
|
|
29
34
|
onAudioData(message: AudioDataMessage): void;
|
|
30
35
|
ensureMixedPCM(startUs: TimeUs): Promise<AudioBuffer | null>;
|
|
36
|
+
prepareAudioForPlayback(startUs: TimeUs): Promise<AudioPlaybackInfo | null>;
|
|
31
37
|
activateAllAudioClips(): Promise<void>;
|
|
32
38
|
handleAudioStream(stream: ReadableStream<AudioData>, metadata: Record<string, any>): void;
|
|
33
39
|
reset(): void;
|
|
40
|
+
/**
|
|
41
|
+
* Create export encoded audio stream with metadata callback
|
|
42
|
+
* Mixes all audio clips and encodes to EncodedAudioChunk for export
|
|
43
|
+
* Extracts metadata from first chunk and invokes callback
|
|
44
|
+
*/
|
|
45
|
+
createExportEncodedStream(config?: Partial<AudioEncoderConfig>, onFirstMetadata?: (metadata: EncodedAudioChunkMetadata) => void): Promise<ReadableStream<EncodedAudioChunk> | null>;
|
|
46
|
+
/**
|
|
47
|
+
* Create export audio stream
|
|
48
|
+
* Mixes all audio clips for the entire composition and outputs AudioData stream
|
|
49
|
+
*/
|
|
50
|
+
createExportAudioStream(): Promise<ReadableStream<AudioData> | null>;
|
|
51
|
+
/**
|
|
52
|
+
* Wait for audio clips to be decoded and cached
|
|
53
|
+
*/
|
|
54
|
+
private waitForAudioClipsReady;
|
|
55
|
+
/**
|
|
56
|
+
* Wait for clip PCM data to be available
|
|
57
|
+
*/
|
|
58
|
+
private waitForClipPCM;
|
|
59
|
+
/**
|
|
60
|
+
* Convert AudioBuffer to AudioData for encoding
|
|
61
|
+
*/
|
|
62
|
+
private audioBufferToAudioData;
|
|
63
|
+
/**
|
|
64
|
+
* Interleave planar audio data for AudioData constructor
|
|
65
|
+
*/
|
|
66
|
+
private interleavePlanarData;
|
|
34
67
|
private setupAudioPipeline;
|
|
35
68
|
private alignToWindow;
|
|
36
69
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GlobalAudioSession.d.ts","sourceRoot":"","sources":["../../../src/stages/compose/GlobalAudioSession.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAEhD,OAAO,KAAK,EAAE,gBAAgB,EAAQ,MAAM,aAAa,CAAC;AAC1D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAE1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"GlobalAudioSession.d.ts","sourceRoot":"","sources":["../../../src/stages/compose/GlobalAudioSession.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAEhD,OAAO,KAAK,EAAE,gBAAgB,EAAQ,MAAM,aAAa,CAAC;AAC1D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAE1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAG7D,UAAU,gBAAgB;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,SAAS,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,WAAW,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,UAAU,gBAAgB;IACxB,YAAY,EAAE,YAAY,CAAC;IAC3B,OAAO,EAAE,UAAU,CAAC;IACpB,cAAc,EAAE,cAAc,CAAC;IAC/B,QAAQ,EAAE,QAAQ,CAAC,eAAe,CAAC,CAAC;IACpC,QAAQ,EAAE,MAAM,gBAAgB,GAAG,IAAI,CAAC;IACxC,kBAAkB,EAAE,MAAM,GAAG,CAAC;CAC/B;AAED,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,KAAK,CAAoB;IACjC,OAAO,CAAC,WAAW,CAAqB;IACxC,OAAO,CAAC,IAAI,CAAmB;gBAEnB,IAAI,EAAE,gBAAgB;IAKlC,WAAW,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI;IAKtC,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAwB5D,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAkB3E,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC;IA0B5C,iBAAiB,CAAC,MAAM,EAAE,cAAc,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IA+BzF,KAAK,IAAI,IAAI;IAKb;;;;OAIG;IACG,yBAAyB,CAC7B,MAAM,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,EACpC,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,yBAAyB,KAAK,IAAI,GAC9D,OAAO,CAAC,cAAc,CAAC,iBAAiB,CAAC,GAAG,IAAI,CAAC;IA6BpD;;;OAGG;IACG,uBAAuB,IAAI,OAAO,CAAC,cAAc,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;IAuC1E;;OAEG;YACW,sBAAsB;IAgBpC;;OAEG;IACH,OAAO,CAAC,cAAc;IAwBtB;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAqB9B;;OAEG;IACH,OAAO,CAAC,oBAAoB;YAgBd,kBAAkB;IAiChC,OAAO,CAAC,aAAa;CAGtB"}
|