@meframe/core 0.0.40 → 0.0.42

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 (63) hide show
  1. package/dist/Meframe.d.ts +1 -0
  2. package/dist/Meframe.d.ts.map +1 -1
  3. package/dist/Meframe.js +2 -2
  4. package/dist/Meframe.js.map +1 -1
  5. package/dist/cache/CacheManager.d.ts +1 -0
  6. package/dist/cache/CacheManager.d.ts.map +1 -1
  7. package/dist/cache/CacheManager.js +2 -1
  8. package/dist/cache/CacheManager.js.map +1 -1
  9. package/dist/cache/resource/MP4IndexCache.d.ts +4 -0
  10. package/dist/cache/resource/MP4IndexCache.d.ts.map +1 -1
  11. package/dist/cache/resource/MP4IndexCache.js +6 -0
  12. package/dist/cache/resource/MP4IndexCache.js.map +1 -1
  13. package/dist/cache/resource/ResourceCache.d.ts +3 -8
  14. package/dist/cache/resource/ResourceCache.d.ts.map +1 -1
  15. package/dist/cache/resource/ResourceCache.js +26 -11
  16. package/dist/cache/resource/ResourceCache.js.map +1 -1
  17. package/dist/cache/storage/opfs/OPFSManager.d.ts +28 -4
  18. package/dist/cache/storage/opfs/OPFSManager.d.ts.map +1 -1
  19. package/dist/cache/storage/opfs/OPFSManager.js +110 -4
  20. package/dist/cache/storage/opfs/OPFSManager.js.map +1 -1
  21. package/dist/cache/storage/opfs/types.d.ts +5 -0
  22. package/dist/cache/storage/opfs/types.d.ts.map +1 -1
  23. package/dist/config/defaults.js +1 -1
  24. package/dist/config/defaults.js.map +1 -1
  25. package/dist/controllers/PlaybackController.d.ts +0 -3
  26. package/dist/controllers/PlaybackController.d.ts.map +1 -1
  27. package/dist/controllers/PlaybackController.js +29 -53
  28. package/dist/controllers/PlaybackController.js.map +1 -1
  29. package/dist/orchestrator/GlobalAudioSession.d.ts +5 -0
  30. package/dist/orchestrator/GlobalAudioSession.d.ts.map +1 -1
  31. package/dist/orchestrator/GlobalAudioSession.js +45 -57
  32. package/dist/orchestrator/GlobalAudioSession.js.map +1 -1
  33. package/dist/orchestrator/Orchestrator.d.ts.map +1 -1
  34. package/dist/orchestrator/Orchestrator.js +3 -2
  35. package/dist/orchestrator/Orchestrator.js.map +1 -1
  36. package/dist/orchestrator/VideoClipSession.d.ts.map +1 -1
  37. package/dist/orchestrator/VideoClipSession.js +1 -0
  38. package/dist/orchestrator/VideoClipSession.js.map +1 -1
  39. package/dist/stages/compose/FrameRateConverter.d.ts +12 -0
  40. package/dist/stages/compose/FrameRateConverter.d.ts.map +1 -1
  41. package/dist/stages/compose/OfflineAudioMixer.d.ts.map +1 -1
  42. package/dist/stages/compose/OfflineAudioMixer.js +3 -1
  43. package/dist/stages/compose/OfflineAudioMixer.js.map +1 -1
  44. package/dist/stages/demux/MP4IndexParser.d.ts +1 -0
  45. package/dist/stages/demux/MP4IndexParser.d.ts.map +1 -1
  46. package/dist/stages/demux/MP4IndexParser.js +20 -10
  47. package/dist/stages/demux/MP4IndexParser.js.map +1 -1
  48. package/dist/stages/load/ResourceLoader.d.ts +3 -1
  49. package/dist/stages/load/ResourceLoader.d.ts.map +1 -1
  50. package/dist/stages/load/ResourceLoader.js +45 -4
  51. package/dist/stages/load/ResourceLoader.js.map +1 -1
  52. package/dist/stages/load/TaskManager.d.ts +7 -1
  53. package/dist/stages/load/TaskManager.d.ts.map +1 -1
  54. package/dist/stages/load/TaskManager.js +40 -2
  55. package/dist/stages/load/TaskManager.js.map +1 -1
  56. package/dist/utils/errors.d.ts +27 -0
  57. package/dist/utils/errors.d.ts.map +1 -1
  58. package/dist/utils/errors.js +32 -0
  59. package/dist/utils/errors.js.map +1 -1
  60. package/dist/workers/stages/compose/{video-compose.worker.DM_bsOY8.js → video-compose.worker.Ckk8AtaQ.js} +51 -21
  61. package/dist/workers/stages/compose/{video-compose.worker.DM_bsOY8.js.map → video-compose.worker.Ckk8AtaQ.js.map} +1 -1
  62. package/dist/workers/worker-manifest.json +1 -1
  63. package/package.json +1 -1
