@meframe/core 0.0.38 → 0.0.39

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.
Files changed (46) hide show
  1. package/dist/orchestrator/ExportScheduler.d.ts.map +1 -1
  2. package/dist/orchestrator/ExportScheduler.js +11 -7
  3. package/dist/orchestrator/ExportScheduler.js.map +1 -1
  4. package/dist/orchestrator/GlobalAudioSession.d.ts.map +1 -1
  5. package/dist/orchestrator/GlobalAudioSession.js +19 -17
  6. package/dist/orchestrator/GlobalAudioSession.js.map +1 -1
  7. package/dist/orchestrator/OnDemandVideoSession.d.ts.map +1 -1
  8. package/dist/orchestrator/OnDemandVideoSession.js +1 -21
  9. package/dist/orchestrator/OnDemandVideoSession.js.map +1 -1
  10. package/dist/orchestrator/Orchestrator.d.ts +5 -1
  11. package/dist/orchestrator/Orchestrator.d.ts.map +1 -1
  12. package/dist/orchestrator/Orchestrator.js +39 -26
  13. package/dist/orchestrator/Orchestrator.js.map +1 -1
  14. package/dist/stages/compose/FrameRateConverter.d.ts +6 -1
  15. package/dist/stages/compose/FrameRateConverter.d.ts.map +1 -1
  16. package/dist/stages/decode/BaseDecoder.d.ts.map +1 -1
  17. package/dist/stages/decode/BaseDecoder.js +0 -29
  18. package/dist/stages/decode/BaseDecoder.js.map +1 -1
  19. package/dist/stages/decode/VideoChunkDecoder.d.ts.map +1 -1
  20. package/dist/stages/encode/BaseEncoder.d.ts.map +1 -1
  21. package/dist/stages/encode/BaseEncoder.js +0 -24
  22. package/dist/stages/encode/BaseEncoder.js.map +1 -1
  23. package/dist/stages/load/ResourceLoader.d.ts.map +1 -1
  24. package/dist/stages/load/ResourceLoader.js +36 -20
  25. package/dist/stages/load/ResourceLoader.js.map +1 -1
  26. package/dist/stages/load/TaskManager.d.ts +6 -1
  27. package/dist/stages/load/TaskManager.d.ts.map +1 -1
  28. package/dist/stages/load/TaskManager.js +11 -8
  29. package/dist/stages/load/TaskManager.js.map +1 -1
  30. package/dist/stages/load/types.d.ts +3 -3
  31. package/dist/stages/load/types.d.ts.map +1 -1
  32. package/dist/workers/{BaseDecoder.DWHTBMDB.js → BaseDecoder.CB5XmTpS.js} +1 -30
  33. package/dist/workers/BaseDecoder.CB5XmTpS.js.map +1 -0
  34. package/dist/workers/stages/compose/{video-compose.worker.BhpN-lxf.js → video-compose.worker.DM_bsOY8.js} +27 -4
  35. package/dist/workers/stages/compose/{video-compose.worker.BhpN-lxf.js.map → video-compose.worker.DM_bsOY8.js.map} +1 -1
  36. package/dist/workers/stages/decode/{audio-decode.worker.BsuBzFx5.js → audio-decode.worker.B__6tqsy.js} +2 -2
  37. package/dist/workers/stages/decode/{audio-decode.worker.BsuBzFx5.js.map → audio-decode.worker.B__6tqsy.js.map} +1 -1
  38. package/dist/workers/stages/decode/{video-decode.worker.CwOjEmre.js → video-decode.worker.tOv-QR2f.js} +2 -4
  39. package/dist/workers/stages/decode/video-decode.worker.tOv-QR2f.js.map +1 -0
  40. package/dist/workers/stages/encode/{video-encode.worker.CXgr5E16.js → video-encode.worker.D8pfFber.js} +1 -25
  41. package/dist/workers/stages/encode/video-encode.worker.D8pfFber.js.map +1 -0
  42. package/dist/workers/worker-manifest.json +4 -4
  43. package/package.json +1 -1
  44. package/dist/workers/BaseDecoder.DWHTBMDB.js.map +0 -1
  45. package/dist/workers/stages/decode/video-decode.worker.CwOjEmre.js.map +0 -1
  46. package/dist/workers/stages/encode/video-encode.worker.CXgr5E16.js.map +0 -1
