@meframe/core 0.0.2 → 0.0.4

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 (193) hide show
  1. package/dist/Meframe.d.ts.map +1 -1
  2. package/dist/Meframe.js +6 -4
  3. package/dist/Meframe.js.map +1 -1
  4. package/dist/cache/CacheManager.d.ts +2 -2
  5. package/dist/cache/CacheManager.d.ts.map +1 -1
  6. package/dist/cache/CacheManager.js +4 -3
  7. package/dist/cache/CacheManager.js.map +1 -1
  8. package/dist/cache/l1/VideoL1Cache.d.ts +2 -2
  9. package/dist/cache/l1/VideoL1Cache.d.ts.map +1 -1
  10. package/dist/cache/l1/VideoL1Cache.js +13 -8
  11. package/dist/cache/l1/VideoL1Cache.js.map +1 -1
  12. package/dist/config/defaults.d.ts.map +1 -1
  13. package/dist/config/defaults.js +3 -1
  14. package/dist/config/defaults.js.map +1 -1
  15. package/dist/config/types.d.ts +6 -0
  16. package/dist/config/types.d.ts.map +1 -1
  17. package/dist/controllers/PlaybackController.d.ts +7 -8
  18. package/dist/controllers/PlaybackController.d.ts.map +1 -1
  19. package/dist/controllers/PlaybackController.js +56 -76
  20. package/dist/controllers/PlaybackController.js.map +1 -1
  21. package/dist/controllers/types.d.ts +2 -3
  22. package/dist/controllers/types.d.ts.map +1 -1
  23. package/dist/event/events.d.ts +1 -4
  24. package/dist/event/events.d.ts.map +1 -1
  25. package/dist/event/events.js.map +1 -1
  26. package/dist/model/CompositionModel.d.ts +1 -0
  27. package/dist/model/CompositionModel.d.ts.map +1 -1
  28. package/dist/model/CompositionModel.js +2 -0
  29. package/dist/model/CompositionModel.js.map +1 -1
  30. package/dist/model/patch.d.ts +6 -2
  31. package/dist/model/patch.d.ts.map +1 -1
  32. package/dist/model/patch.js +76 -2
  33. package/dist/model/patch.js.map +1 -1
  34. package/dist/model/types.d.ts +1 -0
  35. package/dist/model/types.d.ts.map +1 -1
  36. package/dist/orchestrator/CompositionPlanner.d.ts +8 -7
  37. package/dist/orchestrator/CompositionPlanner.d.ts.map +1 -1
  38. package/dist/orchestrator/CompositionPlanner.js +33 -56
  39. package/dist/orchestrator/CompositionPlanner.js.map +1 -1
  40. package/dist/orchestrator/Orchestrator.d.ts +0 -1
  41. package/dist/orchestrator/Orchestrator.d.ts.map +1 -1
  42. package/dist/orchestrator/Orchestrator.js +40 -19
  43. package/dist/orchestrator/Orchestrator.js.map +1 -1
  44. package/dist/orchestrator/VideoClipSession.d.ts +3 -5
  45. package/dist/orchestrator/VideoClipSession.d.ts.map +1 -1
  46. package/dist/orchestrator/VideoClipSession.js +66 -69
  47. package/dist/orchestrator/VideoClipSession.js.map +1 -1
  48. package/dist/orchestrator/types.d.ts +2 -0
  49. package/dist/orchestrator/types.d.ts.map +1 -1
  50. package/dist/stages/compose/GlobalAudioSession.d.ts +6 -0
  51. package/dist/stages/compose/GlobalAudioSession.d.ts.map +1 -1
  52. package/dist/stages/compose/GlobalAudioSession.js +17 -1
  53. package/dist/stages/compose/GlobalAudioSession.js.map +1 -1
  54. package/dist/stages/compose/types.d.ts +2 -1
  55. package/dist/stages/compose/types.d.ts.map +1 -1
  56. package/dist/stages/demux/MP4Demuxer.d.ts +0 -1
  57. package/dist/stages/demux/MP4Demuxer.d.ts.map +1 -1
  58. package/dist/stages/load/ResourceLoader.d.ts +22 -1
  59. package/dist/stages/load/ResourceLoader.d.ts.map +1 -1
  60. package/dist/stages/load/ResourceLoader.js +71 -25
  61. package/dist/stages/load/ResourceLoader.js.map +1 -1
  62. package/dist/stages/load/TaskManager.d.ts +1 -1
  63. package/dist/stages/load/TaskManager.d.ts.map +1 -1
  64. package/dist/stages/load/TaskManager.js +3 -2
  65. package/dist/stages/load/TaskManager.js.map +1 -1
  66. package/dist/stages/load/types.d.ts +2 -0
  67. package/dist/stages/load/types.d.ts.map +1 -1
  68. package/dist/utils/time-utils.d.ts +3 -2
  69. package/dist/utils/time-utils.d.ts.map +1 -1
  70. package/dist/utils/time-utils.js +2 -1
  71. package/dist/utils/time-utils.js.map +1 -1
  72. package/dist/vite-plugin.d.ts +5 -3
  73. package/dist/vite-plugin.d.ts.map +1 -1
  74. package/dist/vite-plugin.js +109 -52
  75. package/dist/vite-plugin.js.map +1 -1
  76. package/dist/worker/WorkerPool.d.ts +9 -0
  77. package/dist/worker/WorkerPool.d.ts.map +1 -1
  78. package/dist/worker/WorkerPool.js +32 -5
  79. package/dist/worker/WorkerPool.js.map +1 -1
  80. package/dist/{stages/demux → workers}/MP4Demuxer.js +4 -13
  81. package/dist/workers/MP4Demuxer.js.map +1 -0
  82. package/dist/workers/WorkerChannel.js +486 -0
  83. package/dist/workers/WorkerChannel.js.map +1 -0
  84. package/dist/{assets/video-demux.worker-D019I7GQ.js → workers/mp4box.all.js} +4 -912
  85. package/dist/workers/mp4box.all.js.map +1 -0
  86. package/dist/{assets/audio-compose.worker-nGVvHD5Q.js → workers/stages/compose/audio-compose.worker.js} +7 -481
  87. package/dist/workers/stages/compose/audio-compose.worker.js.map +1 -0
  88. package/dist/{assets/video-compose.worker-DPzsC21d.js → workers/stages/compose/video-compose.worker.js} +120 -562
  89. package/dist/workers/stages/compose/video-compose.worker.js.map +1 -0
  90. package/dist/{assets/decode.worker-DpWHsc7R.js → workers/stages/decode/decode.worker.js} +7 -481
  91. package/dist/workers/stages/decode/decode.worker.js.map +1 -0
  92. package/dist/{stages → workers/stages}/demux/audio-demux.worker.js +184 -4
  93. package/dist/workers/stages/demux/audio-demux.worker.js.map +1 -0
  94. package/dist/{stages → workers/stages}/demux/video-demux.worker.js +2 -3
  95. package/dist/workers/stages/demux/video-demux.worker.js.map +1 -0
  96. package/dist/{stages → workers/stages}/encode/encode.worker.js +238 -4
  97. package/dist/workers/stages/encode/encode.worker.js.map +1 -0
  98. package/dist/{stages/mux/MP4Muxer.js → workers/stages/mux/mux.worker.js} +244 -5
  99. package/dist/workers/stages/mux/mux.worker.js.map +1 -0
  100. package/package.json +21 -21
  101. package/dist/assets/audio-compose.worker-nGVvHD5Q.js.map +0 -1
  102. package/dist/assets/audio-demux.worker-xwWBtbAe.js +0 -8299
  103. package/dist/assets/audio-demux.worker-xwWBtbAe.js.map +0 -1
  104. package/dist/assets/decode.worker-DpWHsc7R.js.map +0 -1
  105. package/dist/assets/encode.worker-nfOb3kw6.js +0 -1026
  106. package/dist/assets/encode.worker-nfOb3kw6.js.map +0 -1
  107. package/dist/assets/mux.worker-uEMQY066.js +0 -8019
  108. package/dist/assets/mux.worker-uEMQY066.js.map +0 -1
  109. package/dist/assets/video-compose.worker-DPzsC21d.js.map +0 -1
  110. package/dist/assets/video-demux.worker-D019I7GQ.js.map +0 -1
  111. package/dist/controllers/PreviewHandle.d.ts +0 -25
  112. package/dist/controllers/PreviewHandle.d.ts.map +0 -1
  113. package/dist/controllers/PreviewHandle.js +0 -45
  114. package/dist/controllers/PreviewHandle.js.map +0 -1
  115. package/dist/model/dirty-range.js +0 -220
  116. package/dist/model/dirty-range.js.map +0 -1
  117. package/dist/model/types.js +0 -5
  118. package/dist/model/types.js.map +0 -1
  119. package/dist/plugins/BackpressureMonitor.js +0 -62
  120. package/dist/plugins/BackpressureMonitor.js.map +0 -1
  121. package/dist/stages/compose/AudioDucker.js +0 -161
  122. package/dist/stages/compose/AudioDucker.js.map +0 -1
  123. package/dist/stages/compose/AudioMixer.js +0 -373
  124. package/dist/stages/compose/AudioMixer.js.map +0 -1
  125. package/dist/stages/compose/FilterProcessor.js +0 -226
  126. package/dist/stages/compose/FilterProcessor.js.map +0 -1
  127. package/dist/stages/compose/LayerRenderer.js +0 -215
  128. package/dist/stages/compose/LayerRenderer.js.map +0 -1
  129. package/dist/stages/compose/TransitionProcessor.js +0 -189
  130. package/dist/stages/compose/TransitionProcessor.js.map +0 -1
  131. package/dist/stages/compose/VideoComposer.js +0 -186
  132. package/dist/stages/compose/VideoComposer.js.map +0 -1
  133. package/dist/stages/compose/audio-compose.worker.d.ts +0 -79
  134. package/dist/stages/compose/audio-compose.worker.d.ts.map +0 -1
  135. package/dist/stages/compose/audio-compose.worker.js +0 -540
  136. package/dist/stages/compose/audio-compose.worker.js.map +0 -1
  137. package/dist/stages/compose/audio-compose.worker2.js +0 -5
  138. package/dist/stages/compose/audio-compose.worker2.js.map +0 -1
  139. package/dist/stages/compose/video-compose.worker.d.ts +0 -60
  140. package/dist/stages/compose/video-compose.worker.d.ts.map +0 -1
  141. package/dist/stages/compose/video-compose.worker.js +0 -379
  142. package/dist/stages/compose/video-compose.worker.js.map +0 -1
  143. package/dist/stages/compose/video-compose.worker2.js +0 -5
  144. package/dist/stages/compose/video-compose.worker2.js.map +0 -1
  145. package/dist/stages/decode/AudioChunkDecoder.js +0 -82
  146. package/dist/stages/decode/AudioChunkDecoder.js.map +0 -1
  147. package/dist/stages/decode/BaseDecoder.js +0 -130
  148. package/dist/stages/decode/BaseDecoder.js.map +0 -1
  149. package/dist/stages/decode/VideoChunkDecoder.js +0 -199
  150. package/dist/stages/decode/VideoChunkDecoder.js.map +0 -1
  151. package/dist/stages/decode/decode.worker.d.ts +0 -70
  152. package/dist/stages/decode/decode.worker.d.ts.map +0 -1
  153. package/dist/stages/decode/decode.worker.js +0 -423
  154. package/dist/stages/decode/decode.worker.js.map +0 -1
  155. package/dist/stages/decode/decode.worker2.js +0 -5
  156. package/dist/stages/decode/decode.worker2.js.map +0 -1
  157. package/dist/stages/demux/MP3FrameParser.js +0 -186
  158. package/dist/stages/demux/MP3FrameParser.js.map +0 -1
  159. package/dist/stages/demux/MP4Demuxer.js.map +0 -1
  160. package/dist/stages/demux/audio-demux.worker.d.ts +0 -51
  161. package/dist/stages/demux/audio-demux.worker.d.ts.map +0 -1
  162. package/dist/stages/demux/audio-demux.worker.js.map +0 -1
  163. package/dist/stages/demux/audio-demux.worker2.js +0 -5
  164. package/dist/stages/demux/audio-demux.worker2.js.map +0 -1
  165. package/dist/stages/demux/video-demux.worker.d.ts +0 -51
  166. package/dist/stages/demux/video-demux.worker.d.ts.map +0 -1
  167. package/dist/stages/demux/video-demux.worker.js.map +0 -1
  168. package/dist/stages/demux/video-demux.worker2.js +0 -5
  169. package/dist/stages/demux/video-demux.worker2.js.map +0 -1
  170. package/dist/stages/encode/AudioChunkEncoder.js +0 -37
  171. package/dist/stages/encode/AudioChunkEncoder.js.map +0 -1
  172. package/dist/stages/encode/BaseEncoder.js +0 -164
  173. package/dist/stages/encode/BaseEncoder.js.map +0 -1
  174. package/dist/stages/encode/VideoChunkEncoder.js +0 -50
  175. package/dist/stages/encode/VideoChunkEncoder.js.map +0 -1
  176. package/dist/stages/encode/encode.worker.d.ts +0 -3
  177. package/dist/stages/encode/encode.worker.d.ts.map +0 -1
  178. package/dist/stages/encode/encode.worker.js.map +0 -1
  179. package/dist/stages/encode/encode.worker2.js +0 -5
  180. package/dist/stages/encode/encode.worker2.js.map +0 -1
  181. package/dist/stages/mux/MP4Muxer.js.map +0 -1
  182. package/dist/stages/mux/mux.worker.d.ts +0 -65
  183. package/dist/stages/mux/mux.worker.d.ts.map +0 -1
  184. package/dist/stages/mux/mux.worker.js +0 -219
  185. package/dist/stages/mux/mux.worker.js.map +0 -1
  186. package/dist/stages/mux/mux.worker2.js +0 -5
  187. package/dist/stages/mux/mux.worker2.js.map +0 -1
  188. package/dist/stages/mux/utils.js +0 -34
  189. package/dist/stages/mux/utils.js.map +0 -1
  190. package/dist/worker/worker-registry.d.ts +0 -12
  191. package/dist/worker/worker-registry.d.ts.map +0 -1
  192. package/dist/worker/worker-registry.js +0 -20
  193. package/dist/worker/worker-registry.js.map +0 -1