@@ -9,4 +9,31 @@ export declare class WaiterReplacedError extends Error {
9
9
  readonly clipId: string;
10
10
  constructor(clipId: string);
11
11
  }
12
+ /**
13
+ * Error thrown when reading an empty or incomplete OPFS file
14
+ * Usually indicates a race condition between write and read operations
15
+ */
16
+ export declare class EmptyStreamError extends Error {
17
+ readonly resourceId: string;
18
+ readonly fileOffset: number;
19
+ constructor(resourceId: string, fileOffset: number);
20
+ }
21
+ /**
22
+ * Error thrown when a cached resource file is corrupted or incomplete
23
+ */
24
+ export declare class ResourceCorruptedError extends Error {
25
+ readonly resourceId: string;
26
+ readonly reason: string;
27
+ constructor(resourceId: string, reason: string);
28
+ }
29
+ /**
30
+ * Error thrown when OPFS quota is exceeded
31
+ * Used for project-level LRU eviction coordination
32
+ */
33
+ export declare class OPFSQuotaExceededError extends Error {
34
+ readonly projectId: string;
35
+ readonly prefix: string;
36
+ readonly retryable: boolean;
37
+ constructor(projectId: string, prefix: string, retryable: boolean);
38
+ }
12
39
  //# sourceMappingURL=errors.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;GAGG;AACH,qBAAa,mBAAoB,SAAQ,KAAK;aAChB,MAAM,EAAE,MAAM;gBAAd,MAAM,EAAE,MAAM;CAI3C"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;GAGG;AACH,qBAAa,mBAAoB,SAAQ,KAAK;aAChB,MAAM,EAAE,MAAM;gBAAd,MAAM,EAAE,MAAM;CAI3C;AAED;;;GAGG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;aAEvB,UAAU,EAAE,MAAM;aAClB,UAAU,EAAE,MAAM;gBADlB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM;CAQrC;AAED;;GAEG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;aAE7B,UAAU,EAAE,MAAM;aAClB,MAAM,EAAE,MAAM;gBADd,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM;CAKjC;AAED;;;GAGG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;aAE7B,SAAS,EAAE,MAAM;aACjB,MAAM,EAAE,MAAM;aACd,SAAS,EAAE,OAAO;gBAFlB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,OAAO;CAQrC"}
@@ -5,7 +5,39 @@ class WaiterReplacedError extends Error {
5
5
  this.name = "WaiterReplacedError";
6
6
  }
7
7
  }
8
+ class EmptyStreamError extends Error {
9
+ constructor(resourceId, fileOffset) {
10
+ super(
11
+ `Empty stream received for resource ${resourceId}. File offset: ${fileOffset}. This indicates the file is being written or is corrupted.`
12
+ );
13
+ this.resourceId = resourceId;
14
+ this.fileOffset = fileOffset;
15
+ this.name = "EmptyStreamError";
16
+ }
17
+ }
18
+ class ResourceCorruptedError extends Error {
19
+ constructor(resourceId, reason) {
20
+ super(`Resource ${resourceId} is corrupted: ${reason}`);
21
+ this.resourceId = resourceId;
22
+ this.reason = reason;
23
+ this.name = "ResourceCorruptedError";
24
+ }
25
+ }
26
+ class OPFSQuotaExceededError extends Error {
27
+ constructor(projectId, prefix, retryable) {
28
+ super(
29
+ `OPFS quota exceeded for ${prefix}-${projectId}. ` + (retryable ? "Old projects evicted, please retry." : "No space available.")
30
+ );
31
+ this.projectId = projectId;
32
+ this.prefix = prefix;
33
+ this.retryable = retryable;
34
+ this.name = "OPFSQuotaExceededError";
35
+ }
36
+ }
8
37
  export {
38
+ EmptyStreamError,
39
+ OPFSQuotaExceededError,
40
+ ResourceCorruptedError,
9
41
  WaiterReplacedError
10
42
  };
