@meframe/core 0.4.3 → 0.4.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.
Files changed (39) hide show
  1. package/dist/model/types.d.ts +6 -0
  2. package/dist/model/types.d.ts.map +1 -1
  3. package/dist/model/types.js +14 -1
  4. package/dist/model/types.js.map +1 -1
  5. package/dist/orchestrator/AudioPreviewSession.d.ts.map +1 -1
  6. package/dist/orchestrator/AudioPreviewSession.js +3 -3
  7. package/dist/orchestrator/AudioPreviewSession.js.map +1 -1
  8. package/dist/orchestrator/AudioWindowPreparer.d.ts.map +1 -1
  9. package/dist/orchestrator/AudioWindowPreparer.js +6 -3
  10. package/dist/orchestrator/AudioWindowPreparer.js.map +1 -1
  11. package/dist/orchestrator/CompositionPlanner.d.ts.map +1 -1
  12. package/dist/orchestrator/CompositionPlanner.js +4 -2
  13. package/dist/orchestrator/CompositionPlanner.js.map +1 -1
  14. package/dist/orchestrator/ExportScheduler.d.ts.map +1 -1
  15. package/dist/orchestrator/ExportScheduler.js +4 -2
  16. package/dist/orchestrator/ExportScheduler.js.map +1 -1
  17. package/dist/orchestrator/Orchestrator.d.ts.map +1 -1
  18. package/dist/orchestrator/Orchestrator.js +18 -11
  19. package/dist/orchestrator/Orchestrator.js.map +1 -1
  20. package/dist/orchestrator/VideoWindowDecodeSession.d.ts +3 -0
  21. package/dist/orchestrator/VideoWindowDecodeSession.d.ts.map +1 -1
  22. package/dist/orchestrator/VideoWindowDecodeSession.js +41 -1
  23. package/dist/orchestrator/VideoWindowDecodeSession.js.map +1 -1
  24. package/dist/stages/compose/FrameRateConverter.d.ts +2 -1
  25. package/dist/stages/compose/FrameRateConverter.d.ts.map +1 -1
  26. package/dist/stages/compose/OfflineAudioMixer.d.ts.map +1 -1
  27. package/dist/stages/compose/OfflineAudioMixer.js +9 -3
  28. package/dist/stages/compose/OfflineAudioMixer.js.map +1 -1
  29. package/dist/stages/load/ResourceLoader.d.ts.map +1 -1
  30. package/dist/stages/load/ResourceLoader.js +58 -2
  31. package/dist/stages/load/ResourceLoader.js.map +1 -1
  32. package/dist/utils/loop-utils.d.ts +2 -0
  33. package/dist/utils/loop-utils.d.ts.map +1 -1
  34. package/dist/utils/loop-utils.js +5 -2
  35. package/dist/utils/loop-utils.js.map +1 -1
  36. package/dist/workers/stages/export/{export.worker.DCStS1mL.js → export.worker.Cw9iPvkh.js} +27 -17
  37. package/dist/workers/stages/export/{export.worker.DCStS1mL.js.map → export.worker.Cw9iPvkh.js.map} +1 -1
  38. package/dist/workers/worker-manifest.json +1 -1
  39. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"loop-utils.d.ts","sourceRoot":"","sources":["../../src/utils/loop-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAE7C,MAAM,WAAW,WAAW;IAC1B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,2BAA2B,CAAC,MAAM,EAAE;IAClD,mBAAmB,EAAE,MAAM,CAAC;IAC5B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,IAAI,EAAE,OAAO,CAAC;CACf,GAAG,WAAW,EAAE,CA+ChB"}