@@ -1,6 +1,33 @@
1
- import "../../node_modules/.pnpm/mp4box@0.5.4/node_modules/mp4box/dist/mp4box.all.js";
2
- import { calculateTimescale, parseCodecString, usToTimescale } from "./utils.js";
3
- import { __exports as mp4box_all } from "../../_virtual/mp4box.all.js";
1
+ import { W as WorkerChannel, a as WorkerMessageType, b as WorkerState } from "../../WorkerChannel.js";
2
+ import { m as mp4box_all } from "../../mp4box.all.js";
3
+ function usToTimescale(microseconds, timescale) {
4
+ return Math.round(microseconds * timescale / 1e6);
5
+ }
6
+ function calculateTimescale(frameRate) {
7
+ if (!frameRate) return 9e4;
8
+ const commonRates = {
9
+ 24: 24e3,
10
+ 25: 25e3,
11
+ 30: 3e4,
12
+ 50: 5e4,
13
+ 60: 6e4
14
+ };
15
+ return commonRates[Math.round(frameRate)] || 9e4;
16
+ }
17
+ function parseCodecString(codec) {
18
+ const parts = codec.split(".");
19
+ const result = { codec: parts[0] };
20
+ if (parts[0] === "avc1" || parts[0] === "hev1" || parts[0] === "hvc1") {
21
+ if (parts[1]) {
22
+ result.profile = parts[1].substring(0, 2);
23
+ result.level = parts[1].substring(4, 6);
24
+ }
25
+ } else if (parts[0] === "mp4a") {
26
+ if (parts[1]) result.objectType = parts[1];
27
+ if (parts[2]) result.audioObjectType = parts[2];
28
+ }
29
+ return result;
30
+ }
4
31
  class MP4Muxer {
5
32
  mp4boxFile;
6
33
  tracks = /* @__PURE__ */ new Map();
@@ -256,7 +283,219 @@ class MP4Muxer {
256
283
  this.outputChunks = [];
257
284
  }
258
285
  }
