@meframe/core 0.0.4 → 0.0.6
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 +106 -86
- package/dist/Meframe.js.map +1 -1
- package/dist/cache/CacheManager.d.ts +27 -10
- package/dist/cache/CacheManager.d.ts.map +1 -1
- package/dist/cache/CacheManager.js +92 -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 +242 -44
- package/dist/cache/L2Cache.js.map +1 -1
- package/dist/cache/l1/VideoL1Cache.d.ts +1 -1
- package/dist/cache/l1/VideoL1Cache.js.map +1 -1
- package/dist/controllers/PreRenderService.d.ts +31 -4
- package/dist/controllers/PreRenderService.d.ts.map +1 -1
- package/dist/controllers/PreRenderService.js +130 -10
- package/dist/controllers/PreRenderService.js.map +1 -1
- package/dist/event/events.d.ts +12 -3
- package/dist/event/events.d.ts.map +1 -1
- package/dist/event/events.js +1 -0
- package/dist/event/events.js.map +1 -1
- package/dist/model/CompositionModel.d.ts +1 -1
- package/dist/model/CompositionModel.js +1 -1
- package/dist/model/CompositionModel.js.map +1 -1
- package/dist/model/patch.d.ts +1 -1
- package/dist/model/patch.js.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 +1 -1
- package/dist/orchestrator/CompositionPlanner.js +1 -1
- package/dist/orchestrator/CompositionPlanner.js.map +1 -1
- package/dist/orchestrator/Orchestrator.d.ts +10 -1
- package/dist/orchestrator/Orchestrator.d.ts.map +1 -1
- package/dist/orchestrator/Orchestrator.js +83 -38
- package/dist/orchestrator/Orchestrator.js.map +1 -1
- package/dist/orchestrator/VideoClipSession.d.ts +11 -4
- package/dist/orchestrator/VideoClipSession.d.ts.map +1 -1
- package/dist/orchestrator/VideoClipSession.js +70 -28
- package/dist/orchestrator/VideoClipSession.js.map +1 -1
- package/dist/stages/compose/GlobalAudioSession.d.ts +28 -1
- package/dist/stages/compose/GlobalAudioSession.d.ts.map +1 -1
- package/dist/stages/compose/GlobalAudioSession.js +133 -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.map +1 -1
- package/dist/stages/load/ResourceLoader.js +17 -12
- 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 +2 -2
- package/dist/stages/load/TaskManager.js.map +1 -1
- package/dist/stages/load/types.d.ts +2 -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.map +1 -1
- package/dist/worker/WorkerPool.js +2 -4
- 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 +25 -14
- package/dist/workers/stages/compose/video-compose.worker.js.map +1 -1
- package/dist/workers/stages/decode/decode.worker.js +37 -28
- 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 +192 -196
- package/dist/workers/stages/encode/encode.worker.js.map +1 -1
- package/package.json +2 -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
|
@@ -9,6 +9,7 @@ import { CompositionPlanner } from "./CompositionPlanner.js";
|
|
|
9
9
|
import { VideoClipSession } from "./VideoClipSession.js";
|
|
10
10
|
import { ClipSessionManager } from "./ClipSessionManager.js";
|
|
11
11
|
import { GlobalAudioSession } from "../stages/compose/GlobalAudioSession.js";
|
|
12
|
+
import { MuxManager } from "../stages/mux/MuxManager.js";
|
|
12
13
|
class Orchestrator {
|
|
13
14
|
workers;
|
|
14
15
|
eventBus;
|
|
@@ -17,6 +18,7 @@ class Orchestrator {
|
|
|
17
18
|
cacheManager;
|
|
18
19
|
planner;
|
|
19
20
|
audioSession;
|
|
21
|
+
muxManager;
|
|
20
22
|
activeClips = /* @__PURE__ */ new Set();
|
|
21
23
|
isInitialized = false;
|
|
22
24
|
config = ConfigLoader.getInstance().getConfig();
|
|
@@ -73,6 +75,11 @@ class Orchestrator {
|
|
|
73
75
|
getModel: () => this.compositionModel,
|
|
74
76
|
buildWorkerConfigs: () => this.buildWorkerConfigs()
|
|
75
77
|
});
|
|
78
|
+
this.muxManager = new MuxManager(
|
|
79
|
+
this.cacheManager,
|
|
80
|
+
this.audioSession,
|
|
81
|
+
this.config.encode.audio
|
|
82
|
+
);
|
|
76
83
|
}
|
|
77
84
|
get workerStatus() {
|
|
78
85
|
const status = this.workers.status;
|
|
@@ -83,8 +90,7 @@ class Orchestrator {
|
|
|
83
90
|
"decode",
|
|
84
91
|
"videoCompose",
|
|
85
92
|
"audioCompose",
|
|
86
|
-
"encode"
|
|
87
|
-
"mux"
|
|
93
|
+
"encode"
|
|
88
94
|
];
|
|
89
95
|
for (const type of workerTypes) {
|
|
90
96
|
result[type] = status[type] || {
|
|
@@ -113,7 +119,6 @@ class Orchestrator {
|
|
|
113
119
|
async setCompositionModel(model) {
|
|
114
120
|
this.compositionModel = model;
|
|
115
121
|
this.planner.setModel(model);
|
|
116
|
-
this.cacheManager.configure(model);
|
|
117
122
|
this.currentClipId = null;
|
|
118
123
|
this.eventBus.emit(MeframeEvent.ModelSet, model);
|
|
119
124
|
this.eventBus.emit(MeframeEvent.CompositionUpdated, {
|
|
@@ -201,7 +206,7 @@ class Orchestrator {
|
|
|
201
206
|
if (session) {
|
|
202
207
|
await session.activate();
|
|
203
208
|
}
|
|
204
|
-
} else if (type === "decode" || type === "audioCompose" || type === "encode"
|
|
209
|
+
} else if (type === "decode" || type === "audioCompose" || type === "encode") {
|
|
205
210
|
await this.setupSharedConnections();
|
|
206
211
|
}
|
|
207
212
|
}
|
|
@@ -239,7 +244,7 @@ class Orchestrator {
|
|
|
239
244
|
return null;
|
|
240
245
|
}
|
|
241
246
|
/**
|
|
242
|
-
* Ensure clips are cached using
|
|
247
|
+
* Ensure clips are cached using 2-Clip strategy
|
|
243
248
|
* Called by PlaybackController
|
|
244
249
|
*/
|
|
245
250
|
async ensureClipCache(timeUs) {
|
|
@@ -269,44 +274,97 @@ class Orchestrator {
|
|
|
269
274
|
timeoutMs: options?.timeoutMs ?? 5e3
|
|
270
275
|
});
|
|
271
276
|
}
|
|
277
|
+
/**
|
|
278
|
+
* Render a clip completely for L2 cache (bypass ClipSessionManager)
|
|
279
|
+
* Returns a promise that resolves when encoding is complete
|
|
280
|
+
*/
|
|
281
|
+
async renderClipForL2(clipId) {
|
|
282
|
+
const sessionId = `${clipId}#l2`;
|
|
283
|
+
return new Promise((resolve, reject) => {
|
|
284
|
+
this.createSession(sessionId, {
|
|
285
|
+
forL2Only: true,
|
|
286
|
+
clipId,
|
|
287
|
+
onL2Complete: () => {
|
|
288
|
+
resolve();
|
|
289
|
+
},
|
|
290
|
+
onL2Error: (error) => {
|
|
291
|
+
console.error("[Orchestrator] L2 rendering failed for", clipId, error);
|
|
292
|
+
reject(error);
|
|
293
|
+
}
|
|
294
|
+
}).then((session) => session.activate()).catch((error) => {
|
|
295
|
+
console.error(`[Orchestrator] renderClipForL2 error for ${clipId}:`, error);
|
|
296
|
+
reject(error);
|
|
297
|
+
});
|
|
298
|
+
});
|
|
299
|
+
}
|
|
272
300
|
/**
|
|
273
301
|
* Create a new session for a clip
|
|
274
302
|
*/
|
|
275
|
-
async createSession(
|
|
303
|
+
async createSession(sessionId, options) {
|
|
304
|
+
const clipId = options?.clipId ?? sessionId;
|
|
276
305
|
const clip = this.compositionModel?.findClip(clipId);
|
|
277
306
|
if (!clip) {
|
|
278
307
|
throw new Error(`Clip ${clipId} not found`);
|
|
279
308
|
}
|
|
280
309
|
const session = await VideoClipSession.create({
|
|
281
310
|
clipId,
|
|
311
|
+
sessionId,
|
|
282
312
|
planner: this.planner,
|
|
283
313
|
workerPool: this.workers,
|
|
284
314
|
cacheManager: this.cacheManager,
|
|
285
315
|
compositionModel: this.compositionModel,
|
|
286
316
|
workerConfigs: this.buildWorkerConfigs(),
|
|
287
317
|
callbacks: {
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
318
|
+
onComposedStreamReady: (stream, fps) => {
|
|
319
|
+
if (options?.forL2Only) {
|
|
320
|
+
stream.cancel();
|
|
321
|
+
} else {
|
|
322
|
+
this.cacheManager.receiveComposedFrames(stream, {
|
|
323
|
+
clipId,
|
|
324
|
+
trackId: this.compositionModel.mainTrackId,
|
|
325
|
+
fps,
|
|
326
|
+
onFrame: () => {
|
|
327
|
+
}
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
},
|
|
331
|
+
onEncodedStreamReady: (stream, track) => {
|
|
332
|
+
if (options?.forL2Only) {
|
|
333
|
+
this.cacheManager.receiveEncodedChunks(stream, clipId, track, {
|
|
334
|
+
onComplete: () => {
|
|
335
|
+
session.dispose();
|
|
336
|
+
if (track === "video" && options.onL2Complete) {
|
|
337
|
+
options.onL2Complete();
|
|
338
|
+
}
|
|
339
|
+
},
|
|
340
|
+
onError: (error) => {
|
|
341
|
+
console.error(
|
|
342
|
+
`[Orchestrator] L2 encode stream error for ${clipId} ${track}:`,
|
|
343
|
+
error
|
|
344
|
+
);
|
|
345
|
+
session.dispose();
|
|
346
|
+
if (options.onL2Error) {
|
|
347
|
+
options.onL2Error(error);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
});
|
|
351
|
+
} else {
|
|
352
|
+
stream.cancel();
|
|
353
|
+
}
|
|
296
354
|
},
|
|
297
|
-
onPipelineReady: async (
|
|
298
|
-
const clip2 = this.compositionModel?.findClip(
|
|
355
|
+
onPipelineReady: async () => {
|
|
356
|
+
const clip2 = this.compositionModel?.findClip(clipId);
|
|
299
357
|
if (clip2?.resourceId) {
|
|
300
358
|
await this.resourceLoader.fetch(clip2.resourceId, {
|
|
301
|
-
priority: "high",
|
|
302
|
-
|
|
359
|
+
priority: options?.forL2Only ? "low" : "high",
|
|
360
|
+
sessionId,
|
|
303
361
|
trackId: clip2.trackId
|
|
304
362
|
});
|
|
305
363
|
}
|
|
306
364
|
}
|
|
307
365
|
}
|
|
308
366
|
});
|
|
309
|
-
this.activeClips.add(
|
|
367
|
+
this.activeClips.add(sessionId);
|
|
310
368
|
return session;
|
|
311
369
|
}
|
|
312
370
|
async dispose() {
|
|
@@ -321,8 +379,8 @@ class Orchestrator {
|
|
|
321
379
|
}
|
|
322
380
|
buildWorkerConfigs() {
|
|
323
381
|
const config = this.config;
|
|
324
|
-
const defaultCanvasWidth = config.global?.defaultCanvasWidth ??
|
|
325
|
-
const defaultCanvasHeight = config.global?.defaultCanvasHeight ??
|
|
382
|
+
const defaultCanvasWidth = config.global?.defaultCanvasWidth ?? 720;
|
|
383
|
+
const defaultCanvasHeight = config.global?.defaultCanvasHeight ?? 1280;
|
|
326
384
|
const defaultFps = config.global?.defaultFps ?? 30;
|
|
327
385
|
return {
|
|
328
386
|
videoDemux: {
|
|
@@ -356,7 +414,7 @@ class Orchestrator {
|
|
|
356
414
|
framerate: config.encode?.video?.framerate || defaultFps,
|
|
357
415
|
latencyMode: "quality",
|
|
358
416
|
bitrateMode: "variable",
|
|
359
|
-
hardwareAcceleration: "
|
|
417
|
+
hardwareAcceleration: "no-preference",
|
|
360
418
|
...config.encode?.video
|
|
361
419
|
},
|
|
362
420
|
audio: {
|
|
@@ -366,9 +424,6 @@ class Orchestrator {
|
|
|
366
424
|
bitrate: config.encode?.audio?.bitrateKbps ? config.encode.audio.bitrateKbps * 1e3 : 128e3,
|
|
367
425
|
...config.encode?.audio
|
|
368
426
|
}
|
|
369
|
-
},
|
|
370
|
-
mux: {
|
|
371
|
-
container: config.export?.container || "mp4"
|
|
372
427
|
}
|
|
373
428
|
};
|
|
374
429
|
}
|
|
@@ -379,19 +434,9 @@ class Orchestrator {
|
|
|
379
434
|
this.audioSession.handleAudioStream(stream, metadata);
|
|
380
435
|
}
|
|
381
436
|
});
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
await encodeWorker.send(
|
|
386
|
-
"connect",
|
|
387
|
-
{ direction: "downstream", port: videoChannel.port1, streamType: "video" },
|
|
388
|
-
{ transfer: [videoChannel.port1] }
|
|
389
|
-
);
|
|
390
|
-
await muxWorker.send(
|
|
391
|
-
"connect",
|
|
392
|
-
{ direction: "upstream", port: videoChannel.port2, streamType: "video" },
|
|
393
|
-
{ transfer: [videoChannel.port2] }
|
|
394
|
-
);
|
|
437
|
+
}
|
|
438
|
+
async export(model, options) {
|
|
439
|
+
return this.muxManager.export(model, options);
|
|
395
440
|
}
|
|
396
441
|
}
|
|
397
442
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Orchestrator.js","sources":["../../src/orchestrator/Orchestrator.ts"],"sourcesContent":["import { EventBus } from '../event/EventBus';\nimport { WorkerPool } from '../worker/WorkerPool';\nimport { applyPatch as applyModelPatch } from '../model/patch';\nimport { ResourceLoader } from '../stages/load/ResourceLoader';\nimport { CacheManager } from '../cache/CacheManager';\nimport { ConfigLoader } from '../config/ConfigLoader';\nimport type { IOrchestrator, OrchestratorConfig, RenderFrameOptions } from './types';\nimport { WorkerStatus, WorkerType } from '../worker/types';\nimport { CompositionModel, CompositionPatch, Resource, TimeUs, RcFrame } from '../model';\nimport { MeframeEvent, type EventPayloadMap } from '../event/events';\nimport { CompositionPlanner } from './CompositionPlanner';\nimport { VideoClipSession } from './VideoClipSession';\nimport { ClipSessionManager } from './ClipSessionManager';\nimport { GlobalAudioSession } from '../stages/compose/GlobalAudioSession';\n\nexport class Orchestrator implements IOrchestrator {\n workers: WorkerPool;\n eventBus: EventBus<EventPayloadMap>;\n compositionModel: CompositionModel | null = null;\n resourceLoader: ResourceLoader;\n cacheManager: CacheManager;\n planner: CompositionPlanner;\n audioSession: GlobalAudioSession;\n\n private activeClips = new Set<string>();\n private isInitialized = false;\n private config = ConfigLoader.getInstance().getConfig();\n private clipSessionManager: ClipSessionManager;\n private currentClipId: string | null = null;\n readonly events: Pick<EventBus<EventPayloadMap>, 'on' | 'off' | 'once'>;\n\n constructor(config: OrchestratorConfig) {\n // Use provided eventBus or create a new one\n this.eventBus = config.eventBus || new EventBus<EventPayloadMap>();\n this.events = this.eventBus.asReadonly();\n\n // Initialize config first\n this.config = ConfigLoader.getInstance().getConfig();\n\n const workerConfigs = this.buildWorkerConfigs();\n\n // Initialize WorkerPool with worker path from config\n this.workers = new WorkerPool({\n eventBus: this.eventBus,\n workerConfigs,\n workerPath: config.workerPath,\n workerExtension: config.workerExtension,\n });\n\n this.resourceLoader = new ResourceLoader({\n orchestrator: this as any,\n eventBus: this.eventBus,\n config: {\n maxConcurrent: config.maxWorkers || (this.config.load as any)?.retry?.maxAttempts || 4,\n },\n onStateChange: (resourceId, state) => this.handleResourceStateChange(resourceId, state),\n });\n\n this.planner = new CompositionPlanner();\n\n const cacheConfig = config.cacheConfig || this.config.cache;\n this.cacheManager = new CacheManager(\n {\n l1: {\n maxMemoryMB:\n (cacheConfig as any)?.l1Size || (cacheConfig as any)?.l1?.maxMemoryMB || 1024,\n maxGOPs: (this.config.decode as any)?.video?.maxGOPs || 4,\n },\n l2: {\n maxSizeMB: (cacheConfig as any)?.l2Size || (cacheConfig as any)?.l2?.maxSizeMB || 2048,\n projectId: 'default',\n },\n },\n this.eventBus\n );\n\n this.clipSessionManager = new ClipSessionManager({\n maxConcurrent: 2,\n factory: {\n createSession: (clipId) => this.createSession(clipId),\n },\n model: () => this.compositionModel,\n cacheManager: this.cacheManager,\n });\n\n this.audioSession = new GlobalAudioSession({\n cacheManager: this.cacheManager,\n workers: this.workers,\n resourceLoader: this.resourceLoader,\n eventBus: this.eventBus,\n getModel: () => this.compositionModel,\n buildWorkerConfigs: () => this.buildWorkerConfigs(),\n });\n }\n\n get workerStatus(): WorkerStatus {\n const status = this.workers.status;\n const result: WorkerStatus = {} as WorkerStatus;\n\n const workerTypes: WorkerType[] = [\n 'videoDemux',\n 'audioDemux',\n 'decode',\n 'videoCompose',\n 'audioCompose',\n 'encode',\n 'mux',\n ];\n\n for (const type of workerTypes) {\n result[type] = status[type] || {\n state: 'idle',\n taskCount: 0,\n };\n }\n\n return result;\n }\n\n async initialize(): Promise<void> {\n if (this.isInitialized) return;\n\n await this.cacheManager.init();\n // Use unified stream pipeline wiring\n await this.setupSharedConnections();\n\n this.isInitialized = true;\n }\n\n // Event methods - forward to eventBus\n on<K extends keyof EventPayloadMap>(\n event: K,\n handler: (payload: EventPayloadMap[K]) => void\n ): void {\n this.eventBus.on(event, handler);\n }\n\n off<K extends keyof EventPayloadMap>(\n event: K,\n handler: (payload: EventPayloadMap[K]) => void\n ): void {\n this.eventBus.off(event, handler);\n }\n\n once<K extends keyof EventPayloadMap>(\n event: K,\n handler: (payload: EventPayloadMap[K]) => void\n ): void {\n this.eventBus.once(event, handler);\n }\n\n async setCompositionModel(model: CompositionModel): Promise<void> {\n this.compositionModel = model;\n this.planner.setModel(model);\n this.cacheManager.configure(model);\n this.currentClipId = null;\n\n this.eventBus.emit(MeframeEvent.ModelSet, model);\n\n this.eventBus.emit(MeframeEvent.CompositionUpdated, {\n trackCount: model.tracks.length,\n clipCount: model.tracks.reduce((acc: number, track: any) => acc + track.clips.length, 0),\n durationUs: model.durationUs,\n });\n\n await this.audioSession.activateAllAudioClips();\n\n this.ensureClipCache(0);\n }\n\n async applyPatch(patch: CompositionPatch): Promise<void> {\n if (!this.compositionModel) {\n throw new Error('No composition model set');\n }\n\n // Apply patch and get affected clip IDs (simplified for 3-Clip strategy)\n const affectedClipIds = applyModelPatch(this.compositionModel, patch);\n const clipUpdates = this.planner.applyPatch(patch, affectedClipIds);\n\n this.eventBus.emit(MeframeEvent.PatchApplied, {\n operations: patch.operations.length,\n affectedClips: Array.from(affectedClipIds),\n });\n\n // Get currently active clips in the 3-Clip window\n const activeClipIds = new Set(\n Array.from(this.clipSessionManager['entries'].keys()).filter((clipId) =>\n this.clipSessionManager.isClipActive(clipId)\n )\n );\n\n // Process clip updates\n for (const update of clipUpdates) {\n if (update.type === 'remove') {\n this.activeClips.delete(update.clipId);\n this.cacheManager.evictClip(update.clipId);\n }\n\n // Notify ClipSessionManager to handle the update\n // This will install new instructions or restart pipeline as needed\n await this.clipSessionManager.handlePlannerUpdate(update.clipId, update);\n\n // Only evict cache for active clips (in current 3-Clip window)\n // Non-active clips will be regenerated when they enter the window\n if (activeClipIds.has(update.clipId) && update.type !== 'remove') {\n this.cacheManager.evictClip(update.clipId);\n }\n }\n }\n\n private handleResourceStateChange(resourceId: string, state: Resource['state']): void {\n if (!this.compositionModel) {\n return;\n }\n\n this.compositionModel.updateResourceState(resourceId, state ?? 'pending');\n\n if (state !== 'ready') {\n return;\n }\n\n const resource = this.compositionModel.getResource(resourceId);\n if (!resource) {\n return;\n }\n\n // Main video/audio resources: data will flow naturally into pipeline\n if (resource.type === 'video' || resource.type === 'audio') {\n return;\n }\n\n // Attachment resources (fonts, images): update instructions for active clips\n const clipIds = this.compositionModel.getClipIdsByResourceId(resourceId);\n for (const clipId of clipIds) {\n // Only update active clips (in 3-Clip window)\n if (!this.clipSessionManager.isClipActive(clipId)) {\n continue;\n }\n\n const clip = this.compositionModel.findClip(clipId);\n if (!clip) {\n continue;\n }\n\n // Rebuild instructions with updated resource status\n const instructions = this.planner.getInstructions(clipId);\n if (!instructions) {\n continue;\n }\n\n // Send updated instructions to worker (no pipeline restart needed)\n const session = this.clipSessionManager.getSession(clipId);\n const visualWorker = session?.visualWorkerHandle;\n if (visualWorker) {\n visualWorker.send('install_instructions', instructions);\n }\n }\n }\n\n async restartWorker(type: WorkerType, clipId?: string): Promise<void> {\n if ((type === 'videoDemux' || type === 'audioDemux' || type === 'videoCompose') && !clipId) {\n throw new Error(`clipId required for restarting ${type} worker`);\n }\n\n this.workers.terminate(type, clipId);\n const worker = await this.workers.get(type, clipId);\n\n this.eventBus.emit(MeframeEvent.WorkerRestarted, {\n type,\n workerId: worker.getWorkerId(),\n reason: 'Manual restart',\n });\n\n if (clipId) {\n const session = this.clipSessionManager.getSession(clipId);\n if (session) {\n await session.activate();\n }\n } else if (\n type === 'decode' ||\n type === 'audioCompose' ||\n type === 'encode' ||\n type === 'mux'\n ) {\n await this.setupSharedConnections();\n }\n }\n\n async renderFrame(timeUs: TimeUs, options?: RenderFrameOptions): Promise<RcFrame | null> {\n const signal = options?.signal;\n\n if (!this.compositionModel) {\n throw new Error('No composition model set');\n }\n\n const clip = this.compositionModel.getClipsAtTime(timeUs, this.compositionModel.mainTrackId)[0];\n if (!clip) {\n return null;\n }\n\n // Detect clip change and proactively ensure cache for prev/current/next\n if (this.currentClipId !== clip.id) {\n this.currentClipId = clip.id;\n void this.ensureClipCache(timeUs);\n }\n\n const cachedFrame = await this.cacheManager.getFrame(timeUs, clip.id);\n // console.log('>>>>>>>>>>>> renderFrame', timeUs, clip.id, cachedFrame);\n if (cachedFrame) {\n this.eventBus.emit(MeframeEvent.CacheHit, {\n timeUs,\n level: 'L1',\n key: `${clip.id}-${timeUs}`,\n });\n return cachedFrame;\n }\n // Cache miss - also ensure cache (defensive, already called on clip change)\n void this.ensureClipCache(timeUs);\n\n this.eventBus.emit(MeframeEvent.CacheMiss, {\n timeUs,\n level: 'L1',\n key: `${clip.id}-${timeUs}`,\n });\n\n if (signal?.aborted) {\n throw new DOMException('Render aborted', 'AbortError');\n }\n\n // Return null immediately instead of waiting\n // This allows PlaybackController to detect miss and trigger buffering\n return null;\n }\n\n /**\n * Ensure clips are cached using 3-Clip strategy\n * Called by PlaybackController\n */\n async ensureClipCache(timeUs: TimeUs): Promise<void> {\n if (!this.compositionModel) {\n return;\n }\n\n await this.clipSessionManager.ensureClips(timeUs);\n }\n\n /**\n * Wait for clip cache to be ready for playback\n * Returns true if minimum cache is ready, false if timeout\n */\n async waitForClipReady(\n timeUs: TimeUs,\n options?: { minFrameCount?: number; timeoutMs?: number }\n ): Promise<boolean> {\n if (!this.compositionModel) {\n return false;\n }\n\n const clips = this.compositionModel.getClipsAtTime(timeUs, this.compositionModel.mainTrackId);\n if (clips.length === 0) {\n return true;\n }\n\n const currentClip = clips[0];\n if (!currentClip) {\n return true;\n }\n\n return this.cacheManager.waitForClipReady(currentClip.id, {\n minFrameCount: options?.minFrameCount ?? 30,\n timeoutMs: options?.timeoutMs ?? 5_000,\n });\n }\n\n /**\n * Create a new session for a clip\n */\n private async createSession(clipId: string): Promise<VideoClipSession> {\n const clip = this.compositionModel?.findClip(clipId);\n if (!clip) {\n throw new Error(`Clip ${clipId} not found`);\n }\n\n const session = await VideoClipSession.create({\n clipId,\n planner: this.planner,\n workerPool: this.workers,\n cacheManager: this.cacheManager,\n compositionModel: this.compositionModel!,\n workerConfigs: this.buildWorkerConfigs(),\n callbacks: {\n onStreamReady: (id, stream, fps) => {\n this.cacheManager.receiveComposedFrames(stream, {\n clipId: id,\n trackId: this.compositionModel!.mainTrackId,\n fps,\n onFrame: () => {\n // Frame arrived\n },\n });\n },\n onPipelineReady: async (clipId) => {\n // Pipeline is connected, now trigger resource loading\n const clip = this.compositionModel?.findClip(clipId);\n if (clip?.resourceId) {\n await this.resourceLoader.fetch(clip.resourceId, {\n priority: 'high',\n clipId,\n trackId: clip.trackId,\n });\n }\n },\n },\n });\n\n this.activeClips.add(clipId);\n return session;\n }\n\n async dispose(): Promise<void> {\n this.resourceLoader.dispose();\n await this.clipSessionManager.dispose();\n await this.cacheManager.clear();\n\n this.currentClipId = null;\n this.activeClips.clear();\n\n this.workers.terminateAll();\n this.compositionModel = null;\n this.eventBus.dispose();\n }\n\n private buildWorkerConfigs(): Record<WorkerType, any> {\n const config = this.config as any;\n const defaultCanvasWidth = config.global?.defaultCanvasWidth ?? 1280;\n const defaultCanvasHeight = config.global?.defaultCanvasHeight ?? 720;\n const defaultFps = config.global?.defaultFps ?? 30;\n return {\n videoDemux: {\n highWaterMark: config.demux?.backpressure?.highWaterMark ?? 10,\n },\n audioDemux: {\n highWaterMark: config.demux?.backpressure?.highWaterMark ?? 10,\n },\n decode: {\n video: config.decode?.video,\n audio: config.decode?.audio,\n },\n videoCompose: {\n width: config.compose?.canvas?.width ?? defaultCanvasWidth,\n height: config.compose?.canvas?.height ?? defaultCanvasHeight,\n fps: config.global?.defaultFps ?? defaultFps,\n backgroundColor: config.compose?.canvas?.backgroundColor ?? '#000000',\n enableSmoothing: config.compose?.visual?.enableSmoothing ?? true,\n enableHardwareAcceleration: config.compose?.visual?.enableHardwareAcceleration ?? true,\n },\n audioCompose: {\n ducking: config.compose?.audio?.ducking,\n mixing: config.compose?.audio?.mixing,\n },\n encode: {\n video: {\n codec: 'avc1.42002A',\n width: config.compose?.canvas?.width || defaultCanvasWidth,\n height: config.compose?.canvas?.height || defaultCanvasHeight,\n bitrate: config.encode?.video?.bitrateKbps\n ? config.encode.video.bitrateKbps * 1000\n : 12_000_000,\n framerate: config.encode?.video?.framerate || defaultFps,\n latencyMode: 'quality',\n bitrateMode: 'variable',\n hardwareAcceleration: 'prefer-hardware',\n ...(config.encode?.video as any),\n },\n audio: {\n codec: 'mp4a.40.2',\n sampleRate: 48000,\n numberOfChannels: 2,\n bitrate: config.encode?.audio?.bitrateKbps\n ? config.encode.audio.bitrateKbps * 1000\n : 128000,\n ...(config.encode?.audio as any),\n },\n },\n mux: {\n container: config.export?.container || 'mp4',\n },\n };\n }\n\n private async setupSharedConnections(): Promise<void> {\n const decodeWorker = await this.workers.get('decode');\n\n decodeWorker.receiveStream((stream, metadata) => {\n if (metadata?.streamType === 'audio') {\n this.audioSession.handleAudioStream(stream as ReadableStream<AudioData>, metadata);\n }\n });\n\n const encodeWorker = await this.workers.get('encode');\n const muxWorker = await this.workers.get('mux');\n const videoChannel = new MessageChannel();\n await encodeWorker.send(\n 'connect',\n { direction: 'downstream', port: videoChannel.port1, streamType: 'video' },\n { transfer: [videoChannel.port1] }\n );\n await muxWorker.send(\n 'connect',\n { direction: 'upstream', port: videoChannel.port2, streamType: 'video' },\n { transfer: [videoChannel.port2] }\n );\n }\n}\n"],"names":["applyModelPatch","clipId","clip"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Orchestrator.js","sources":["../../src/orchestrator/Orchestrator.ts"],"sourcesContent":["import { EventBus } from '../event/EventBus';\nimport { WorkerPool } from '../worker/WorkerPool';\nimport { applyPatch as applyModelPatch } from '../model/patch';\nimport { ResourceLoader } from '../stages/load/ResourceLoader';\nimport { CacheManager } from '../cache/CacheManager';\nimport { ConfigLoader } from '../config/ConfigLoader';\nimport type { IOrchestrator, OrchestratorConfig, RenderFrameOptions } from './types';\nimport { WorkerStatus, WorkerType } from '../worker/types';\nimport { CompositionModel, CompositionPatch, Resource, TimeUs, RcFrame } from '../model';\nimport { MeframeEvent, type EventPayloadMap } from '../event/events';\nimport { CompositionPlanner } from './CompositionPlanner';\nimport { VideoClipSession } from './VideoClipSession';\nimport { ClipSessionManager } from './ClipSessionManager';\nimport { GlobalAudioSession } from '../stages/compose/GlobalAudioSession';\nimport { MuxManager } from '../stages/mux/MuxManager';\nimport { ExportOptions } from '@/types';\n\nexport class Orchestrator implements IOrchestrator {\n workers: WorkerPool;\n eventBus: EventBus<EventPayloadMap>;\n compositionModel: CompositionModel | null = null;\n resourceLoader: ResourceLoader;\n cacheManager: CacheManager;\n planner: CompositionPlanner;\n audioSession: GlobalAudioSession;\n muxManager: MuxManager;\n\n private activeClips = new Set<string>();\n private isInitialized = false;\n private config = ConfigLoader.getInstance().getConfig();\n private clipSessionManager: ClipSessionManager;\n private currentClipId: string | null = null;\n readonly events: Pick<EventBus<EventPayloadMap>, 'on' | 'off' | 'once'>;\n\n constructor(config: OrchestratorConfig) {\n // Use provided eventBus or create a new one\n this.eventBus = config.eventBus || new EventBus<EventPayloadMap>();\n this.events = this.eventBus.asReadonly();\n\n // Initialize config first\n this.config = ConfigLoader.getInstance().getConfig();\n\n const workerConfigs = this.buildWorkerConfigs();\n\n // Initialize WorkerPool with worker path from config\n this.workers = new WorkerPool({\n eventBus: this.eventBus,\n workerConfigs,\n workerPath: config.workerPath,\n workerExtension: config.workerExtension,\n });\n\n this.resourceLoader = new ResourceLoader({\n orchestrator: this as any,\n eventBus: this.eventBus,\n config: {\n maxConcurrent: config.maxWorkers || (this.config.load as any)?.retry?.maxAttempts || 4,\n },\n onStateChange: (resourceId, state) => this.handleResourceStateChange(resourceId, state),\n });\n\n this.planner = new CompositionPlanner();\n\n const cacheConfig = config.cacheConfig || this.config.cache;\n this.cacheManager = new CacheManager(\n {\n l1: {\n maxMemoryMB:\n (cacheConfig as any)?.l1Size || (cacheConfig as any)?.l1?.maxMemoryMB || 1024,\n maxGOPs: (this.config.decode as any)?.video?.maxGOPs || 4,\n },\n l2: {\n maxSizeMB: (cacheConfig as any)?.l2Size || (cacheConfig as any)?.l2?.maxSizeMB || 2048,\n projectId: 'default',\n },\n },\n this.eventBus\n );\n\n this.clipSessionManager = new ClipSessionManager({\n maxConcurrent: 2,\n factory: {\n createSession: (clipId) => this.createSession(clipId),\n },\n model: () => this.compositionModel,\n cacheManager: this.cacheManager,\n });\n\n this.audioSession = new GlobalAudioSession({\n cacheManager: this.cacheManager,\n workers: this.workers,\n resourceLoader: this.resourceLoader,\n eventBus: this.eventBus,\n getModel: () => this.compositionModel,\n buildWorkerConfigs: () => this.buildWorkerConfigs(),\n });\n\n this.muxManager = new MuxManager(\n this.cacheManager,\n this.audioSession,\n this.config.encode.audio as AudioEncoderConfig\n );\n }\n\n get workerStatus(): WorkerStatus {\n const status = this.workers.status;\n const result: WorkerStatus = {} as WorkerStatus;\n\n const workerTypes: WorkerType[] = [\n 'videoDemux',\n 'audioDemux',\n 'decode',\n 'videoCompose',\n 'audioCompose',\n 'encode',\n ];\n\n for (const type of workerTypes) {\n result[type] = status[type] || {\n state: 'idle',\n taskCount: 0,\n };\n }\n\n return result;\n }\n\n async initialize(): Promise<void> {\n if (this.isInitialized) return;\n\n await this.cacheManager.init();\n // Use unified stream pipeline wiring\n await this.setupSharedConnections();\n\n this.isInitialized = true;\n }\n\n // Event methods - forward to eventBus\n on<K extends keyof EventPayloadMap>(\n event: K,\n handler: (payload: EventPayloadMap[K]) => void\n ): void {\n this.eventBus.on(event, handler);\n }\n\n off<K extends keyof EventPayloadMap>(\n event: K,\n handler: (payload: EventPayloadMap[K]) => void\n ): void {\n this.eventBus.off(event, handler);\n }\n\n once<K extends keyof EventPayloadMap>(\n event: K,\n handler: (payload: EventPayloadMap[K]) => void\n ): void {\n this.eventBus.once(event, handler);\n }\n\n async setCompositionModel(model: CompositionModel): Promise<void> {\n this.compositionModel = model;\n this.planner.setModel(model);\n this.currentClipId = null;\n\n this.eventBus.emit(MeframeEvent.ModelSet, model);\n\n this.eventBus.emit(MeframeEvent.CompositionUpdated, {\n trackCount: model.tracks.length,\n clipCount: model.tracks.reduce((acc: number, track: any) => acc + track.clips.length, 0),\n durationUs: model.durationUs,\n });\n\n await this.audioSession.activateAllAudioClips();\n\n this.ensureClipCache(0);\n }\n\n async applyPatch(patch: CompositionPatch): Promise<void> {\n if (!this.compositionModel) {\n throw new Error('No composition model set');\n }\n\n // Apply patch and get affected clip IDs (simplified for 2-Clip strategy)\n const affectedClipIds = applyModelPatch(this.compositionModel, patch);\n const clipUpdates = this.planner.applyPatch(patch, affectedClipIds);\n\n this.eventBus.emit(MeframeEvent.PatchApplied, {\n operations: patch.operations.length,\n affectedClips: Array.from(affectedClipIds),\n });\n\n // Get currently active clips in the 2-Clip window\n const activeClipIds = new Set(\n Array.from(this.clipSessionManager['entries'].keys()).filter((clipId) =>\n this.clipSessionManager.isClipActive(clipId)\n )\n );\n\n // Process clip updates\n for (const update of clipUpdates) {\n if (update.type === 'remove') {\n this.activeClips.delete(update.clipId);\n this.cacheManager.evictClip(update.clipId);\n }\n\n // Notify ClipSessionManager to handle the update\n // This will install new instructions or restart pipeline as needed\n await this.clipSessionManager.handlePlannerUpdate(update.clipId, update);\n\n // Only evict cache for active clips (in current 2-Clip window)\n // Non-active clips will be regenerated when they enter the window\n if (activeClipIds.has(update.clipId) && update.type !== 'remove') {\n this.cacheManager.evictClip(update.clipId);\n }\n }\n }\n\n private handleResourceStateChange(resourceId: string, state: Resource['state']): void {\n if (!this.compositionModel) {\n return;\n }\n\n this.compositionModel.updateResourceState(resourceId, state ?? 'pending');\n\n if (state !== 'ready') {\n return;\n }\n\n const resource = this.compositionModel.getResource(resourceId);\n if (!resource) {\n return;\n }\n\n // Main video/audio resources: data will flow naturally into pipeline\n if (resource.type === 'video' || resource.type === 'audio') {\n return;\n }\n\n // Attachment resources (fonts, images): update instructions for active clips\n const clipIds = this.compositionModel.getClipIdsByResourceId(resourceId);\n for (const clipId of clipIds) {\n // Only update active clips (in 2-Clip window)\n if (!this.clipSessionManager.isClipActive(clipId)) {\n continue;\n }\n\n const clip = this.compositionModel.findClip(clipId);\n if (!clip) {\n continue;\n }\n\n // Rebuild instructions with updated resource status\n const instructions = this.planner.getInstructions(clipId);\n if (!instructions) {\n continue;\n }\n\n // Send updated instructions to worker (no pipeline restart needed)\n const session = this.clipSessionManager.getSession(clipId);\n const visualWorker = session?.visualWorkerHandle;\n if (visualWorker) {\n visualWorker.send('install_instructions', instructions);\n }\n }\n }\n\n async restartWorker(type: WorkerType, clipId?: string): Promise<void> {\n if ((type === 'videoDemux' || type === 'audioDemux' || type === 'videoCompose') && !clipId) {\n throw new Error(`clipId required for restarting ${type} worker`);\n }\n\n this.workers.terminate(type, clipId);\n const worker = await this.workers.get(type, clipId);\n\n this.eventBus.emit(MeframeEvent.WorkerRestarted, {\n type,\n workerId: worker.getWorkerId(),\n reason: 'Manual restart',\n });\n\n if (clipId) {\n const session = this.clipSessionManager.getSession(clipId);\n if (session) {\n await session.activate();\n }\n } else if (type === 'decode' || type === 'audioCompose' || type === 'encode') {\n await this.setupSharedConnections();\n }\n }\n\n async renderFrame(timeUs: TimeUs, options?: RenderFrameOptions): Promise<RcFrame | null> {\n const signal = options?.signal;\n\n if (!this.compositionModel) {\n throw new Error('No composition model set');\n }\n\n const clip = this.compositionModel.getClipsAtTime(timeUs, this.compositionModel.mainTrackId)[0];\n if (!clip) {\n return null;\n }\n\n // Detect clip change and proactively ensure cache for prev/current/next\n if (this.currentClipId !== clip.id) {\n this.currentClipId = clip.id;\n void this.ensureClipCache(timeUs);\n }\n\n const cachedFrame = await this.cacheManager.getFrame(timeUs, clip.id);\n // console.log('>>>>>>>>>>>> renderFrame', timeUs, clip.id, cachedFrame);\n if (cachedFrame) {\n this.eventBus.emit(MeframeEvent.CacheHit, {\n timeUs,\n level: 'L1',\n key: `${clip.id}-${timeUs}`,\n });\n return cachedFrame;\n }\n // Cache miss - also ensure cache (defensive, already called on clip change)\n void this.ensureClipCache(timeUs);\n\n this.eventBus.emit(MeframeEvent.CacheMiss, {\n timeUs,\n level: 'L1',\n key: `${clip.id}-${timeUs}`,\n });\n\n if (signal?.aborted) {\n throw new DOMException('Render aborted', 'AbortError');\n }\n\n // Return null immediately instead of waiting\n // This allows PlaybackController to detect miss and trigger buffering\n return null;\n }\n\n /**\n * Ensure clips are cached using 2-Clip strategy\n * Called by PlaybackController\n */\n async ensureClipCache(timeUs: TimeUs): Promise<void> {\n if (!this.compositionModel) {\n return;\n }\n\n await this.clipSessionManager.ensureClips(timeUs);\n }\n\n /**\n * Wait for clip cache to be ready for playback\n * Returns true if minimum cache is ready, false if timeout\n */\n async waitForClipReady(\n timeUs: TimeUs,\n options?: { minFrameCount?: number; timeoutMs?: number }\n ): Promise<boolean> {\n if (!this.compositionModel) {\n return false;\n }\n\n const clips = this.compositionModel.getClipsAtTime(timeUs, this.compositionModel.mainTrackId);\n if (clips.length === 0) {\n return true;\n }\n\n const currentClip = clips[0];\n if (!currentClip) {\n return true;\n }\n\n return this.cacheManager.waitForClipReady(currentClip.id, {\n minFrameCount: options?.minFrameCount ?? 30,\n timeoutMs: options?.timeoutMs ?? 5_000,\n });\n }\n\n /**\n * Render a clip completely for L2 cache (bypass ClipSessionManager)\n * Returns a promise that resolves when encoding is complete\n */\n async renderClipForL2(clipId: string): Promise<void> {\n const sessionId = `${clipId}#l2`;\n\n return new Promise<void>((resolve, reject) => {\n this.createSession(sessionId, {\n forL2Only: true,\n clipId: clipId,\n onL2Complete: () => {\n resolve();\n },\n onL2Error: (error) => {\n console.error('[Orchestrator] L2 rendering failed for', clipId, error);\n reject(error);\n },\n })\n .then((session) => session.activate())\n .catch((error) => {\n console.error(`[Orchestrator] renderClipForL2 error for ${clipId}:`, error);\n reject(error);\n });\n });\n }\n\n /**\n * Create a new session for a clip\n */\n private async createSession(\n sessionId: string,\n options?: {\n forL2Only?: boolean;\n clipId?: string;\n onL2Complete?: () => void;\n onL2Error?: (error: Error) => void;\n }\n ): Promise<VideoClipSession> {\n const clipId = options?.clipId ?? sessionId;\n const clip = this.compositionModel?.findClip(clipId);\n if (!clip) {\n throw new Error(`Clip ${clipId} not found`);\n }\n\n const session = await VideoClipSession.create({\n clipId,\n sessionId,\n planner: this.planner,\n workerPool: this.workers,\n cacheManager: this.cacheManager,\n compositionModel: this.compositionModel!,\n workerConfigs: this.buildWorkerConfigs(),\n callbacks: {\n onComposedStreamReady: (stream, fps) => {\n if (options?.forL2Only) {\n // L2 channel: don't need L1, cancel stream\n stream.cancel();\n } else {\n // Preview channel: fill L1\n this.cacheManager.receiveComposedFrames(stream, {\n clipId: clipId,\n trackId: this.compositionModel!.mainTrackId,\n fps,\n onFrame: () => {},\n });\n }\n },\n onEncodedStreamReady: (stream, track) => {\n if (options?.forL2Only) {\n // L2 channel: write to L2 using clipId, notify on complete\n this.cacheManager.receiveEncodedChunks(stream, clipId, track, {\n onComplete: () => {\n session.dispose();\n // Only notify completion for video track (audio is optional)\n if (track === 'video' && options.onL2Complete) {\n options.onL2Complete();\n }\n },\n onError: (error) => {\n console.error(\n `[Orchestrator] L2 encode stream error for ${clipId} ${track}:`,\n error\n );\n session.dispose();\n if (options.onL2Error) {\n options.onL2Error(error);\n }\n },\n });\n } else {\n // Preview channel: don't write to L2, cancel stream\n stream.cancel();\n }\n },\n onPipelineReady: async () => {\n const clip = this.compositionModel?.findClip(clipId);\n if (clip?.resourceId) {\n await this.resourceLoader.fetch(clip.resourceId, {\n priority: options?.forL2Only ? 'low' : 'high',\n sessionId: sessionId,\n trackId: clip.trackId,\n });\n }\n },\n },\n });\n\n this.activeClips.add(sessionId);\n return session;\n }\n\n async dispose(): Promise<void> {\n this.resourceLoader.dispose();\n await this.clipSessionManager.dispose();\n await this.cacheManager.clear();\n\n this.currentClipId = null;\n this.activeClips.clear();\n\n this.workers.terminateAll();\n this.compositionModel = null;\n this.eventBus.dispose();\n }\n\n private buildWorkerConfigs(): Record<WorkerType, any> {\n const config = this.config as any;\n const defaultCanvasWidth = config.global?.defaultCanvasWidth ?? 720;\n const defaultCanvasHeight = config.global?.defaultCanvasHeight ?? 1280;\n const defaultFps = config.global?.defaultFps ?? 30;\n return {\n videoDemux: {\n highWaterMark: config.demux?.backpressure?.highWaterMark ?? 10,\n },\n audioDemux: {\n highWaterMark: config.demux?.backpressure?.highWaterMark ?? 10,\n },\n decode: {\n video: config.decode?.video,\n audio: config.decode?.audio,\n },\n videoCompose: {\n width: config.compose?.canvas?.width ?? defaultCanvasWidth,\n height: config.compose?.canvas?.height ?? defaultCanvasHeight,\n fps: config.global?.defaultFps ?? defaultFps,\n backgroundColor: config.compose?.canvas?.backgroundColor ?? '#000000',\n enableSmoothing: config.compose?.visual?.enableSmoothing ?? true,\n enableHardwareAcceleration: config.compose?.visual?.enableHardwareAcceleration ?? true,\n },\n audioCompose: {\n ducking: config.compose?.audio?.ducking,\n mixing: config.compose?.audio?.mixing,\n },\n encode: {\n video: {\n codec: 'avc1.42002A',\n width: config.compose?.canvas?.width || defaultCanvasWidth,\n height: config.compose?.canvas?.height || defaultCanvasHeight,\n bitrate: config.encode?.video?.bitrateKbps\n ? config.encode.video.bitrateKbps * 1000\n : 12_000_000,\n framerate: config.encode?.video?.framerate || defaultFps,\n latencyMode: 'quality',\n bitrateMode: 'variable',\n hardwareAcceleration: 'no-preference',\n ...(config.encode?.video as any),\n },\n audio: {\n codec: 'mp4a.40.2',\n sampleRate: 48000,\n numberOfChannels: 2,\n bitrate: config.encode?.audio?.bitrateKbps\n ? config.encode.audio.bitrateKbps * 1000\n : 128000,\n ...(config.encode?.audio as any),\n },\n },\n };\n }\n\n private async setupSharedConnections(): Promise<void> {\n const decodeWorker = await this.workers.get('decode');\n\n decodeWorker.receiveStream((stream, metadata) => {\n if (metadata?.streamType === 'audio') {\n this.audioSession.handleAudioStream(stream as ReadableStream<AudioData>, metadata);\n }\n });\n }\n\n async export(model: CompositionModel, options: ExportOptions): Promise<Blob> {\n return this.muxManager.export(model, options);\n }\n}\n"],"names":["applyModelPatch","clip"],"mappings":"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"}
|
|
@@ -6,12 +6,18 @@ import { BaseWorker } from '../worker/BaseWorker';
|
|
|
6
6
|
import { WorkerType } from '../worker/types';
|
|
7
7
|
|
|
8
8
|
interface VideoClipSessionCallbacks {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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>;
|
|
12
16
|
}
|
|
13
17
|
interface VideoClipSessionConfig {
|
|
14
18
|
clipId: string;
|
|
19
|
+
sessionId?: string;
|
|
20
|
+
forL2Only?: boolean;
|
|
15
21
|
planner: CompositionPlanner;
|
|
16
22
|
workerPool: WorkerPool;
|
|
17
23
|
cacheManager: CacheManager;
|
|
@@ -21,6 +27,7 @@ interface VideoClipSessionConfig {
|
|
|
21
27
|
}
|
|
22
28
|
export declare class VideoClipSession {
|
|
23
29
|
private readonly clipId;
|
|
30
|
+
private readonly sessionId;
|
|
24
31
|
private readonly planner;
|
|
25
32
|
private readonly workerPool;
|
|
26
33
|
private readonly cacheManager;
|
|
@@ -56,7 +63,7 @@ export declare class VideoClipSession {
|
|
|
56
63
|
private installInstructions;
|
|
57
64
|
private restartPipeline;
|
|
58
65
|
private releasePipeline;
|
|
59
|
-
|
|
66
|
+
invalidateClipCache(): Promise<void>;
|
|
60
67
|
}
|
|
61
68
|
export {};
|
|
62
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,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAEjF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,UAAU,yBAAyB;IACjC,
|
|
1
|
+
{"version":3,"file":"VideoClipSession.d.ts","sourceRoot":"","sources":["../../src/orchestrator/VideoClipSession.ts"],"names":[],"mappings":"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"}
|