11
43
  //# sourceMappingURL=errors.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sources":["../../src/utils/errors.ts"],"sourcesContent":["/**\n * Custom error types for Meframe\n */\n\n/**\n * Error thrown when a clip ready waiter is replaced by a newer one\n * This happens during rapid seeks and should be ignored by callers\n */\nexport class WaiterReplacedError extends Error {\n constructor(public readonly clipId: string) {\n super(`Waiter for clip ${clipId} was replaced by a newer waiter`);\n this.name = 'WaiterReplacedError';\n }\n}\n"],"names":[],"mappings":"AAQO,MAAM,4BAA4B,MAAM;AAAA,EAC7C,YAA4B,QAAgB;AAC1C,UAAM,mBAAmB,MAAM,iCAAiC;AADtC,SAAA,SAAA;AAE1B,SAAK,OAAO;AAAA,EACd;AACF;"}
1
+ {"version":3,"file":"errors.js","sources":["../../src/utils/errors.ts"],"sourcesContent":["/**\n * Custom error types for Meframe\n */\n\n/**\n * Error thrown when a clip ready waiter is replaced by a newer one\n * This happens during rapid seeks and should be ignored by callers\n */\nexport class WaiterReplacedError extends Error {\n constructor(public readonly clipId: string) {\n super(`Waiter for clip ${clipId} was replaced by a newer waiter`);\n this.name = 'WaiterReplacedError';\n }\n}\n\n/**\n * Error thrown when reading an empty or incomplete OPFS file\n * Usually indicates a race condition between write and read operations\n */\nexport class EmptyStreamError extends Error {\n constructor(\n public readonly resourceId: string,\n public readonly fileOffset: number\n ) {\n super(\n `Empty stream received for resource ${resourceId}. ` +\n `File offset: ${fileOffset}. This indicates the file is being written or is corrupted.`\n );\n this.name = 'EmptyStreamError';\n }\n}\n\n/**\n * Error thrown when a cached resource file is corrupted or incomplete\n */\nexport class ResourceCorruptedError extends Error {\n constructor(\n public readonly resourceId: string,\n public readonly reason: string\n ) {\n super(`Resource ${resourceId} is corrupted: ${reason}`);\n this.name = 'ResourceCorruptedError';\n }\n}\n\n/**\n * Error thrown when OPFS quota is exceeded\n * Used for project-level LRU eviction coordination\n */\nexport class OPFSQuotaExceededError extends Error {\n constructor(\n public readonly projectId: string,\n public readonly prefix: string,\n public readonly retryable: boolean\n ) {\n super(\n `OPFS quota exceeded for ${prefix}-${projectId}. ` +\n (retryable ? 'Old projects evicted, please retry.' : 'No space available.')\n );\n this.name = 'OPFSQuotaExceededError';\n }\n}\n"],"names":[],"mappings":"AAQO,MAAM,4BAA4B,MAAM;AAAA,EAC7C,YAA4B,QAAgB;AAC1C,UAAM,mBAAmB,MAAM,iCAAiC;AADtC,SAAA,SAAA;AAE1B,SAAK,OAAO;AAAA,EACd;AACF;AAMO,MAAM,yBAAyB,MAAM;AAAA,EAC1C,YACkB,YACA,YAChB;AACA;AAAA,MACE,sCAAsC,UAAU,kBAC9B,UAAU;AAAA,IAAA;AALd,SAAA,aAAA;AACA,SAAA,aAAA;AAMhB,SAAK,OAAO;AAAA,EACd;AACF;AAKO,MAAM,+BAA+B,MAAM;AAAA,EAChD,YACkB,YACA,QAChB;AACA,UAAM,YAAY,UAAU,kBAAkB,MAAM,EAAE;AAHtC,SAAA,aAAA;AACA,SAAA,SAAA;AAGhB,SAAK,OAAO;AAAA,EACd;AACF;AAMO,MAAM,+BAA+B,MAAM;AAAA,EAChD,YACkB,WACA,QACA,WAChB;AACA;AAAA,MACE,2BAA2B,MAAM,IAAI,SAAS,QAC3C,YAAY,wCAAwC;AAAA,IAAA;AANzC,SAAA,YAAA;AACA,SAAA,SAAA;AACA,SAAA,YAAA;AAMhB,SAAK,OAAO;AAAA,EACd;AACF;"}
@@ -1849,29 +1849,59 @@ class FrameRateConverter {
1849
1849
  * Flush remaining target frames at end of stream
1850
1850
  */
1851
1851
  flushRemainingFrames(controller) {
1852
- while (this.sourceFrameBuffer.length > 0) {
1852
+ let lastFrame = null;
1853
+ while (this.sourceFrameBuffer.length > 0 && this.targetFrameTimeUs < this.clipDurationUs) {
1853
1854
  const closestFrame = this.findClosestFrame(this.targetFrameTimeUs);
1854
- if (!closestFrame) {
1855
- break;
1856
- }
1857
- if (this.targetFrameTimeUs >= this.clipDurationUs) {
1858
- break;
1859
- }
1860
- try {
1861
- const targetFrame = new VideoFrame(closestFrame, {
1862
- timestamp: this.targetFrameTimeUs,
1863
- duration: this.frameDurationUs
1864
- });
1865
- controller.enqueue(targetFrame);
1866
- this.cleanupOldFrames(this.targetFrameTimeUs);
1867
- this.targetFrameIndex++;
1868
- this.targetFrameTimeUs = this.targetFrameIndex * this.frameDurationUs;
1869
- } catch (_error) {
1870
- console.error("[FrameRateConverter] Failed to create target frame in flush:", _error);
1871
- break;
1872
- }
1855
+ if (!closestFrame) break;
1856
+ if (!this.outputTargetFrame(closestFrame, controller)) break;
1857
+ lastFrame = closestFrame;
1858
+ }
1859
+ if (lastFrame && this.targetFrameTimeUs < this.clipDurationUs) {
1860
+ this.padWithLastFrame(lastFrame, controller);
1861
+ }
1862
+ this.cleanupAllFrames(lastFrame);
1863
+ }
1864
+ /**
1865
+ * Output a single target frame
1866
+ */
1867
+ outputTargetFrame(sourceFrame, controller) {
1868
+ try {
1869
+ const targetFrame = new VideoFrame(sourceFrame, {
1870
+ timestamp: this.targetFrameTimeUs,
1871
+ duration: this.frameDurationUs
1872
+ });
1873
+ controller.enqueue(targetFrame);
1874
+ this.targetFrameIndex++;
1875
+ this.targetFrameTimeUs = this.targetFrameIndex * this.frameDurationUs;
1876
+ return true;
1877
+ } catch (error) {
1878
+ console.error("[FrameRateConverter] Failed to create target frame:", error);
1879
+ return false;
1873
1880
  }
1881
+ }
1882
+ /**
1883
+ * Pad remaining duration with last frame (freeze frame effect)
1884
+ */
1885
+ padWithLastFrame(lastFrame, controller) {
1886
+ const index = this.sourceFrameBuffer.indexOf(lastFrame);
1887
+ if (index >= 0) {
1888
+ this.sourceFrameBuffer.splice(index, 1);
1889
+ }
1890
+ this.cleanupAllFrames(null);
1891
+ while (this.targetFrameTimeUs < this.clipDurationUs) {
1892
+ if (!this.outputTargetFrame(lastFrame, controller)) break;
1893
+ }
1894
+ try {
1895
+ lastFrame.close();
1896
+ } catch {
1897
+ }
1898
+ }
1899
+ /**
1900
+ * Clean up all buffered frames (except the specified frame to keep)
1901
+ */
1902
+ cleanupAllFrames(keepFrame) {
1874
1903
  for (const frame of this.sourceFrameBuffer) {
1904
+ if (frame === keepFrame) continue;
1875
1905
  try {
1876
1906
  frame.close();
1877
1907
  } catch {
@@ -2402,4 +2432,4 @@ export {
2402
2432
  VideoComposeWorker,
2403
2433
  videoCompose_worker as default
2404
2434
  };
2405
- //# sourceMappingURL=video-compose.worker.DM_bsOY8.js.map
2435
+ //# sourceMappingURL=video-compose.worker.Ckk8AtaQ.js.map