286
+ class MuxWorkerImpl {
287
+ channel;
288
+ muxer = null;
289
+ config = null;
290
+ constructor() {
291
+ this.channel = new WorkerChannel(self, {
292
+ name: "MuxWorker",
293
+ timeout: 6e4
294
+ // 60s for export operations
295
+ });
296
+ this.setupHandlers();
297
+ }
298
+ setupHandlers() {
299
+ this.channel.registerHandler("configure", this.handleConfigure.bind(this));
300
+ this.channel.registerHandler("connect", this.handleUnifiedConnect.bind(this));
301
+ this.channel.registerHandler("write_video_chunk", this.handleWriteVideoChunk.bind(this));
302
+ this.channel.registerHandler("write_audio_chunk", this.handleWriteAudioChunk.bind(this));
303
+ this.channel.registerHandler("flush", this.handleFlush.bind(this));
304
+ this.channel.registerHandler("finalize", this.handleFinalize.bind(this));
305
+ this.channel.registerHandler("get_stats", this.handleGetStats.bind(this));
306
+ this.channel.registerHandler(WorkerMessageType.Dispose, this.handleDispose.bind(this));
307
+ this.channel.receiveStream(this.handleInputStream.bind(this));
308
+ }
309
+ /**
310
+ * Unified connect handler used by stream pipeline
311
+ */
312
+ async handleUnifiedConnect(_payload) {
313
+ return { success: true };
314
+ }
315
+ /**
316
+ * Connect to encoder worker to receive encoded chunks
317
+ */
318
+ // private async handleConnectEncoder(_payload: {
319
+ // port: MessagePort;
320
+ // }): Promise<{ success: boolean }> {
321
+ // // Store the port for receiving encoded chunks
322
+ // // The actual stream handling is done via receiveStream in handleInputStream
323
+ // // This connection allows direct communication with the encoder worker
324
+ // return { success: true };
325
+ // }
326
+ /**
327
+ * Configure muxer with container settings
328
+ * @param payload.config - Muxer configuration including tracks and output format
329
+ * @param payload.initial - If true, initialize worker state; otherwise just update config
330
+ */
331
+ async handleConfigure(payload) {
332
+ const { config, initial = false } = payload;
333
+ try {
334
+ if (initial) {
335
+ this.channel.state = WorkerState.Ready;
336
+ if (this.muxer) {
337
+ this.muxer.destroy();
338
+ }
339
+ this.config = config;
340
+ this.muxer = new MP4Muxer(config);
341
+ const trackCount = (config.video ? 1 : 0) + (config.audio ? 1 : 0);
342
+ this.channel.notify("configured", {
343
+ container: config.container,
344
+ hasVideo: !!config.video,
345
+ hasAudio: !!config.audio,
346
+ fragmented: !!config.mp4?.fragmented,
347
+ trackCount
348
+ });
349
+ return { success: true, tracks: trackCount };
350
+ } else {
351
+ if (!this.muxer) {
352
+ throw {
353
+ code: "NOT_INITIALIZED",
354
+ message: "Muxer not initialized. Call configure with initial=true first"
355
+ };
356
+ }
357
+ this.config = { ...this.config, ...config };
358
+ return { success: true };
359
+ }
360
+ } catch (error) {
361
+ throw {
362
+ code: error.code || "CONFIG_ERROR",
363
+ message: error.message
364
+ };
365
+ }
366
+ }
367
+ /**
368
+ * Write single video chunk
369
+ */
370
+ async handleWriteVideoChunk(payload) {
371
+ if (!this.muxer) {
372
+ throw {
373
+ code: "NOT_INITIALIZED",
374
+ message: "Muxer not initialized"
375
+ };
376
+ }
377
+ this.muxer.writeVideoChunk(payload.chunk, payload.trackId);
378
+ return { bytesWritten: this.muxer.totalBytesWritten };
379
+ }
380
+ /**
381
+ * Write single audio chunk
382
+ */
383
+ async handleWriteAudioChunk(payload) {
384
+ if (!this.muxer) {
385
+ throw {
386
+ code: "NOT_INITIALIZED",
387
+ message: "Muxer not initialized"
388
+ };
389
+ }
390
+ this.muxer.writeAudioChunk(payload.chunk, payload.trackId);
391
+ return { bytesWritten: this.muxer.totalBytesWritten };
392
+ }
393
+ /**
394
+ * Handle input stream from CacheManager (L2 encoded chunks)
395
+ * This is the main export path where CacheManager sends encoded chunks
396
+ */
397
+ async handleInputStream(stream, metadata) {
398
+ if (!this.muxer) {
399
+ throw new Error("Muxer not configured");
400
+ }
401
+ const reader = stream.getReader();
402
+ let chunksProcessed = 0;
403
+ try {
404
+ this.channel.state = WorkerState.Processing;
405
+ while (true) {
406
+ const { done, value } = await reader.read();
407
+ if (done) break;
408
+ const isVideoChunk = metadata?.type === "video" || value.type === "key" || value.type === "delta";
409
+ if (isVideoChunk) {
410
+ this.muxer.writeVideoChunk(value, metadata?.trackId || 1);
411
+ } else {
412
+ this.muxer.writeAudioChunk(value, metadata?.trackId || 2);
413
+ }
414
+ chunksProcessed++;
415
+ if (chunksProcessed % 100 === 0) {
416
+ this.channel.notify("mux_progress", {
417
+ chunksProcessed,
418
+ bytesWritten: this.muxer.totalBytesWritten
419
+ });
420
+ }
421
+ }
422
+ this.muxer.flush();
423
+ this.channel.state = WorkerState.Ready;
424
+ this.channel.notify("mux_complete", {
425
+ chunksProcessed,
426
+ bytesWritten: this.muxer.totalBytesWritten
427
+ });
428
+ } finally {
429
+ reader.releaseLock();
430
+ }
431
+ }
432
+ /**
433
+ * Flush pending samples
434
+ */
435
+ async handleFlush() {
436
+ if (!this.muxer) {
437
+ throw {
438
+ code: "NOT_INITIALIZED",
439
+ message: "Muxer not initialized"
440
+ };
441
+ }
442
+ this.muxer.flush();
443
+ return { success: true };
444
+ }
445
+ /**
446
+ * Finalize muxing and get output
447
+ * This completes the export process
448
+ */
449
+ async handleFinalize() {
450
+ if (!this.muxer) {
451
+ throw {
452
+ code: "NOT_INITIALIZED",
453
+ message: "Muxer not initialized"
454
+ };
455
+ }
456
+ const blob = this.muxer.finalize();
457
+ this.channel.notify("export_done", {
458
+ blob,
459
+ totalBytes: blob.size
460
+ });
461
+ return {
462
+ success: true,
463
+ blob,
464
+ totalBytes: blob.size
465
+ };
466
+ }
467
+ /**
468
+ * Get muxer statistics
469
+ */
470
+ async handleGetStats() {
471
+ if (!this.muxer) {
472
+ return { state: this.channel.state };
473
+ }
474
+ return {
475
+ bytesWritten: this.muxer.totalBytesWritten,
476
+ chunksCount: this.muxer.outputChunks.length,
477
+ isFinalized: this.muxer.isFinalized,
478
+ state: this.channel.state
479
+ };
480
+ }
481
+ /**
482
+ * Dispose worker and cleanup resources
483
+ */
484
+ async handleDispose() {
485
+ this.muxer?.destroy();
486
+ this.muxer = null;
487
+ this.config = null;
488
+ this.channel.state = WorkerState.Disposed;
489
+ return { success: true };
490
+ }
491
+ }
492
+ const worker = new MuxWorkerImpl();
493
+ self.addEventListener("beforeunload", () => {
494
+ worker["handleDispose"]();
495
+ });
496
+ const mux_worker = null;
259
497
  export {
260
- MP4Muxer
498
+ MuxWorkerImpl,
499
+ mux_worker as default
261
500
  };