1
+ {"version":3,"file":"loop-utils.d.ts","sourceRoot":"","sources":["../../src/utils/loop-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAE7C,MAAM,WAAW,WAAW;IAC1B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,2BAA2B,CAAC,MAAM,EAAE;IAClD,mBAAmB,EAAE,MAAM,CAAC;IAC5B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,IAAI,EAAE,OAAO,CAAC;IACd,wEAAwE;IACxE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GAAG,WAAW,EAAE,CAkDhB"}
@@ -6,12 +6,15 @@ function buildLoopedResourceSegments(params) {
6
6
  return [];
7
7
  }
8
8
  if (!params.loop) {
9
+ const rawR = params.playbackRate ?? 1;
10
+ const rate = typeof rawR === "number" && Number.isFinite(rawR) && rawR > 0 ? rawR : 1;
11
+ const trim = params.trimStartUs ?? 0;
9
12
  return [
10
13
  {
11
14
  clipRelativeStartUs: rangeStartUs,
12
15
  durationUs: requestedDurationUs,
13
- resourceStartUs: rangeStartUs + (params.trimStartUs ?? 0),
14
- resourceEndUs: rangeEndUs + (params.trimStartUs ?? 0)
16
+ resourceStartUs: trim + rangeStartUs * rate,
17
+ resourceEndUs: trim + rangeEndUs * rate
15
18
  }
16
19
  ];
17
20
  }
@@ -1 +1 @@
1
- {"version":3,"file":"loop-utils.js","sources":["../../src/utils/loop-utils.ts"],"sourcesContent":["import type { TimeUs } from '../model/types';\n\nexport interface LoopSegment {\n clipRelativeStartUs: TimeUs;\n durationUs: TimeUs;\n resourceStartUs: TimeUs;\n resourceEndUs: TimeUs;\n}\n\nexport function buildLoopedResourceSegments(params: {\n clipRelativeStartUs: TimeUs;\n clipRelativeEndUs: TimeUs;\n trimStartUs: TimeUs;\n resourceDurationUs: TimeUs;\n loop: boolean;\n}): LoopSegment[] {\n const rangeStartUs = Math.max(0, params.clipRelativeStartUs);\n const rangeEndUs = Math.max(rangeStartUs, params.clipRelativeEndUs);\n\n const requestedDurationUs = rangeEndUs - rangeStartUs;\n if (requestedDurationUs <= 0) {\n return [];\n }\n\n if (!params.loop) {\n return [\n {\n clipRelativeStartUs: rangeStartUs,\n durationUs: requestedDurationUs,\n resourceStartUs: rangeStartUs + (params.trimStartUs ?? 0),\n resourceEndUs: rangeEndUs + (params.trimStartUs ?? 0),\n },\n ];\n }\n\n const trimStartUs = params.trimStartUs ?? 0;\n const periodUs = params.resourceDurationUs - trimStartUs;\n if (periodUs <= 0) {\n return [];\n }\n\n const segments: LoopSegment[] = [];\n let tUs = rangeStartUs;\n\n while (tUs < rangeEndUs) {\n const offsetInPeriodUs = tUs % periodUs;\n const maxLenUs = periodUs - offsetInPeriodUs;\n const lenUs = Math.min(rangeEndUs - tUs, maxLenUs);\n if (lenUs <= 0) break;\n\n const resourceStartUs = trimStartUs + offsetInPeriodUs;\n segments.push({\n clipRelativeStartUs: tUs,\n durationUs: lenUs,\n resourceStartUs,\n resourceEndUs: resourceStartUs + lenUs,\n });\n\n tUs += lenUs;\n }\n\n return segments;\n}\n"],"names":[],"mappings":"AASO,SAAS,4BAA4B,QAM1B;AAChB,QAAM,eAAe,KAAK,IAAI,GAAG,OAAO,mBAAmB;AAC3D,QAAM,aAAa,KAAK,IAAI,cAAc,OAAO,iBAAiB;AAElE,QAAM,sBAAsB,aAAa;AACzC,MAAI,uBAAuB,GAAG;AAC5B,WAAO,CAAA;AAAA,EACT;AAEA,MAAI,CAAC,OAAO,MAAM;AAChB,WAAO;AAAA,MACL;AAAA,QACE,qBAAqB;AAAA,QACrB,YAAY;AAAA,QACZ,iBAAiB,gBAAgB,OAAO,eAAe;AAAA,QACvD,eAAe,cAAc,OAAO,eAAe;AAAA,MAAA;AAAA,IACrD;AAAA,EAEJ;AAEA,QAAM,cAAc,OAAO,eAAe;AAC1C,QAAM,WAAW,OAAO,qBAAqB;AAC7C,MAAI,YAAY,GAAG;AACjB,WAAO,CAAA;AAAA,EACT;AAEA,QAAM,WAA0B,CAAA;AAChC,MAAI,MAAM;AAEV,SAAO,MAAM,YAAY;AACvB,UAAM,mBAAmB,MAAM;AAC/B,UAAM,WAAW,WAAW;AAC5B,UAAM,QAAQ,KAAK,IAAI,aAAa,KAAK,QAAQ;AACjD,QAAI,SAAS,EAAG;AAEhB,UAAM,kBAAkB,cAAc;AACtC,aAAS,KAAK;AAAA,MACZ,qBAAqB;AAAA,MACrB,YAAY;AAAA,MACZ;AAAA,MACA,eAAe,kBAAkB;AAAA,IAAA,CAClC;AAED,WAAO;AAAA,EACT;AAEA,SAAO;AACT;"}
1
+ {"version":3,"file":"loop-utils.js","sources":["../../src/utils/loop-utils.ts"],"sourcesContent":["import type { TimeUs } from '../model/types';\n\nexport interface LoopSegment {\n clipRelativeStartUs: TimeUs;\n durationUs: TimeUs;\n resourceStartUs: TimeUs;\n resourceEndUs: TimeUs;\n}\n\nexport function buildLoopedResourceSegments(params: {\n clipRelativeStartUs: TimeUs;\n clipRelativeEndUs: TimeUs;\n trimStartUs: TimeUs;\n resourceDurationUs: TimeUs;\n loop: boolean;\n /** Applied only when loop is false (e.g. video clip timeline speed). */\n playbackRate?: number;\n}): LoopSegment[] {\n const rangeStartUs = Math.max(0, params.clipRelativeStartUs);\n const rangeEndUs = Math.max(rangeStartUs, params.clipRelativeEndUs);\n\n const requestedDurationUs = rangeEndUs - rangeStartUs;\n if (requestedDurationUs <= 0) {\n return [];\n }\n\n if (!params.loop) {\n const rawR = params.playbackRate ?? 1;\n const rate = typeof rawR === 'number' && Number.isFinite(rawR) && rawR > 0 ? rawR : 1;\n const trim = params.trimStartUs ?? 0;\n return [\n {\n clipRelativeStartUs: rangeStartUs,\n durationUs: requestedDurationUs,\n resourceStartUs: trim + rangeStartUs * rate,\n resourceEndUs: trim + rangeEndUs * rate,\n },\n ];\n }\n\n const trimStartUs = params.trimStartUs ?? 0;\n const periodUs = params.resourceDurationUs - trimStartUs;\n if (periodUs <= 0) {\n return [];\n }\n\n const segments: LoopSegment[] = [];\n let tUs = rangeStartUs;\n\n while (tUs < rangeEndUs) {\n const offsetInPeriodUs = tUs % periodUs;\n const maxLenUs = periodUs - offsetInPeriodUs;\n const lenUs = Math.min(rangeEndUs - tUs, maxLenUs);\n if (lenUs <= 0) break;\n\n const resourceStartUs = trimStartUs + offsetInPeriodUs;\n segments.push({\n clipRelativeStartUs: tUs,\n durationUs: lenUs,\n resourceStartUs,\n resourceEndUs: resourceStartUs + lenUs,\n });\n\n tUs += lenUs;\n }\n\n return segments;\n}\n"],"names":[],"mappings":"AASO,SAAS,4BAA4B,QAQ1B;AAChB,QAAM,eAAe,KAAK,IAAI,GAAG,OAAO,mBAAmB;AAC3D,QAAM,aAAa,KAAK,IAAI,cAAc,OAAO,iBAAiB;AAElE,QAAM,sBAAsB,aAAa;AACzC,MAAI,uBAAuB,GAAG;AAC5B,WAAO,CAAA;AAAA,EACT;AAEA,MAAI,CAAC,OAAO,MAAM;AAChB,UAAM,OAAO,OAAO,gBAAgB;AACpC,UAAM,OAAO,OAAO,SAAS,YAAY,OAAO,SAAS,IAAI,KAAK,OAAO,IAAI,OAAO;AACpF,UAAM,OAAO,OAAO,eAAe;AACnC,WAAO;AAAA,MACL;AAAA,QACE,qBAAqB;AAAA,QACrB,YAAY;AAAA,QACZ,iBAAiB,OAAO,eAAe;AAAA,QACvC,eAAe,OAAO,aAAa;AAAA,MAAA;AAAA,IACrC;AAAA,EAEJ;AAEA,QAAM,cAAc,OAAO,eAAe;AAC1C,QAAM,WAAW,OAAO,qBAAqB;AAC7C,MAAI,YAAY,GAAG;AACjB,WAAO,CAAA;AAAA,EACT;AAEA,QAAM,WAA0B,CAAA;AAChC,MAAI,MAAM;AAEV,SAAO,MAAM,YAAY;AACvB,UAAM,mBAAmB,MAAM;AAC/B,UAAM,WAAW,WAAW;AAC5B,UAAM,QAAQ,KAAK,IAAI,aAAa,KAAK,QAAQ;AACjD,QAAI,SAAS,EAAG;AAEhB,UAAM,kBAAkB,cAAc;AACtC,aAAS,KAAK;AAAA,MACZ,qBAAqB;AAAA,MACrB,YAAY;AAAA,MACZ;AAAA,MACA,eAAe,kBAAkB;AAAA,IAAA,CAClC;AAED,WAAO;AAAA,EACT;AAEA,SAAO;AACT;"}
@@ -2633,13 +2633,14 @@ class FrameRateConverter {
2633
2633
  clipDurationUs;
2634
2634
  frameDurationUs;
2635
2635
  trimStartUs;
2636
+ playbackRate;
2636
2637
  totalFrameCount;
2637
2638
  // State for frame processing
2638
2639
  targetFrameIndex = 0;
2639
2640
  targetFrameTimeUs = 0;
2640
2641
  sourceFrameBuffer = [];
2641
2642
  maxSourceTimestampUs = null;
2642
- constructor(targetFps, clipDurationUs, trimStartUs = 0) {
2643
+ constructor(targetFps, clipDurationUs, trimStartUs = 0, playbackRate = 1) {
2643
2644
  if (targetFps <= 0) {
2644
2645
  throw new Error(`Invalid target fps: ${targetFps}`);
2645
2646
  }
@@ -2649,6 +2650,7 @@ class FrameRateConverter {
2649
2650
  this.clipDurationUs = clipDurationUs;
2650
2651
  this.frameDurationUs = Math.round(1e6 / targetFps);
2651
2652
  this.trimStartUs = trimStartUs;
2653
+ this.playbackRate = typeof playbackRate === "number" && Number.isFinite(playbackRate) && playbackRate > 0 ? playbackRate : 1;
2652
2654
  this.totalFrameCount = Number.isFinite(clipDurationUs) ? Math.max(1, Math.round(clipDurationUs / this.frameDurationUs)) : null;
2653
2655
  }
2654
2656
  /**
@@ -2699,10 +2701,11 @@ class FrameRateConverter {
2699
2701
  const bufferedTs = frameToBuffer.timestamp ?? 0;
2700
2702
  this.maxSourceTimestampUs = this.maxSourceTimestampUs === null ? bufferedTs : Math.max(this.maxSourceTimestampUs, bufferedTs);
2701
2703
  while (this.shouldContinueOutput()) {
2702
- if (this.maxSourceTimestampUs !== null && this.targetFrameTimeUs > this.maxSourceTimestampUs) {
2704
+ const targetSourceUs = this.targetFrameTimeUs * this.playbackRate;
2705
+ if (this.maxSourceTimestampUs !== null && targetSourceUs > this.maxSourceTimestampUs) {
2703
2706
  break;
2704
2707
  }
2705
- const closestFrame = this.findClosestFrame(this.targetFrameTimeUs);
2708
+ const closestFrame = this.findClosestFrame(targetSourceUs);
2706
2709
  if (!closestFrame) {
2707
2710
  break;
2708
2711
  }
@@ -2731,10 +2734,11 @@ class FrameRateConverter {
2731
2734
  */
2732
2735
  flushRemainingFrames(controller) {
2733
2736
  while (this.sourceFrameBuffer.length > 0 && this.shouldContinueOutput()) {
2734
- if (this.maxSourceTimestampUs !== null && this.targetFrameTimeUs > this.maxSourceTimestampUs) {
2737
+ const targetSourceUs = this.targetFrameTimeUs * this.playbackRate;
2738
+ if (this.maxSourceTimestampUs !== null && targetSourceUs > this.maxSourceTimestampUs) {
2735
2739
  break;
2736
2740
  }
2737
- const closestFrame = this.findClosestFrame(this.targetFrameTimeUs);
2741
+ const closestFrame = this.findClosestFrame(targetSourceUs);
2738
2742
  if (!closestFrame) break;
2739
2743
  if (!this.outputTargetFrame(closestFrame, controller)) break;
2740
2744
  }
@@ -2830,7 +2834,8 @@ class FrameRateConverter {
2830
2834
  shouldWaitForNextFrame(closestFrame) {
2831
2835
  if (this.sourceFrameBuffer.length <= 1) {
2832
2836
  const frameTimestamp = closestFrame.timestamp ?? 0;
2833
- if (frameTimestamp < this.targetFrameTimeUs) {
2837
+ const targetSourceUs = this.targetFrameTimeUs * this.playbackRate;
2838
+ if (frameTimestamp < targetSourceUs) {
2834
2839
  return true;
2835
2840
  }
2836
2841
  }
@@ -2840,16 +2845,18 @@ class FrameRateConverter {
2840
2845
  * Clean up source frames that are no longer needed
2841
2846
  * Keep frames that might be needed for future target frames
2842
2847
  */
2843
- cleanupOldFrames(currentTargetTimeUs) {
2844
- const nextTargetTimeUs = currentTargetTimeUs + this.frameDurationUs;
2845
- const previousTargetTimeUs = currentTargetTimeUs - this.frameDurationUs;
2848
+ cleanupOldFrames(currentTimelineTargetUs) {
2849
+ const nextTimelineUs = currentTimelineTargetUs + this.frameDurationUs;
2850
+ const prevTimelineUs = currentTimelineTargetUs - this.frameDurationUs;
2851
+ const nextSourceUs = nextTimelineUs * this.playbackRate;
2852
+ const prevSourceUs = prevTimelineUs * this.playbackRate;
2846
2853
  let removeCount = 0;
2847
2854
  for (let i = 0; i < this.sourceFrameBuffer.length; i++) {
2848
2855
  const frame = this.sourceFrameBuffer[i];
2849
2856
  if (!frame) continue;
2850
2857
  const frameTimestamp = frame.timestamp ?? 0;
2851
- const isNeededForNext = Math.abs(frameTimestamp - nextTargetTimeUs) < Math.abs(frameTimestamp - previousTargetTimeUs);
2852
- if (frameTimestamp < previousTargetTimeUs && !isNeededForNext) {
2858
+ const isNeededForNext = Math.abs(frameTimestamp - nextSourceUs) < Math.abs(frameTimestamp - prevSourceUs);
2859
+ if (frameTimestamp < prevSourceUs && !isNeededForNext) {
2853
2860
  try {
2854
2861
  frame.close();
2855
2862
  } catch {
@@ -3062,19 +3069,22 @@ class ExportWorker {
3062
3069
  (l) => l.type === "video" && !l.payload.attachmentId
3063
3070
  );
3064
3071
  const clipTrimStartUs = mainLayer?.type === "video" ? mainLayer.payload.trimStartUs ?? 0 : 0;
3072
+ const rawRate = mainLayer?.type === "video" ? mainLayer.payload.playbackRate ?? 1 : 1;
3073
+ const playbackRate = typeof rawRate === "number" && Number.isFinite(rawRate) && rawRate > 0 ? rawRate : 1;
3065
3074
  const timeline = this.instructions.baseConfig.timeline;
3066
3075
  const fps = timeline?.compositionFps ?? 30;
3067
3076
  const windowStartUs = metadata?.windowStartUs ?? clipTrimStartUs;
3068
- const windowEndUs = metadata?.windowEndUs ?? clipTrimStartUs + (timeline?.clipDurationUs ?? Infinity);
3069
- const windowDurationUs = windowEndUs - windowStartUs;
3070
- const windowToClipOffsetUs = windowStartUs - clipTrimStartUs;
3071
- const fpsConverter = new FrameRateConverter(fps, windowDurationUs, windowStartUs);
3077
+ const windowEndResourceUs = metadata?.windowEndUs ?? clipTrimStartUs + (timeline?.clipDurationUs ?? Infinity) * playbackRate;
3078
+ const resourceWindowUs = windowEndResourceUs - windowStartUs;
3079
+ const timelineWindowUs = resourceWindowUs / playbackRate;
3080
+ const windowToClipOffsetUs = (windowStartUs - clipTrimStartUs) / playbackRate;
3081
+ const fpsConverter = new FrameRateConverter(fps, timelineWindowUs, windowStartUs, playbackRate);
3072
3082
  const cfrStream = stream.pipeThrough(fpsConverter.createStream());
3073
3083
  const composeRequestStream = cfrStream.pipeThrough(
3074
3084
  new TransformStream({
3075
3085
  transform: (frame, controller) => {
3076
3086
  let composeFrame = frame;
3077
- if (windowToClipOffsetUs > 0) {
3087
+ if (windowToClipOffsetUs !== 0) {
3078
3088
  composeFrame = new VideoFrame(frame, {
3079
3089
  timestamp: (frame.timestamp ?? 0) + windowToClipOffsetUs
3080
3090
  });
@@ -3243,4 +3253,4 @@ const export_worker = null;
3243
3253
  export {
3244
3254
  export_worker as default
3245
3255
  };
3246
- //# sourceMappingURL=export.worker.DCStS1mL.js.map
3256
+ //# sourceMappingURL=export.worker.Cw9iPvkh.js.map