@@ -9,24 +9,7 @@ class BaseDecoder {
9
9
  if (this.decoder?.state === "configured") {
10
10
  return;
11
11
  }
12
- const configInfo = {
13
- codec: this.config.codec,
14
- width: this.config.width,
15
- height: this.config.height,
16
- sampleRate: this.config.sampleRate,
17
- numberOfChannels: this.config.numberOfChannels,
18
- hardwareAcceleration: this.config.hardwareAcceleration
19
- };
20
- console.log(`[${this.getDecoderType()}Decoder] Checking config support:`, {
21
- platform: typeof navigator !== "undefined" ? navigator.platform : "unknown",
22
- userAgent: typeof navigator !== "undefined" ? navigator.userAgent : "unknown",
23
- config: configInfo
24
- });
25
12
  const isSupported = await this.isConfigSupported(this.config);
26
- console.log(`[${this.getDecoderType()}Decoder] Config support result:`, {
27
- supported: isSupported.supported,
28
- config: configInfo
29
- });
30
13
  if (!isSupported.supported) {
31
14
  throw new Error(
32
15
  `Codec not supported: ${this.config.codecString || this.config.codec}`
@@ -36,12 +19,7 @@ class BaseDecoder {
36
19
  output: this.handleOutput.bind(this),
37
20
  error: this.handleError.bind(this)
38
21
  });
39
- console.log(`[${this.getDecoderType()}Decoder] Decoder created, configuring...`);
40
22
  await this.configureDecoder(this.config);
41
- console.log(
42
- `[${this.getDecoderType()}Decoder] Configured successfully, state:`,
43
- this.decoder?.state
44
- );
45
23
  }
46
24
  async reconfigure(config) {
47
25
  this.config = { ...this.config, ...config };
@@ -107,13 +85,6 @@ class BaseDecoder {
107
85
  }
108
86
  }
109
87
  handleError(error) {
110
- console.error(`[${this.getDecoderType()}Decoder] Decode error:`, {
111
- name: error.name,
112
- message: error.message,
113
- decoderState: this.decoder?.state,
114
- queueSize: this.queueSize,
115
- platform: typeof navigator !== "undefined" ? navigator.platform : "unknown"
116
- });
117
88
  this.controller?.error(error);
118
89
  }
119
90
  closeIfPossible(data) {
@@ -163,4 +134,4 @@ class BaseDecoder {
163
134
  export {
164
135
  BaseDecoder as B
165
136
  };
166
- //# sourceMappingURL=BaseDecoder.DWHTBMDB.js.map
137
+ //# sourceMappingURL=BaseDecoder.CB5XmTpS.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseDecoder.CB5XmTpS.js","sources":["../../src/stages/decode/BaseDecoder.ts"],"sourcesContent":["/**\n * Base decoder class abstracting common WebCodecs decoder workflow.\n * Mirrors BaseEncoder but for decoding path.\n */\nimport { AudioDecoderConfig, DecodedVideoFrame, VideoDecoderConfig } from './types';\n\nexport abstract class BaseDecoder<\n TDecoder extends VideoDecoder | AudioDecoder,\n TConfig extends VideoDecoderConfig | AudioDecoderConfig,\n TInput extends EncodedVideoChunk | EncodedAudioChunk,\n TOutput extends VideoFrame | AudioData | DecodedVideoFrame,\n> {\n protected decoder?: TDecoder;\n protected config: TConfig;\n protected controller: TransformStreamDefaultController<TOutput> | null = null;\n\n constructor(config: TConfig) {\n this.config = config;\n }\n\n async initialize(): Promise<void> {\n if (this.decoder?.state === 'configured') {\n return;\n }\n\n const isSupported = await this.isConfigSupported(this.config);\n\n if (!isSupported.supported) {\n throw new Error(\n `Codec not supported: ${(this.config as any).codecString || (this.config as any).codec}`\n );\n }\n\n this.decoder = this.createDecoder({\n output: this.handleOutput.bind(this),\n error: this.handleError.bind(this),\n });\n\n await this.configureDecoder(this.config);\n }\n\n async reconfigure(config: Partial<TConfig>): Promise<void> {\n this.config = { ...this.config, ...config } as TConfig;\n\n if (!this.decoder) {\n await this.initialize();\n return;\n }\n\n // Flush before reconfiguring\n if (this.decoder.state === 'configured') {\n await this.decoder.flush();\n }\n\n const isSupported = await this.isConfigSupported(this.config);\n if (!isSupported.supported) {\n throw new Error(\n `New configuration not supported: ${(this.config as any).codecString || (this.config as any).codec}`\n );\n }\n\n await this.configureDecoder(this.config);\n }\n\n async flush(): Promise<void> {\n if (!this.decoder) return;\n await this.decoder.flush();\n }\n\n async reset(): Promise<void> {\n if (!this.decoder) return;\n\n // Windows Media Foundation requires flush before reset to avoid decoder error state\n if (this.decoder.state === 'configured') {\n try {\n await this.decoder.flush();\n } catch {\n // Ignore flush errors during reset\n }\n }\n\n this.decoder.reset();\n this.onReset();\n }\n\n async close(): Promise<void> {\n if (!this.decoder) return;\n\n if (this.decoder.state === 'configured') {\n await this.decoder.flush();\n }\n\n this.decoder.close();\n this.decoder = undefined;\n }\n\n get isReady(): boolean {\n return this.decoder?.state === 'configured';\n }\n\n get queueSize(): number {\n return (this.decoder as any)?.decodeQueueSize ?? 0;\n }\n\n protected handleOutput(data: TOutput): void {\n if (!this.controller) {\n this.closeIfPossible(data);\n return;\n }\n\n try {\n this.controller.enqueue(data);\n if (data instanceof VideoFrame && (this.config as VideoDecoderConfig).thread !== 'main') {\n // ugly hack to avoid memory leak\n // setTimeout(() => {\n // data.close();\n // }, 500);\n }\n } catch (error) {\n // Stream closed or errored - silently drop frame\n if (error instanceof TypeError) {\n this.closeIfPossible(data);\n return;\n }\n\n throw error;\n }\n }\n\n protected handleError(error: DOMException): void {\n this.controller?.error(error);\n }\n\n private closeIfPossible(data: TOutput): void {\n (data as any)?.close?.();\n (data as DecodedVideoFrame)?.frame?.close?.();\n }\n\n // Abstracts\n protected abstract isConfigSupported(config: TConfig): Promise<{ supported: boolean }>;\n protected abstract createDecoder(init: DecoderInit): TDecoder;\n protected abstract configureDecoder(config: TConfig): Promise<void>;\n protected abstract getDecoderType(): string;\n protected abstract decode(input: TInput): void;\n protected onReset(): void {}\n\n // Backpressure\n protected abstract readonly highWaterMark: number;\n protected abstract readonly decodeQueueThreshold: number;\n\n createStream(): TransformStream<TInput, TOutput> {\n return new TransformStream<TInput, TOutput>(\n {\n start: async (controller) => {\n this.controller = controller;\n if (!this.isReady) {\n await this.initialize();\n }\n },\n transform: async (input) => {\n if (!this.decoder || this.decoder.state !== 'configured') {\n throw new Error('Decoder not configured');\n }\n // backpressure\n if ((this.decoder as any).decodeQueueSize >= this.decodeQueueThreshold) {\n await new Promise<void>((resolve) => {\n const check = () => {\n if (\n !this.decoder ||\n (this.decoder as any).decodeQueueSize < this.decodeQueueThreshold - 1\n ) {\n resolve();\n } else {\n setTimeout(check, 10);\n }\n };\n check();\n });\n }\n this.decode(input);\n },\n flush: async () => {\n await this.flush();\n },\n },\n {\n highWaterMark: this.highWaterMark,\n size: () => 1,\n }\n );\n }\n}\n\ninterface DecoderInit {\n output: (data: any) => void;\n error: (error: DOMException) => void;\n}\n"],"names":[],"mappings":"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"}
@@ -1760,11 +1760,12 @@ function applyEasing(t, easing) {
1760
1760
  class FrameRateConverter {
1761
1761
  clipDurationUs;
1762
1762
  frameDurationUs;
1763
+ trimStartUs;
1763
1764
  // State for frame processing
1764
1765
  targetFrameIndex = 0;
1765
1766
  targetFrameTimeUs = 0;
1766
1767
  sourceFrameBuffer = [];
1767
- constructor(targetFps, clipDurationUs) {
1768
+ constructor(targetFps, clipDurationUs, trimStartUs = 0) {
1768
1769
  if (targetFps <= 0) {
1769
1770
  throw new Error(`Invalid target fps: ${targetFps}`);
1770
1771
  }
@@ -1773,6 +1774,7 @@ class FrameRateConverter {
1773
1774
  }
1774
1775
  this.clipDurationUs = clipDurationUs;
1775
1776
  this.frameDurationUs = Math.round(1e6 / targetFps);
1777
+ this.trimStartUs = trimStartUs;
1776
1778
  }
1777
1779
  /**
1778
1780
  * Create a TransformStream that converts VFR frames to CFR frames
@@ -1800,7 +1802,23 @@ class FrameRateConverter {
1800
1802
  * Process incoming source frame and output target frames
1801
1803
  */
1802
1804
  processSourceFrame(sourceFrame, controller) {
1803
- this.sourceFrameBuffer.push(sourceFrame);
1805
+ const sourceTimestamp = sourceFrame.timestamp ?? 0;
1806
+ if (sourceTimestamp < this.trimStartUs) {
1807
+ sourceFrame.close();
1808
+ return;
1809
+ }
1810
+ let frameToBuffer;
1811
+ if (this.trimStartUs > 0) {
1812
+ const adjustedTimestamp = sourceTimestamp - this.trimStartUs;
1813
+ frameToBuffer = new VideoFrame(sourceFrame, {
1814
+ timestamp: adjustedTimestamp,
1815
+ duration: sourceFrame.duration ?? void 0
1816
+ });
1817
+ sourceFrame.close();
1818
+ } else {
1819
+ frameToBuffer = sourceFrame;
1820
+ }
1821
+ this.sourceFrameBuffer.push(frameToBuffer);
1804
1822
  this.sourceFrameCount++;
1805
1823
  while (this.targetFrameTimeUs < this.clipDurationUs) {
1806
1824
  const closestFrame = this.findClosestFrame(this.targetFrameTimeUs);
@@ -2131,10 +2149,15 @@ class VideoComposeWorker {
2131
2149
  console.warn("[VideoComposeWorker] No instructions installed");
2132
2150
  return;
2133
2151
  }
2152
+ const mainLayer = this.instructions.layers.find(
2153
+ (l) => l.type === "video" && !l.payload.attachmentId
2154
+ );
2155
+ const trimStartUs = mainLayer?.type === "video" ? mainLayer.payload.trimStartUs ?? 0 : 0;
2134
2156
  const timeline = this.instructions.baseConfig.timeline;
2135
2157
  const fpsConverter = new FrameRateConverter(
2136
2158
  timeline?.compositionFps ?? 30,
2137
- timeline?.clipDurationUs ?? Infinity
2159
+ timeline?.clipDurationUs ?? Infinity,
2160
+ trimStartUs
2138
2161
  );
2139
2162
  const cfrStream = stream.pipeThrough(fpsConverter.createStream());
2140
2163
  const filteredStream = cfrStream.pipeThrough(
@@ -2379,4 +2402,4 @@ export {
2379
2402
  VideoComposeWorker,
2380
2403
  videoCompose_worker as default
2381
2404
  };
2382
- //# sourceMappingURL=video-compose.worker.BhpN-lxf.js.map
2405
+ //# sourceMappingURL=video-compose.worker.DM_bsOY8.js.map