262
- //# sourceMappingURL=MP4Muxer.js.map
501
+ //# sourceMappingURL=mux.worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mux.worker.js","sources":["../../../../src/stages/mux/utils.ts","../../../../src/stages/mux/MP4Muxer.ts","../../../../src/stages/mux/mux.worker.ts"],"sourcesContent":["import type { EncodedChunkData, MuxSample } from './types';\n\n/**\n * Convert WebCodecs EncodedChunk to MuxSample\n */\nexport function encodedChunkToMuxSample(data: EncodedChunkData): MuxSample {\n const { chunk, trackId, type } = data;\n\n // Create buffer for chunk data\n const buffer = new Uint8Array(chunk.byteLength);\n chunk.copyTo(buffer);\n\n return {\n trackId,\n data: buffer,\n timestamp: chunk.timestamp,\n duration: chunk.duration || 0,\n isKeyFrame: type === 'video' ? (chunk as EncodedVideoChunk).type === 'key' : true, // Audio samples are always \"key frames\"\n };\n}\n\n/**\n * Convert microseconds to timescale units\n */\nexport function usToTimescale(microseconds: number, timescale: number): number {\n return Math.round((microseconds * timescale) / 1_000_000);\n}\n\n/**\n * Convert timescale units to microseconds\n */\nexport function timescaleToUs(units: number, timescale: number): number {\n return Math.round((units * 1_000_000) / timescale);\n}\n\n/**\n * Calculate optimal timescale for given frame rate\n */\nexport function calculateTimescale(frameRate?: number): number {\n if (!frameRate) return 90000; // Default for video\n\n // Common frame rates and their optimal timescales\n const commonRates: Record<number, number> = {\n 24: 24000,\n 25: 25000,\n 30: 30000,\n 50: 50000,\n 60: 60000,\n };\n\n return commonRates[Math.round(frameRate)] || 90000;\n}\n\n/**\n * Parse codec string to extract codec parameters\n * e.g., 'avc1.42E01E' -> { codec: 'avc1', profile: '42', level: '1E' }\n */\nexport function parseCodecString(codec: string): {\n codec: string;\n profile?: string;\n level?: string;\n} {\n const parts = codec.split('.');\n const result: any = { codec: parts[0] };\n\n if (parts[0] === 'avc1' || parts[0] === 'hev1' || parts[0] === 'hvc1') {\n // H.264/H.265 codec string format\n if (parts[1]) {\n result.profile = parts[1].substring(0, 2);\n result.level = parts[1].substring(4, 6);\n }\n } else if (parts[0] === 'mp4a') {\n // AAC codec string format\n if (parts[1]) result.objectType = parts[1];\n if (parts[2]) result.audioObjectType = parts[2];\n }\n\n return result;\n}\n\n/**\n * Create MP4 file brands based on codec\n */\nexport function createBrands(codecs: string[]): string[] {\n const brands = new Set<string>(['isom', 'iso2']);\n\n for (const codec of codecs) {\n if (codec.startsWith('avc1')) {\n brands.add('avc1');\n brands.add('mp41');\n } else if (codec.startsWith('hev1') || codec.startsWith('hvc1')) {\n brands.add('hev1');\n brands.add('hvc1');\n } else if (codec.startsWith('av01')) {\n brands.add('av01');\n } else if (codec.startsWith('mp4a')) {\n brands.add('mp41');\n }\n }\n\n return Array.from(brands);\n}\n","// @ts-ignore - mp4box doesn't have proper TypeScript definitions\nimport * as MP4Box from 'mp4box';\nimport type { MuxConfig, MuxTrack } from './types';\nimport { usToTimescale, calculateTimescale, parseCodecString } from './utils';\n\ninterface MP4TrackOptions {\n timescale: number;\n type: string;\n nb_samples: number;\n width?: number;\n height?: number;\n channel_count?: number;\n samplerate?: number;\n hdlr?: string;\n name?: string;\n codec?: string;\n avcDecoderConfigRecord?: Uint8Array;\n hvcDecoderConfigRecord?: Uint8Array;\n av1DecoderConfigRecord?: Uint8Array;\n audioDecoderConfig?: Uint8Array;\n opusDecoderConfig?: Uint8Array;\n}\n\n/**\n * MP4 Muxer - Multiplex encoded chunks into MP4 container\n * Terminal stage that consumes encoded chunks and produces MP4 file\n */\nexport class MP4Muxer {\n private mp4boxFile: any;\n tracks = new Map<number, MuxTrack>();\n private mp4Tracks = new Map<number, number>(); // muxTrackId -> mp4boxTrackId\n\n // Expose output chunks directly instead of getter\n outputChunks: Uint8Array[] = [];\n\n // Expose total bytes written as computed property\n get totalBytesWritten(): number {\n return this.outputChunks.reduce((sum, chunk) => sum + chunk.byteLength, 0);\n }\n\n // Expose finalized state\n isFinalized = false;\n\n private config: MuxConfig;\n\n constructor(config: MuxConfig = { container: 'mp4' }) {\n this.config = config;\n this.mp4boxFile = MP4Box.createFile();\n this.setupHandlers();\n this.initializeTracks();\n }\n\n private setupHandlers(): void {\n this.mp4boxFile.onError = (error: string) => {\n console.error('MP4Box error:', error);\n };\n\n // Called when MP4Box has data to write\n this.mp4boxFile.onSegment = (\n _id: number,\n _user: any,\n buffer: ArrayBuffer,\n _sampleNumber: number,\n _last: boolean\n ) => {\n const chunk = new Uint8Array(buffer);\n this.outputChunks.push(chunk);\n };\n\n // Handle initialization segment for fragmented MP4\n if (this.config.mp4?.fragmented) {\n this.mp4boxFile.onInitSegment = (_tracks: any[]) => {\n const initSegment = this.mp4boxFile.getInitializationSegment();\n if (initSegment) {\n const chunk = new Uint8Array(initSegment);\n this.outputChunks.push(chunk);\n }\n };\n }\n }\n\n private initializeTracks(): void {\n // Add video track if configured\n if (this.config.video) {\n const videoTrack: MuxTrack = {\n id: 1, // Default video track ID\n type: 'video',\n codec: this.config.video.codec,\n width: this.config.video.width,\n height: this.config.video.height,\n frameRate: this.config.video.frameRate,\n timescale: calculateTimescale(this.config.video.frameRate),\n codecConfig: this.config.video.description,\n };\n this.addTrack(videoTrack);\n }\n\n // Add audio track if configured\n if (this.config.audio) {\n const audioTrack: MuxTrack = {\n id: 2, // Default audio track ID\n type: 'audio',\n codec: this.config.audio.codec,\n sampleRate: this.config.audio.sampleRate,\n channelCount: this.config.audio.channelCount,\n timescale: this.config.audio.sampleRate,\n codecConfig: this.config.audio.description,\n };\n this.addTrack(audioTrack);\n }\n }\n\n private addTrack(track: MuxTrack): number {\n if (!this.mp4boxFile) {\n throw new Error('Muxer destroyed');\n }\n\n // Store track info\n this.tracks.set(track.id, track);\n\n // Create track options based on type\n const trackOptions =\n track.type === 'video'\n ? this.createVideoTrackOptions(track)\n : this.createAudioTrackOptions(track);\n\n // Add track to MP4Box\n const mp4TrackId = this.mp4boxFile.addTrack(trackOptions);\n this.mp4Tracks.set(track.id, mp4TrackId);\n\n // Configure track for fragmented mode if enabled\n if (this.config.mp4?.fragmented) {\n this.configureFragmentedTrack(mp4TrackId, track);\n }\n\n return track.id;\n }\n\n private configureFragmentedTrack(mp4TrackId: number, track: MuxTrack): void {\n const fragmentDuration = this.config.mp4?.fragmentDuration || 1_000_000; // 1 second default in microseconds\n\n let nbSamples: number;\n\n if (track.type === 'video') {\n // For video: calculate number of frames per fragment based on frame rate\n // nbSamples = fragment_duration_in_seconds * frame_rate\n const frameRate = track.frameRate || 30;\n const fragmentDurationInSeconds = fragmentDuration / 1_000_000;\n nbSamples = Math.ceil(fragmentDurationInSeconds * frameRate);\n } else {\n // For audio: calculate number of samples per fragment\n // Audio typically has many more samples (e.g., 48000 Hz sample rate)\n // A reasonable fragment might contain ~1 second of audio samples\n const sampleRate = track.sampleRate || 48000;\n const fragmentDurationInSeconds = fragmentDuration / 1_000_000;\n // For compressed audio (AAC, Opus), each \"sample\" is actually a frame containing multiple PCM samples\n // AAC frame typically contains 1024 PCM samples, so at 48kHz: 48000/1024 ≈ 47 frames per second\n const framesPerSecond = sampleRate / 1024; // Assuming AAC-like frame size\n nbSamples = Math.ceil(fragmentDurationInSeconds * framesPerSecond);\n }\n\n /**\n * setSegmentOptions parameters:\n * @param trackId - The track ID to configure\n * @param user - User data (passed to callbacks, we don't use it)\n * @param options - Segmentation options:\n * - nbSamples: Number of samples per segment/fragment\n * - rapAlignement: Random Access Point alignment - ensures segments start with keyframes\n * This is critical for seeking and adaptive streaming (HLS/DASH)\n */\n this.mp4boxFile.setSegmentOptions(mp4TrackId, null, {\n nbSamples,\n rapAlignement: true, // Align segments to keyframes for proper seeking\n });\n }\n\n private createVideoTrackOptions(track: MuxTrack): MP4TrackOptions {\n const options: MP4TrackOptions = {\n timescale: track.timescale || calculateTimescale(track.frameRate),\n type: 'video',\n nb_samples: 0,\n width: track.width,\n height: track.height,\n };\n\n // Configure codec-specific options\n const codecInfo = parseCodecString(track.codec);\n\n switch (codecInfo.codec) {\n case 'avc1':\n options.codec = 'avc1';\n options.avcDecoderConfigRecord = track.codecConfig;\n break;\n case 'hev1':\n case 'hvc1':\n options.codec = 'hvc1';\n options.hvcDecoderConfigRecord = track.codecConfig;\n break;\n case 'av01':\n options.codec = 'av01';\n options.av1DecoderConfigRecord = track.codecConfig;\n break;\n case 'vp09':\n options.codec = 'vp09';\n // VP9 specific configuration\n break;\n default:\n throw new Error(`Unsupported video codec: ${track.codec}`);\n }\n\n return options;\n }\n\n private createAudioTrackOptions(track: MuxTrack): MP4TrackOptions {\n const options: MP4TrackOptions = {\n timescale: track.timescale || track.sampleRate || 48000,\n type: 'audio',\n nb_samples: 0,\n channel_count: track.channelCount,\n samplerate: track.sampleRate,\n hdlr: 'soun',\n name: 'SoundHandler',\n };\n\n // Configure codec-specific options\n const codecInfo = parseCodecString(track.codec);\n\n switch (codecInfo.codec) {\n case 'mp4a':\n options.codec = 'mp4a.40.2'; // AAC-LC\n options.audioDecoderConfig = track.codecConfig;\n break;\n case 'opus':\n options.codec = 'Opus';\n options.opusDecoderConfig = track.codecConfig;\n break;\n case 'mp3':\n options.codec = 'mp3';\n break;\n case 'ac-3':\n options.codec = 'ac-3';\n break;\n case 'ec-3':\n options.codec = 'ec-3';\n break;\n default:\n throw new Error(`Unsupported audio codec: ${track.codec}`);\n }\n\n return options;\n }\n\n /**\n * Write video chunk to muxer\n */\n writeVideoChunk(chunk: EncodedVideoChunk, trackId: number = 1): void {\n const mp4TrackId = this.mp4Tracks.get(trackId);\n if (!mp4TrackId) {\n throw new Error(`Track ${trackId} not found`);\n }\n\n const track = this.tracks.get(trackId);\n if (!track) {\n throw new Error(`Track info for ${trackId} not found`);\n }\n\n // Create buffer for chunk data\n const data = new Uint8Array(chunk.byteLength);\n chunk.copyTo(data);\n\n // Convert timestamps to timescale units\n const pts = usToTimescale(chunk.timestamp, track.timescale);\n const dts =\n chunk.timestamp !== undefined ? usToTimescale(chunk.timestamp, track.timescale) : pts;\n const duration = usToTimescale(chunk.duration || 0, track.timescale);\n\n // Create MP4Box sample\n const mp4Sample: any = {\n data: data,\n pts: pts,\n dts: dts,\n duration: duration,\n is_sync: chunk.type === 'key',\n };\n\n // Add sample to track\n this.mp4boxFile.addSample(mp4TrackId, data, mp4Sample);\n }\n\n /**\n * Write audio chunk to muxer\n */\n writeAudioChunk(chunk: EncodedAudioChunk, trackId: number = 2): void {\n const mp4TrackId = this.mp4Tracks.get(trackId);\n if (!mp4TrackId) {\n throw new Error(`Track ${trackId} not found`);\n }\n\n const track = this.tracks.get(trackId);\n if (!track) {\n throw new Error(`Track info for ${trackId} not found`);\n }\n\n // Create buffer for chunk data\n const data = new Uint8Array(chunk.byteLength);\n chunk.copyTo(data);\n\n // Convert timestamps to timescale units\n const pts = usToTimescale(chunk.timestamp, track.timescale);\n const duration = usToTimescale(chunk.duration || 0, track.timescale);\n\n // Create MP4Box sample\n const mp4Sample: any = {\n data: data,\n pts: pts,\n dts: pts,\n duration: duration,\n is_sync: true, // Audio chunks are always sync samples\n };\n\n // Add sample to track\n this.mp4boxFile.addSample(mp4TrackId, data, mp4Sample);\n }\n\n /**\n * Flush pending samples\n */\n flush(): void {\n if (this.mp4boxFile) {\n this.mp4boxFile.flush();\n }\n }\n\n /**\n * Finalize and get the output\n */\n finalize(): Blob {\n if (this.isFinalized) {\n throw new Error('Muxer already finalized');\n }\n\n if (!this.mp4boxFile) {\n throw new Error('Muxer destroyed');\n }\n\n // Flush any remaining samples\n this.flush();\n\n // For non-fragmented mode, close to write moov box\n if (!this.config.mp4?.fragmented) {\n this.mp4boxFile.close();\n }\n\n this.isFinalized = true;\n\n // Return the muxed MP4 as a Blob\n return new Blob(this.outputChunks as BlobPart[], { type: 'video/mp4' });\n }\n\n /**\n * Clear output chunks (after they've been consumed)\n */\n clearOutputChunks(): void {\n this.outputChunks = [];\n }\n\n destroy(): void {\n this.mp4boxFile?.stop?.();\n this.mp4boxFile = null;\n this.tracks.clear();\n this.mp4Tracks.clear();\n this.outputChunks = [];\n }\n}\n","import { WorkerChannel } from '../../worker/WorkerChannel';\nimport { WorkerMessageType, WorkerState } from '../../worker/types';\nimport { MP4Muxer } from './MP4Muxer';\nimport type { MuxConfig } from './types';\n\n/**\n * MuxWorker - Final stage for video/audio multiplexing\n * Combines encoded video and audio tracks into container format (MP4)\n *\n * Pipeline: CacheManager → MuxWorker → Export (Blob/OPFS)\n *\n * Features:\n * - MP4 container muxing with mp4box.js\n * - Stream-based processing from L2 cache\n * - Support for fragmented MP4 (fMP4) for streaming\n * - Direct blob output for download\n */\nexport class MuxWorkerImpl {\n private channel: WorkerChannel;\n private muxer: MP4Muxer | null = null;\n private config: MuxConfig | null = null;\n\n constructor() {\n // Initialize WorkerChannel\n this.channel = new WorkerChannel(self as any, {\n name: 'MuxWorker',\n timeout: 60000, // 60s for export operations\n });\n\n this.setupHandlers();\n }\n\n private setupHandlers(): void {\n // Register message handlers\n this.channel.registerHandler('configure', this.handleConfigure.bind(this));\n // Unified stream connect (feature-flagged)\n this.channel.registerHandler('connect' as any, this.handleUnifiedConnect.bind(this));\n // Unified stream connect only\n this.channel.registerHandler('write_video_chunk', this.handleWriteVideoChunk.bind(this));\n this.channel.registerHandler('write_audio_chunk', this.handleWriteAudioChunk.bind(this));\n this.channel.registerHandler('flush', this.handleFlush.bind(this));\n this.channel.registerHandler('finalize', this.handleFinalize.bind(this));\n this.channel.registerHandler('get_stats', this.handleGetStats.bind(this));\n this.channel.registerHandler(WorkerMessageType.Dispose, this.handleDispose.bind(this));\n\n // Setup stream receiver from CacheManager (L2 encoded chunks)\n this.channel.receiveStream(this.handleInputStream.bind(this));\n }\n\n /**\n * Unified connect handler used by stream pipeline\n */\n private async handleUnifiedConnect(_payload: {\n direction: 'upstream';\n port: MessagePort;\n streamType: 'video' | 'audio' | 'frame' | 'chunk';\n }): Promise<{ success: boolean }> {\n // Mux receives encoded chunks via receiveStream already\n return { success: true };\n }\n\n /**\n * Connect to encoder worker to receive encoded chunks\n */\n // private async handleConnectEncoder(_payload: {\n // port: MessagePort;\n // }): Promise<{ success: boolean }> {\n // // Store the port for receiving encoded chunks\n // // The actual stream handling is done via receiveStream in handleInputStream\n // // This connection allows direct communication with the encoder worker\n // return { success: true };\n // }\n\n /**\n * Configure muxer with container settings\n * @param payload.config - Muxer configuration including tracks and output format\n * @param payload.initial - If true, initialize worker state; otherwise just update config\n */\n private async handleConfigure(payload: {\n config: MuxConfig;\n initial?: boolean;\n }): Promise<{ success: boolean; tracks?: number }> {\n const { config, initial = false } = payload;\n\n try {\n if (initial) {\n // Initial setup - set worker state to ready\n this.channel.state = WorkerState.Ready;\n\n // Create new muxer instance\n if (this.muxer) {\n this.muxer.destroy();\n }\n\n this.config = config;\n this.muxer = new MP4Muxer(config);\n\n const trackCount = (config.video ? 1 : 0) + (config.audio ? 1 : 0);\n\n // Notify configuration complete\n this.channel.notify('configured', {\n container: config.container,\n hasVideo: !!config.video,\n hasAudio: !!config.audio,\n fragmented: !!config.mp4?.fragmented,\n trackCount,\n });\n\n return { success: true, tracks: trackCount };\n } else {\n // Update configuration only\n if (!this.muxer) {\n throw {\n code: 'NOT_INITIALIZED',\n message: 'Muxer not initialized. Call configure with initial=true first',\n };\n }\n\n // MP4Muxer doesn't support runtime config updates\n // Would need to recreate for changes\n this.config = { ...this.config, ...config };\n\n return { success: true };\n }\n } catch (error: any) {\n throw {\n code: error.code || 'CONFIG_ERROR',\n message: error.message,\n };\n }\n }\n\n /**\n * Write single video chunk\n */\n private async handleWriteVideoChunk(payload: {\n chunk: EncodedVideoChunk;\n trackId?: number;\n }): Promise<{ bytesWritten: number }> {\n if (!this.muxer) {\n throw {\n code: 'NOT_INITIALIZED',\n message: 'Muxer not initialized',\n };\n }\n\n this.muxer.writeVideoChunk(payload.chunk, payload.trackId);\n\n return { bytesWritten: this.muxer.totalBytesWritten };\n }\n\n /**\n * Write single audio chunk\n */\n private async handleWriteAudioChunk(payload: {\n chunk: EncodedAudioChunk;\n trackId?: number;\n }): Promise<{ bytesWritten: number }> {\n if (!this.muxer) {\n throw {\n code: 'NOT_INITIALIZED',\n message: 'Muxer not initialized',\n };\n }\n\n this.muxer.writeAudioChunk(payload.chunk, payload.trackId);\n\n return { bytesWritten: this.muxer.totalBytesWritten };\n }\n\n /**\n * Handle input stream from CacheManager (L2 encoded chunks)\n * This is the main export path where CacheManager sends encoded chunks\n */\n private async handleInputStream(\n stream: ReadableStream<EncodedVideoChunk | EncodedAudioChunk>,\n metadata?: Record<string, any>\n ): Promise<void> {\n if (!this.muxer) {\n throw new Error('Muxer not configured');\n }\n\n const reader = stream.getReader();\n let chunksProcessed = 0;\n\n try {\n this.channel.state = WorkerState.Processing;\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n // Determine chunk type and write accordingly\n const isVideoChunk =\n metadata?.type === 'video' ||\n (value as any).type === 'key' ||\n (value as any).type === 'delta';\n\n if (isVideoChunk) {\n this.muxer.writeVideoChunk(value as EncodedVideoChunk, metadata?.trackId || 1);\n } else {\n this.muxer.writeAudioChunk(value as EncodedAudioChunk, metadata?.trackId || 2);\n }\n\n chunksProcessed++;\n\n // Report progress periodically\n if (chunksProcessed % 100 === 0) {\n this.channel.notify('mux_progress', {\n chunksProcessed,\n bytesWritten: this.muxer.totalBytesWritten,\n });\n }\n }\n\n // Flush after stream processing\n this.muxer.flush();\n\n this.channel.state = WorkerState.Ready;\n\n // Notify muxing complete\n this.channel.notify('mux_complete', {\n chunksProcessed,\n bytesWritten: this.muxer.totalBytesWritten,\n });\n } finally {\n reader.releaseLock();\n }\n }\n\n /**\n * Flush pending samples\n */\n private async handleFlush(): Promise<{ success: boolean }> {\n if (!this.muxer) {\n throw {\n code: 'NOT_INITIALIZED',\n message: 'Muxer not initialized',\n };\n }\n\n this.muxer.flush();\n return { success: true };\n }\n\n /**\n * Finalize muxing and get output\n * This completes the export process\n */\n private async handleFinalize(): Promise<{\n success: boolean;\n blob: Blob;\n totalBytes: number;\n }> {\n if (!this.muxer) {\n throw {\n code: 'NOT_INITIALIZED',\n message: 'Muxer not initialized',\n };\n }\n\n const blob = this.muxer.finalize();\n\n // Notify export completion as per architecture doc\n this.channel.notify('export_done', {\n blob,\n totalBytes: blob.size,\n });\n\n return {\n success: true,\n blob,\n totalBytes: blob.size,\n };\n }\n\n /**\n * Get muxer statistics\n */\n private async handleGetStats(): Promise<{\n bytesWritten?: number;\n chunksCount?: number;\n isFinalized?: boolean;\n state?: WorkerState;\n }> {\n if (!this.muxer) {\n return { state: this.channel.state };\n }\n\n return {\n bytesWritten: this.muxer.totalBytesWritten,\n chunksCount: this.muxer.outputChunks.length,\n isFinalized: this.muxer.isFinalized,\n state: this.channel.state,\n };\n }\n\n /**\n * Dispose worker and cleanup resources\n */\n private async handleDispose(): Promise<{ success: boolean }> {\n // Destroy muxer\n this.muxer?.destroy();\n this.muxer = null;\n this.config = null;\n\n this.channel.state = WorkerState.Disposed;\n\n return { success: true };\n }\n}\n\n// Initialize worker\nconst worker = new MuxWorkerImpl();\n\n// Handle worker termination\nself.addEventListener('beforeunload', () => {\n worker['handleDispose']();\n});\n\nexport default null; // Required for TypeScript worker compilation\n"],"names":["MP4Box.createFile"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meframe/core",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "description": "Next generation media processing framework based on WebCodecs",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -38,25 +38,6 @@
38
38
  "LICENSE",
39
39
  "CHANGELOG.md"
40
40
  ],
41
- "scripts": {
42
- "dev": "vite",
43
- "build": "tsc && vite build",
44
- "preview": "vite preview",
45
- "prepublishOnly": "npm run lint && npm run type-check && npm run build",
46
- "test": "vitest run",
47
- "test:watch": "vitest",
48
- "test:coverage": "vitest run --coverage",
49
- "test:ui": "vitest --ui",
50
- "test:integration": "vitest run --config vitest.integration.config.ts",
51
- "test:e2e": "playwright test --project=chromium",
52
- "test:e2e:ui": "playwright test --project=chromium --ui",
53
- "test:e2e:debug": "playwright test --project=chromium --debug",
54
- "lint": "eslint src --ignore-pattern '**/__tests__' --ignore-pattern '**/*.test.ts' --ignore-pattern '**/*.spec.ts'",
55
- "lint:fix": "eslint src --fix --ignore-pattern '**/__tests__' --ignore-pattern '**/*.test.ts' --ignore-pattern '**/*.spec.ts'",
56
- "type-check": "tsc --noEmit",
57
- "clean": "rm -rf dist coverage",
58
- "playwright:install": "playwright install chromium"
59
- },
60
41
  "dependencies": {
61
42
  "mp4box": "^0.5.2"
62
43
  },
@@ -107,5 +88,24 @@
107
88
  "publishConfig": {
108
89
  "access": "public",
109
90
  "registry": "https://registry.npmjs.org/"
91
+ },
92
+ "scripts": {
93
+ "dev": "vite",
94
+ "build": "tsc && vite build && pnpm build:workers",
95
+ "build:workers": "vite build --config vite.worker.config.ts",
96
+ "preview": "vite preview",
97
+ "test": "vitest run",
98
+ "test:watch": "vitest",
99
+ "test:coverage": "vitest run --coverage",
100
+ "test:ui": "vitest --ui",
101
+ "test:integration": "vitest run --config vitest.integration.config.ts",
102
+ "test:e2e": "playwright test --project=chromium",
103
+ "test:e2e:ui": "playwright test --project=chromium --ui",
104
+ "test:e2e:debug": "playwright test --project=chromium --debug",
105
+ "lint": "eslint src --ignore-pattern '**/__tests__' --ignore-pattern '**/*.test.ts' --ignore-pattern '**/*.spec.ts' --ignore-pattern '**/*.worker.ts'",
106
+ "lint:fix": "eslint src --fix --ignore-pattern '**/__tests__' --ignore-pattern '**/*.test.ts' --ignore-pattern '**/*.spec.ts' --ignore-pattern '**/*.worker.ts'",
107
+ "type-check": "tsc --noEmit",
108
+ "clean": "rm -rf dist coverage",
109
+ "playwright:install": "playwright install chromium"
110
110
  }
111
- }
111
+ }