@meframe/core 0.0.1

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 (352) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/LICENSE +22 -0
  3. package/README.md +396 -0
  4. package/dist/Meframe.d.ts +82 -0
  5. package/dist/Meframe.d.ts.map +1 -0
  6. package/dist/Meframe.js +290 -0
  7. package/dist/Meframe.js.map +1 -0
  8. package/dist/_virtual/mp4box.all.js +5 -0
  9. package/dist/_virtual/mp4box.all.js.map +1 -0
  10. package/dist/cache/BatchWriter.d.ts +25 -0
  11. package/dist/cache/BatchWriter.d.ts.map +1 -0
  12. package/dist/cache/CacheManager.d.ts +115 -0
  13. package/dist/cache/CacheManager.d.ts.map +1 -0
  14. package/dist/cache/CacheManager.js +388 -0
  15. package/dist/cache/CacheManager.js.map +1 -0
  16. package/dist/cache/CacheStatsDecorator.d.ts +27 -0
  17. package/dist/cache/CacheStatsDecorator.d.ts.map +1 -0
  18. package/dist/cache/L2Cache.d.ts +39 -0
  19. package/dist/cache/L2Cache.d.ts.map +1 -0
  20. package/dist/cache/L2Cache.js +282 -0
  21. package/dist/cache/L2Cache.js.map +1 -0
  22. package/dist/cache/index.d.ts +7 -0
  23. package/dist/cache/index.d.ts.map +1 -0
  24. package/dist/cache/l1/AudioL1Cache.d.ts +30 -0
  25. package/dist/cache/l1/AudioL1Cache.d.ts.map +1 -0
  26. package/dist/cache/l1/AudioL1Cache.js +306 -0
  27. package/dist/cache/l1/AudioL1Cache.js.map +1 -0
  28. package/dist/cache/l1/MixedAudioL1Cache.d.ts +13 -0
  29. package/dist/cache/l1/MixedAudioL1Cache.d.ts.map +1 -0
  30. package/dist/cache/l1/MixedAudioL1Cache.js +52 -0
  31. package/dist/cache/l1/MixedAudioL1Cache.js.map +1 -0
  32. package/dist/cache/l1/VideoL1Cache.d.ts +69 -0
  33. package/dist/cache/l1/VideoL1Cache.d.ts.map +1 -0
  34. package/dist/cache/l1/VideoL1Cache.js +318 -0
  35. package/dist/cache/l1/VideoL1Cache.js.map +1 -0
  36. package/dist/cache/l1/gop-utils.d.ts +10 -0
  37. package/dist/cache/l1/gop-utils.d.ts.map +1 -0
  38. package/dist/cache/l1/gop-utils.js +78 -0
  39. package/dist/cache/l1/gop-utils.js.map +1 -0
  40. package/dist/cache/l1/index.d.ts +4 -0
  41. package/dist/cache/l1/index.d.ts.map +1 -0
  42. package/dist/cache/l1/types.d.ts +17 -0
  43. package/dist/cache/l1/types.d.ts.map +1 -0
  44. package/dist/cache/types.d.ts +93 -0
  45. package/dist/cache/types.d.ts.map +1 -0
  46. package/dist/config/ConfigLoader.d.ts +69 -0
  47. package/dist/config/ConfigLoader.d.ts.map +1 -0
  48. package/dist/config/ConfigLoader.js +133 -0
  49. package/dist/config/ConfigLoader.js.map +1 -0
  50. package/dist/config/defaults.d.ts +125 -0
  51. package/dist/config/defaults.d.ts.map +1 -0
  52. package/dist/config/defaults.js +191 -0
  53. package/dist/config/defaults.js.map +1 -0
  54. package/dist/config/index.d.ts +6 -0
  55. package/dist/config/index.d.ts.map +1 -0
  56. package/dist/config/presets.d.ts +32 -0
  57. package/dist/config/presets.d.ts.map +1 -0
  58. package/dist/config/presets.js +11 -0
  59. package/dist/config/presets.js.map +1 -0
  60. package/dist/config/types.d.ts +199 -0
  61. package/dist/config/types.d.ts.map +1 -0
  62. package/dist/config/validation.d.ts +19 -0
  63. package/dist/config/validation.d.ts.map +1 -0
  64. package/dist/config/validation.js +232 -0
  65. package/dist/config/validation.js.map +1 -0
  66. package/dist/controllers/PlaybackController.d.ts +55 -0
  67. package/dist/controllers/PlaybackController.d.ts.map +1 -0
  68. package/dist/controllers/PlaybackController.js +369 -0
  69. package/dist/controllers/PlaybackController.js.map +1 -0
  70. package/dist/controllers/PreRenderService.d.ts +34 -0
  71. package/dist/controllers/PreRenderService.d.ts.map +1 -0
  72. package/dist/controllers/PreRenderService.js +83 -0
  73. package/dist/controllers/PreRenderService.js.map +1 -0
  74. package/dist/controllers/PreRenderTaskQueue.d.ts +21 -0
  75. package/dist/controllers/PreRenderTaskQueue.d.ts.map +1 -0
  76. package/dist/controllers/PreviewHandle.d.ts +23 -0
  77. package/dist/controllers/PreviewHandle.d.ts.map +1 -0
  78. package/dist/controllers/PreviewHandle.js +39 -0
  79. package/dist/controllers/PreviewHandle.js.map +1 -0
  80. package/dist/controllers/index.d.ts +8 -0
  81. package/dist/controllers/index.d.ts.map +1 -0
  82. package/dist/controllers/types.d.ts +102 -0
  83. package/dist/controllers/types.d.ts.map +1 -0
  84. package/dist/event/EventBus.d.ts +42 -0
  85. package/dist/event/EventBus.d.ts.map +1 -0
  86. package/dist/event/EventBus.js +94 -0
  87. package/dist/event/EventBus.js.map +1 -0
  88. package/dist/event/events.d.ts +371 -0
  89. package/dist/event/events.d.ts.map +1 -0
  90. package/dist/event/events.js +71 -0
  91. package/dist/event/events.js.map +1 -0
  92. package/dist/event/index.d.ts +4 -0
  93. package/dist/event/index.d.ts.map +1 -0
  94. package/dist/index.d.ts +14 -0
  95. package/dist/index.d.ts.map +1 -0
  96. package/dist/index.js +15 -0
  97. package/dist/index.js.map +1 -0
  98. package/dist/model/CompositionModel.d.ts +48 -0
  99. package/dist/model/CompositionModel.d.ts.map +1 -0
  100. package/dist/model/CompositionModel.js +197 -0
  101. package/dist/model/CompositionModel.js.map +1 -0
  102. package/dist/model/RcFrame.d.ts +34 -0
  103. package/dist/model/RcFrame.d.ts.map +1 -0
  104. package/dist/model/RcFrame.js +97 -0
  105. package/dist/model/RcFrame.js.map +1 -0
  106. package/dist/model/dirty-range.d.ts +5 -0
  107. package/dist/model/dirty-range.d.ts.map +1 -0
  108. package/dist/model/dirty-range.js +220 -0
  109. package/dist/model/dirty-range.js.map +1 -0
  110. package/dist/model/index.d.ts +7 -0
  111. package/dist/model/index.d.ts.map +1 -0
  112. package/dist/model/patch.d.ts +5 -0
  113. package/dist/model/patch.d.ts.map +1 -0
  114. package/dist/model/patch.js +250 -0
  115. package/dist/model/patch.js.map +1 -0
  116. package/dist/model/types.d.ts +135 -0
  117. package/dist/model/types.d.ts.map +1 -0
  118. package/dist/model/types.js +5 -0
  119. package/dist/model/types.js.map +1 -0
  120. package/dist/model/validation.d.ts +15 -0
  121. package/dist/model/validation.d.ts.map +1 -0
  122. package/dist/model/validation.js +74 -0
  123. package/dist/model/validation.js.map +1 -0
  124. package/dist/node_modules/.pnpm/mp4box@0.5.4/node_modules/mp4box/dist/mp4box.all.js +7046 -0
  125. package/dist/node_modules/.pnpm/mp4box@0.5.4/node_modules/mp4box/dist/mp4box.all.js.map +1 -0
  126. package/dist/orchestrator/ClipSessionManager.d.ts +75 -0
  127. package/dist/orchestrator/ClipSessionManager.d.ts.map +1 -0
  128. package/dist/orchestrator/ClipSessionManager.js +160 -0
  129. package/dist/orchestrator/ClipSessionManager.js.map +1 -0
  130. package/dist/orchestrator/CompositionPlanner.d.ts +55 -0
  131. package/dist/orchestrator/CompositionPlanner.d.ts.map +1 -0
  132. package/dist/orchestrator/CompositionPlanner.js +411 -0
  133. package/dist/orchestrator/CompositionPlanner.js.map +1 -0
  134. package/dist/orchestrator/Orchestrator.d.ts +59 -0
  135. package/dist/orchestrator/Orchestrator.d.ts.map +1 -0
  136. package/dist/orchestrator/Orchestrator.js +390 -0
  137. package/dist/orchestrator/Orchestrator.js.map +1 -0
  138. package/dist/orchestrator/VideoClipSession.d.ts +64 -0
  139. package/dist/orchestrator/VideoClipSession.d.ts.map +1 -0
  140. package/dist/orchestrator/VideoClipSession.js +309 -0
  141. package/dist/orchestrator/VideoClipSession.js.map +1 -0
  142. package/dist/orchestrator/index.d.ts +5 -0
  143. package/dist/orchestrator/index.d.ts.map +1 -0
  144. package/dist/orchestrator/types.d.ts +64 -0
  145. package/dist/orchestrator/types.d.ts.map +1 -0
  146. package/dist/plugins/BackpressureMonitor.d.ts +33 -0
  147. package/dist/plugins/BackpressureMonitor.d.ts.map +1 -0
  148. package/dist/plugins/BackpressureMonitor.js +62 -0
  149. package/dist/plugins/BackpressureMonitor.js.map +1 -0
  150. package/dist/plugins/PluginManager.d.ts +37 -0
  151. package/dist/plugins/PluginManager.d.ts.map +1 -0
  152. package/dist/plugins/PluginManager.js +66 -0
  153. package/dist/plugins/PluginManager.js.map +1 -0
  154. package/dist/plugins/types.d.ts +60 -0
  155. package/dist/plugins/types.d.ts.map +1 -0
  156. package/dist/stages/compose/AudioDucker.d.ts +59 -0
  157. package/dist/stages/compose/AudioDucker.d.ts.map +1 -0
  158. package/dist/stages/compose/AudioDucker.js +161 -0
  159. package/dist/stages/compose/AudioDucker.js.map +1 -0
  160. package/dist/stages/compose/AudioMixer.d.ts +29 -0
  161. package/dist/stages/compose/AudioMixer.d.ts.map +1 -0
  162. package/dist/stages/compose/AudioMixer.js +373 -0
  163. package/dist/stages/compose/AudioMixer.js.map +1 -0
  164. package/dist/stages/compose/FilterProcessor.d.ts +41 -0
  165. package/dist/stages/compose/FilterProcessor.d.ts.map +1 -0
  166. package/dist/stages/compose/FilterProcessor.js +226 -0
  167. package/dist/stages/compose/FilterProcessor.js.map +1 -0
  168. package/dist/stages/compose/GlobalAudioSession.d.ts +38 -0
  169. package/dist/stages/compose/GlobalAudioSession.d.ts.map +1 -0
  170. package/dist/stages/compose/GlobalAudioSession.js +122 -0
  171. package/dist/stages/compose/GlobalAudioSession.js.map +1 -0
  172. package/dist/stages/compose/LayerRenderer.d.ts +30 -0
  173. package/dist/stages/compose/LayerRenderer.d.ts.map +1 -0
  174. package/dist/stages/compose/LayerRenderer.js +215 -0
  175. package/dist/stages/compose/LayerRenderer.js.map +1 -0
  176. package/dist/stages/compose/OfflineAudioMixer.d.ts +14 -0
  177. package/dist/stages/compose/OfflineAudioMixer.d.ts.map +1 -0
  178. package/dist/stages/compose/OfflineAudioMixer.js +68 -0
  179. package/dist/stages/compose/OfflineAudioMixer.js.map +1 -0
  180. package/dist/stages/compose/TransitionProcessor.d.ts +30 -0
  181. package/dist/stages/compose/TransitionProcessor.d.ts.map +1 -0
  182. package/dist/stages/compose/TransitionProcessor.js +189 -0
  183. package/dist/stages/compose/TransitionProcessor.js.map +1 -0
  184. package/dist/stages/compose/VideoComposer.d.ts +30 -0
  185. package/dist/stages/compose/VideoComposer.d.ts.map +1 -0
  186. package/dist/stages/compose/VideoComposer.js +186 -0
  187. package/dist/stages/compose/VideoComposer.js.map +1 -0
  188. package/dist/stages/compose/audio-compose.worker.d.ts +79 -0
  189. package/dist/stages/compose/audio-compose.worker.d.ts.map +1 -0
  190. package/dist/stages/compose/audio-compose.worker.js +541 -0
  191. package/dist/stages/compose/audio-compose.worker.js.map +1 -0
  192. package/dist/stages/compose/instructions.d.ts +95 -0
  193. package/dist/stages/compose/instructions.d.ts.map +1 -0
  194. package/dist/stages/compose/types.d.ts +245 -0
  195. package/dist/stages/compose/types.d.ts.map +1 -0
  196. package/dist/stages/compose/video-compose.worker.d.ts +60 -0
  197. package/dist/stages/compose/video-compose.worker.d.ts.map +1 -0
  198. package/dist/stages/compose/video-compose.worker.js +369 -0
  199. package/dist/stages/compose/video-compose.worker.js.map +1 -0
  200. package/dist/stages/decode/AudioChunkDecoder.d.ts +41 -0
  201. package/dist/stages/decode/AudioChunkDecoder.d.ts.map +1 -0
  202. package/dist/stages/decode/AudioChunkDecoder.js +83 -0
  203. package/dist/stages/decode/AudioChunkDecoder.js.map +1 -0
  204. package/dist/stages/decode/BaseDecoder.d.ts +35 -0
  205. package/dist/stages/decode/BaseDecoder.d.ts.map +1 -0
  206. package/dist/stages/decode/BaseDecoder.js +130 -0
  207. package/dist/stages/decode/BaseDecoder.js.map +1 -0
  208. package/dist/stages/decode/VideoChunkDecoder.d.ts +54 -0
  209. package/dist/stages/decode/VideoChunkDecoder.d.ts.map +1 -0
  210. package/dist/stages/decode/VideoChunkDecoder.js +209 -0
  211. package/dist/stages/decode/VideoChunkDecoder.js.map +1 -0
  212. package/dist/stages/decode/decode.worker.d.ts +70 -0
  213. package/dist/stages/decode/decode.worker.d.ts.map +1 -0
  214. package/dist/stages/decode/decode.worker.js +436 -0
  215. package/dist/stages/decode/decode.worker.js.map +1 -0
  216. package/dist/stages/decode/index.d.ts +5 -0
  217. package/dist/stages/decode/index.d.ts.map +1 -0
  218. package/dist/stages/decode/types.d.ts +108 -0
  219. package/dist/stages/decode/types.d.ts.map +1 -0
  220. package/dist/stages/demux/MP3FrameParser.d.ts +33 -0
  221. package/dist/stages/demux/MP3FrameParser.d.ts.map +1 -0
  222. package/dist/stages/demux/MP3FrameParser.js +186 -0
  223. package/dist/stages/demux/MP3FrameParser.js.map +1 -0
  224. package/dist/stages/demux/MP4Demuxer.d.ts +45 -0
  225. package/dist/stages/demux/MP4Demuxer.d.ts.map +1 -0
  226. package/dist/stages/demux/MP4Demuxer.js +227 -0
  227. package/dist/stages/demux/MP4Demuxer.js.map +1 -0
  228. package/dist/stages/demux/aac-esds-extractor.d.ts +7 -0
  229. package/dist/stages/demux/aac-esds-extractor.d.ts.map +1 -0
  230. package/dist/stages/demux/audio-demux.worker.d.ts +51 -0
  231. package/dist/stages/demux/audio-demux.worker.d.ts.map +1 -0
  232. package/dist/stages/demux/audio-demux.worker.js +312 -0
  233. package/dist/stages/demux/audio-demux.worker.js.map +1 -0
  234. package/dist/stages/demux/types.d.ts +77 -0
  235. package/dist/stages/demux/types.d.ts.map +1 -0
  236. package/dist/stages/demux/video-demux.worker.d.ts +48 -0
  237. package/dist/stages/demux/video-demux.worker.d.ts.map +1 -0
  238. package/dist/stages/demux/video-demux.worker.js +173 -0
  239. package/dist/stages/demux/video-demux.worker.js.map +1 -0
  240. package/dist/stages/encode/AudioChunkEncoder.d.ts +21 -0
  241. package/dist/stages/encode/AudioChunkEncoder.d.ts.map +1 -0
  242. package/dist/stages/encode/AudioChunkEncoder.js +37 -0
  243. package/dist/stages/encode/AudioChunkEncoder.js.map +1 -0
  244. package/dist/stages/encode/BaseEncoder.d.ts +44 -0
  245. package/dist/stages/encode/BaseEncoder.d.ts.map +1 -0
  246. package/dist/stages/encode/BaseEncoder.js +164 -0
  247. package/dist/stages/encode/BaseEncoder.js.map +1 -0
  248. package/dist/stages/encode/EncoderPool.d.ts +28 -0
  249. package/dist/stages/encode/EncoderPool.d.ts.map +1 -0
  250. package/dist/stages/encode/VideoChunkEncoder.d.ts +26 -0
  251. package/dist/stages/encode/VideoChunkEncoder.d.ts.map +1 -0
  252. package/dist/stages/encode/VideoChunkEncoder.js +50 -0
  253. package/dist/stages/encode/VideoChunkEncoder.js.map +1 -0
  254. package/dist/stages/encode/encode.worker.d.ts +3 -0
  255. package/dist/stages/encode/encode.worker.d.ts.map +1 -0
  256. package/dist/stages/encode/encode.worker.js +318 -0
  257. package/dist/stages/encode/encode.worker.js.map +1 -0
  258. package/dist/stages/encode/index.d.ts +6 -0
  259. package/dist/stages/encode/index.d.ts.map +1 -0
  260. package/dist/stages/encode/types.d.ts +127 -0
  261. package/dist/stages/encode/types.d.ts.map +1 -0
  262. package/dist/stages/load/EventHandlers.d.ts +35 -0
  263. package/dist/stages/load/EventHandlers.d.ts.map +1 -0
  264. package/dist/stages/load/EventHandlers.js +65 -0
  265. package/dist/stages/load/EventHandlers.js.map +1 -0
  266. package/dist/stages/load/ResourceLoader.d.ts +36 -0
  267. package/dist/stages/load/ResourceLoader.d.ts.map +1 -0
  268. package/dist/stages/load/ResourceLoader.js +184 -0
  269. package/dist/stages/load/ResourceLoader.js.map +1 -0
  270. package/dist/stages/load/StreamFactory.d.ts +42 -0
  271. package/dist/stages/load/StreamFactory.d.ts.map +1 -0
  272. package/dist/stages/load/StreamFactory.js +201 -0
  273. package/dist/stages/load/StreamFactory.js.map +1 -0
  274. package/dist/stages/load/TaskManager.d.ts +50 -0
  275. package/dist/stages/load/TaskManager.d.ts.map +1 -0
  276. package/dist/stages/load/TaskManager.js +103 -0
  277. package/dist/stages/load/TaskManager.js.map +1 -0
  278. package/dist/stages/load/WindowByteRangeResolver.d.ts +47 -0
  279. package/dist/stages/load/WindowByteRangeResolver.d.ts.map +1 -0
  280. package/dist/stages/load/WindowByteRangeResolver.js +270 -0
  281. package/dist/stages/load/WindowByteRangeResolver.js.map +1 -0
  282. package/dist/stages/load/index.d.ts +11 -0
  283. package/dist/stages/load/index.d.ts.map +1 -0
  284. package/dist/stages/load/types.d.ts +177 -0
  285. package/dist/stages/load/types.d.ts.map +1 -0
  286. package/dist/stages/mux/MP4Muxer.d.ts +44 -0
  287. package/dist/stages/mux/MP4Muxer.d.ts.map +1 -0
  288. package/dist/stages/mux/MP4Muxer.js +262 -0
  289. package/dist/stages/mux/MP4Muxer.js.map +1 -0
  290. package/dist/stages/mux/OPFSWriter.d.ts +46 -0
  291. package/dist/stages/mux/OPFSWriter.d.ts.map +1 -0
  292. package/dist/stages/mux/index.d.ts +5 -0
  293. package/dist/stages/mux/index.d.ts.map +1 -0
  294. package/dist/stages/mux/mux.worker.d.ts +65 -0
  295. package/dist/stages/mux/mux.worker.d.ts.map +1 -0
  296. package/dist/stages/mux/mux.worker.js +219 -0
  297. package/dist/stages/mux/mux.worker.js.map +1 -0
  298. package/dist/stages/mux/types.d.ts +95 -0
  299. package/dist/stages/mux/types.d.ts.map +1 -0
  300. package/dist/stages/mux/utils.d.ts +32 -0
  301. package/dist/stages/mux/utils.d.ts.map +1 -0
  302. package/dist/stages/mux/utils.js +34 -0
  303. package/dist/stages/mux/utils.js.map +1 -0
  304. package/dist/types.d.ts +25 -0
  305. package/dist/types.d.ts.map +1 -0
  306. package/dist/utils/BackpressureAdapter.d.ts +26 -0
  307. package/dist/utils/BackpressureAdapter.d.ts.map +1 -0
  308. package/dist/utils/binary-search.d.ts +33 -0
  309. package/dist/utils/binary-search.d.ts.map +1 -0
  310. package/dist/utils/binary-search.js +62 -0
  311. package/dist/utils/binary-search.js.map +1 -0
  312. package/dist/utils/canvas-utils.d.ts +96 -0
  313. package/dist/utils/canvas-utils.d.ts.map +1 -0
  314. package/dist/utils/canvas-utils.js +58 -0
  315. package/dist/utils/canvas-utils.js.map +1 -0
  316. package/dist/utils/object-utils.d.ts +34 -0
  317. package/dist/utils/object-utils.d.ts.map +1 -0
  318. package/dist/utils/object-utils.js +22 -0
  319. package/dist/utils/object-utils.js.map +1 -0
  320. package/dist/utils/time-utils.d.ts +10 -0
  321. package/dist/utils/time-utils.d.ts.map +1 -0
  322. package/dist/utils/time-utils.js +60 -0
  323. package/dist/utils/time-utils.js.map +1 -0
  324. package/dist/worker/BaseWorker.d.ts +44 -0
  325. package/dist/worker/BaseWorker.d.ts.map +1 -0
  326. package/dist/worker/BaseWorker.js +98 -0
  327. package/dist/worker/BaseWorker.js.map +1 -0
  328. package/dist/worker/WorkerChannel.d.ts +105 -0
  329. package/dist/worker/WorkerChannel.d.ts.map +1 -0
  330. package/dist/worker/WorkerChannel.js +355 -0
  331. package/dist/worker/WorkerChannel.js.map +1 -0
  332. package/dist/worker/WorkerPool.d.ts +52 -0
  333. package/dist/worker/WorkerPool.d.ts.map +1 -0
  334. package/dist/worker/WorkerPool.js +124 -0
  335. package/dist/worker/WorkerPool.js.map +1 -0
  336. package/dist/worker/index.d.ts +11 -0
  337. package/dist/worker/index.d.ts.map +1 -0
  338. package/dist/worker/transferable-helper.d.ts +89 -0
  339. package/dist/worker/transferable-helper.d.ts.map +1 -0
  340. package/dist/worker/transferable-helper.js +44 -0
  341. package/dist/worker/transferable-helper.js.map +1 -0
  342. package/dist/worker/types.d.ts +179 -0
  343. package/dist/worker/types.d.ts.map +1 -0
  344. package/dist/worker/types.js +50 -0
  345. package/dist/worker/types.js.map +1 -0
  346. package/dist/worker/worker-event-whitelist.d.ts +23 -0
  347. package/dist/worker/worker-event-whitelist.d.ts.map +1 -0
  348. package/dist/worker/worker-retry.d.ts +36 -0
  349. package/dist/worker/worker-retry.d.ts.map +1 -0
  350. package/dist/worker/worker-retry.js +55 -0
  351. package/dist/worker/worker-retry.js.map +1 -0
  352. package/package.json +105 -0
@@ -0,0 +1,312 @@
1
+ import { WorkerChannel } from "../../worker/WorkerChannel.js";
2
+ import { WorkerMessageType, WorkerState } from "../../worker/types.js";
3
+ import { MP4Demuxer } from "./MP4Demuxer.js";
4
+ import { MP3FrameParser } from "./MP3FrameParser.js";
5
+ class AudioDemuxWorker {
6
+ channel;
7
+ demuxer = null;
8
+ audioStream = null;
9
+ mp3Parser = null;
10
+ currentFormat = null;
11
+ // Connection to decoder worker
12
+ decoderPort = null;
13
+ constructor() {
14
+ this.channel = new WorkerChannel(self, {
15
+ name: "AudioDemuxWorker",
16
+ timeout: 3e4
17
+ });
18
+ this.setupHandlers();
19
+ }
20
+ setupHandlers() {
21
+ this.channel.registerHandler("configure", this.handleConfigure.bind(this));
22
+ this.channel.registerHandler("connect", this.handleConnect.bind(this));
23
+ this.channel.registerHandler("get_stats", this.handleGetStats.bind(this));
24
+ this.channel.registerHandler(WorkerMessageType.Dispose, this.handleDispose.bind(this));
25
+ this.channel.receiveStream(this.handleInputStream.bind(this));
26
+ }
27
+ /**
28
+ * Unified connect handler used by stream pipeline
29
+ */
30
+ async handleConnect(payload) {
31
+ this.decoderPort = payload.port;
32
+ return { success: true };
33
+ }
34
+ /**
35
+ * Configure demuxer with format settings
36
+ * @param payload.config - Demuxer configuration
37
+ * @param payload.initial - If true, initialize worker state; otherwise just update config
38
+ */
39
+ async handleConfigure(payload) {
40
+ const { config, initial = false } = payload;
41
+ try {
42
+ if (initial) {
43
+ this.channel.state = WorkerState.Ready;
44
+ const format = config.container || this.detectFormat(config);
45
+ if (format === "mp3") {
46
+ this.mp3Parser = new MP3FrameParser();
47
+ this.demuxer?.destroy();
48
+ this.demuxer = null;
49
+ this.audioStream = null;
50
+ this.currentFormat = "mp3";
51
+ const mp3Track = { id: 1, type: "audio", codec: "mp3" };
52
+ this.channel.notify("configured", {
53
+ tracks: [mp3Track],
54
+ format,
55
+ codec: "mp3"
56
+ });
57
+ return { success: true, tracks: [mp3Track] };
58
+ } else if (format === "mp4" || format === "m4a") {
59
+ if (this.demuxer) {
60
+ this.demuxer.destroy();
61
+ }
62
+ this.demuxer = new MP4Demuxer({
63
+ ...config,
64
+ skipVideo: true
65
+ // Audio only
66
+ });
67
+ this.audioStream = this.demuxer.createAudioStream();
68
+ this.mp3Parser = null;
69
+ this.currentFormat = "mp4";
70
+ } else {
71
+ throw {
72
+ code: "UNSUPPORTED_FORMAT",
73
+ message: `Unsupported audio format: ${format}`
74
+ };
75
+ }
76
+ if (!this.audioStream) {
77
+ throw {
78
+ code: "NO_AUDIO_TRACK",
79
+ message: "No audio track found in container"
80
+ };
81
+ }
82
+ const tracks = Array.from(this.demuxer.tracks.values());
83
+ this.channel.notify("configured", {
84
+ tracks,
85
+ format,
86
+ codec: tracks[0]?.codec
87
+ });
88
+ return { success: true, tracks };
89
+ } else {
90
+ if (!this.demuxer) {
91
+ throw {
92
+ code: "NOT_INITIALIZED",
93
+ message: "Demuxer not initialized. Call configure with initial=true first"
94
+ };
95
+ }
96
+ return { success: true };
97
+ }
98
+ } catch (error) {
99
+ throw {
100
+ code: error.code || "CONFIG_ERROR",
101
+ message: error.message
102
+ };
103
+ }
104
+ }
105
+ /**
106
+ * Detect audio format from configuration
107
+ */
108
+ detectFormat(config) {
109
+ if (config.codec?.includes("mp3")) return "mp3";
110
+ if (config.codec?.includes("aac")) return "mp4";
111
+ if (config.codec?.includes("opus")) return "webm";
112
+ return "mp3";
113
+ }
114
+ /**
115
+ * Handle input stream from ResourceLoader (main thread)
116
+ */
117
+ async handleInputStream(stream, metadata) {
118
+ if (this.currentFormat === "mp3" && !this.mp3Parser) {
119
+ this.mp3Parser = new MP3FrameParser();
120
+ }
121
+ if (this.currentFormat === "mp4" && (!this.demuxer || !this.audioStream)) {
122
+ await this.handleConfigure({
123
+ config: { container: "mp4", highWaterMark: 10 },
124
+ initial: true
125
+ });
126
+ }
127
+ if (!this.decoderPort) {
128
+ throw new Error("Decoder not connected");
129
+ }
130
+ const decoderChannel = new WorkerChannel(this.decoderPort, {
131
+ name: "AudioDemux-Decoder",
132
+ timeout: 3e4
133
+ });
134
+ if (this.currentFormat === "mp3") {
135
+ await this.pipeMp3Stream(stream, decoderChannel, metadata);
136
+ } else if (this.demuxer && this.audioStream) {
137
+ const transformed = stream.pipeThrough(this.audioStream);
138
+ const trackInfo = Array.from(this.demuxer.tracks.values())[0];
139
+ await decoderChannel.sendStream(transformed, {
140
+ streamType: "audio",
141
+ clipId: metadata?.clipId ?? "default",
142
+ trackId: metadata?.trackId ?? "main",
143
+ codec: trackInfo?.codec ?? "mp4a.40.2",
144
+ sampleRate: trackInfo?.sampleRate ?? 44100,
145
+ numberOfChannels: trackInfo?.numberOfChannels ?? 2,
146
+ description: trackInfo?.description
147
+ });
148
+ this.channel.notify("demux_complete", {
149
+ tracksProcessed: this.demuxer?.tracks.size || 0
150
+ });
151
+ } else {
152
+ throw new Error("Audio demuxer not initialized");
153
+ }
154
+ }
155
+ async pipeMp3Stream(stream, decoderChannel, metadata) {
156
+ if (!this.mp3Parser) {
157
+ this.mp3Parser = new MP3FrameParser();
158
+ }
159
+ const reader = stream.getReader();
160
+ let currentConfig = null;
161
+ let configured = false;
162
+ const bufferedFrames = [];
163
+ let writer = null;
164
+ const ensureWriter = async () => {
165
+ if (!writer) {
166
+ const cfg = currentConfig;
167
+ if (!cfg) {
168
+ throw new Error("MP3 config missing while creating writer");
169
+ }
170
+ const transform = new TransformStream();
171
+ writer = transform.writable.getWriter();
172
+ await decoderChannel.sendStream(transform.readable, {
173
+ streamType: "audio",
174
+ clipId: metadata?.clipId ?? "default",
175
+ trackId: metadata?.trackId ?? "main",
176
+ codec: "mp3",
177
+ sampleRate: cfg.sampleRate,
178
+ numberOfChannels: cfg.channels,
179
+ description: void 0
180
+ });
181
+ }
182
+ return writer;
183
+ };
184
+ try {
185
+ while (true) {
186
+ const { done, value } = await reader.read();
187
+ if (done) {
188
+ break;
189
+ }
190
+ if (!value) {
191
+ continue;
192
+ }
193
+ const { frames, config } = this.mp3Parser.push(value);
194
+ if (config) {
195
+ currentConfig = config;
196
+ }
197
+ if (config && !configured) {
198
+ await decoderChannel.send("configure", {
199
+ streamType: "audio",
200
+ clipId: metadata?.clipId ?? "default",
201
+ codec: "mp3",
202
+ sampleRate: config.sampleRate,
203
+ numberOfChannels: config.channels,
204
+ description: void 0
205
+ });
206
+ this.channel.notify("demux_configured", {
207
+ clipId: metadata?.clipId ?? "default",
208
+ codec: "mp3",
209
+ sampleRate: config.sampleRate,
210
+ numberOfChannels: config.channels
211
+ });
212
+ configured = true;
213
+ }
214
+ if (config) {
215
+ this.currentFormat = "mp3";
216
+ }
217
+ if (!configured) {
218
+ bufferedFrames.push(...frames);
219
+ continue;
220
+ }
221
+ const targetWriter = await ensureWriter();
222
+ const readyFrames = bufferedFrames.splice(0, bufferedFrames.length);
223
+ readyFrames.push(...frames);
224
+ for (const frame of readyFrames) {
225
+ const chunk = new EncodedAudioChunk({
226
+ type: "key",
227
+ timestamp: frame.timestampUs,
228
+ duration: frame.durationUs,
229
+ data: frame.data.buffer.slice(
230
+ frame.data.byteOffset,
231
+ frame.data.byteOffset + frame.data.byteLength
232
+ )
233
+ });
234
+ await targetWriter.write(chunk);
235
+ }
236
+ }
237
+ const remaining = this.mp3Parser.flush();
238
+ if (remaining.length) {
239
+ if (!configured) {
240
+ throw new Error("MP3 stream ended before configuration");
241
+ }
242
+ const targetWriter = await ensureWriter();
243
+ for (const frame of remaining) {
244
+ const chunk = new EncodedAudioChunk({
245
+ type: "key",
246
+ timestamp: frame.timestampUs,
247
+ duration: frame.durationUs,
248
+ data: frame.data.buffer.slice(
249
+ frame.data.byteOffset,
250
+ frame.data.byteOffset + frame.data.byteLength
251
+ )
252
+ });
253
+ await targetWriter.write(chunk);
254
+ }
255
+ }
256
+ if (writer) {
257
+ await writer.close();
258
+ }
259
+ this.channel.notify("demux_complete", {
260
+ tracksProcessed: 1
261
+ });
262
+ } finally {
263
+ reader.releaseLock();
264
+ }
265
+ }
266
+ /**
267
+ * Get demuxer statistics
268
+ */
269
+ async handleGetStats() {
270
+ if (this.currentFormat === "mp3") {
271
+ return {
272
+ tracksInfo: this.mp3Parser ? [{ id: 1, type: "audio", codec: "mp3" }] : [],
273
+ format: "mp3",
274
+ state: this.channel.state
275
+ };
276
+ }
277
+ if (this.demuxer) {
278
+ return {
279
+ tracksInfo: Array.from(this.demuxer.tracks.values()),
280
+ format: "mp4",
281
+ state: this.channel.state
282
+ };
283
+ }
284
+ return { state: this.channel.state };
285
+ }
286
+ /**
287
+ * Dispose worker and cleanup resources
288
+ */
289
+ async handleDispose() {
290
+ if (this.demuxer) {
291
+ this.demuxer.destroy();
292
+ }
293
+ this.demuxer = null;
294
+ this.audioStream = null;
295
+ this.mp3Parser = null;
296
+ this.currentFormat = null;
297
+ this.decoderPort?.close();
298
+ this.decoderPort = null;
299
+ this.channel.state = WorkerState.Disposed;
300
+ return { success: true };
301
+ }
302
+ }
303
+ const worker = new AudioDemuxWorker();
304
+ self.addEventListener("beforeunload", () => {
305
+ worker["handleDispose"]();
306
+ });
307
+ const audioDemux_worker = null;
308
+ export {
309
+ AudioDemuxWorker,
310
+ audioDemux_worker as default
311
+ };
312
+ //# sourceMappingURL=audio-demux.worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audio-demux.worker.js","sources":["../../../src/stages/demux/audio-demux.worker.ts"],"sourcesContent":["import { WorkerChannel } from '../../worker/WorkerChannel';\nimport { WorkerMessageType, WorkerState } from '../../worker/types';\nimport { MP4Demuxer } from './MP4Demuxer';\nimport { MP3FrameParser, type MP3Config, type MP3Frame } from './MP3FrameParser';\nimport type { DemuxConfig } from './types';\n\n/**\n * AudioDemuxWorker - First stage for audio processing\n * Extracts audio tracks from various container formats (MP3, MP4/M4A, etc.)\n *\n * Pipeline: ResourceLoader (Main Thread) → AudioDemuxWorker → DecodeWorker\n *\n * Features:\n * - Multi-format support (MP3, AAC in MP4/M4A)\n * - Stream-based processing with backpressure\n * - Direct streaming to DecodeWorker\n */\nexport class AudioDemuxWorker {\n private channel: WorkerChannel;\n private demuxer: MP4Demuxer | null = null;\n private audioStream: TransformStream<Uint8Array, EncodedAudioChunk> | null = null;\n private mp3Parser: MP3FrameParser | null = null;\n private currentFormat: 'mp3' | 'mp4' | null = null;\n\n // Connection to decoder worker\n private decoderPort: MessagePort | null = null;\n\n constructor() {\n // Initialize WorkerChannel\n this.channel = new WorkerChannel(self as any, {\n name: 'AudioDemuxWorker',\n timeout: 30000,\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.handleConnect.bind(this));\n // Unified stream connect only\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 ResourceLoader (main thread)\n this.channel.receiveStream(this.handleInputStream.bind(this));\n }\n\n /**\n * Unified connect handler used by stream pipeline\n */\n private async handleConnect(payload: {\n direction: 'upstream';\n port: MessagePort;\n streamType: 'video' | 'audio' | 'frame' | 'chunk';\n }): Promise<{ success: boolean }> {\n this.decoderPort = payload.port;\n // Demux connects upstream to decoder\n return { success: true };\n }\n\n /**\n * Configure demuxer with format settings\n * @param payload.config - Demuxer configuration\n * @param payload.initial - If true, initialize worker state; otherwise just update config\n */\n private async handleConfigure(payload: {\n config: DemuxConfig;\n initial?: boolean;\n }): Promise<{ success: boolean; tracks?: any[] }> {\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 // Detect format and create appropriate demuxer\n const format = config.container || this.detectFormat(config);\n\n if (format === 'mp3') {\n this.mp3Parser = new MP3FrameParser();\n this.demuxer?.destroy();\n this.demuxer = null;\n this.audioStream = null;\n this.currentFormat = 'mp3';\n\n const mp3Track = { id: 1, type: 'audio', codec: 'mp3' };\n this.channel.notify('configured', {\n tracks: [mp3Track],\n format,\n codec: 'mp3',\n });\n\n return { success: true, tracks: [mp3Track] };\n } else if (format === 'mp4' || format === 'm4a') {\n if (this.demuxer) {\n this.demuxer.destroy();\n }\n\n this.demuxer = new MP4Demuxer({\n ...config,\n skipVideo: true, // Audio only\n });\n this.audioStream = this.demuxer.createAudioStream();\n this.mp3Parser = null;\n this.currentFormat = 'mp4';\n } else {\n throw {\n code: 'UNSUPPORTED_FORMAT',\n message: `Unsupported audio format: ${format}`,\n };\n }\n\n if (!this.audioStream) {\n throw {\n code: 'NO_AUDIO_TRACK',\n message: 'No audio track found in container',\n };\n }\n\n const tracks = Array.from(this.demuxer.tracks.values());\n\n // Notify configuration complete\n this.channel.notify('configured', {\n tracks,\n format,\n codec: tracks[0]?.codec,\n });\n\n return { success: true, tracks };\n } else {\n // Update configuration only (e.g., backpressure settings)\n if (!this.demuxer) {\n throw {\n code: 'NOT_INITIALIZED',\n message: 'Demuxer not initialized. Call configure with initial=true first',\n };\n }\n\n // Demuxers don't support runtime config updates\n // Would need initial=true for changes\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 * Detect audio format from configuration\n */\n private detectFormat(config: DemuxConfig): string {\n // Simple format detection based on codec or file extension\n if (config.codec?.includes('mp3')) return 'mp3';\n if (config.codec?.includes('aac')) return 'mp4';\n if (config.codec?.includes('opus')) return 'webm';\n\n return 'mp3';\n }\n\n /**\n * Handle input stream from ResourceLoader (main thread)\n */\n private async handleInputStream(\n stream: ReadableStream<Uint8Array>,\n metadata?: Record<string, any>\n ): Promise<void> {\n // Initialize demuxer if not configured\n if (this.currentFormat === 'mp3' && !this.mp3Parser) {\n this.mp3Parser = new MP3FrameParser();\n }\n\n if (this.currentFormat === 'mp4' && (!this.demuxer || !this.audioStream)) {\n await this.handleConfigure({\n config: { container: 'mp4', highWaterMark: 10 },\n initial: true,\n });\n }\n\n if (!this.decoderPort) {\n throw new Error('Decoder not connected');\n }\n\n // Setup channel to decoder\n const decoderChannel = new WorkerChannel(this.decoderPort, {\n name: 'AudioDemux-Decoder',\n timeout: 30000,\n });\n\n if (this.currentFormat === 'mp3') {\n await this.pipeMp3Stream(stream, decoderChannel, metadata);\n } else if (this.demuxer && this.audioStream) {\n const transformed = stream.pipeThrough(this.audioStream);\n const trackInfo = Array.from(this.demuxer.tracks.values())[0];\n\n await decoderChannel.sendStream(transformed, {\n streamType: 'audio',\n clipId: metadata?.clipId ?? 'default',\n trackId: metadata?.trackId ?? 'main',\n codec: trackInfo?.codec ?? 'mp4a.40.2',\n sampleRate: trackInfo?.sampleRate ?? 44_100,\n numberOfChannels: trackInfo?.numberOfChannels ?? 2,\n description: trackInfo?.description,\n });\n\n this.channel.notify('demux_complete', {\n tracksProcessed: this.demuxer?.tracks.size || 0,\n });\n } else {\n throw new Error('Audio demuxer not initialized');\n }\n }\n\n private async pipeMp3Stream(\n stream: ReadableStream<Uint8Array>,\n decoderChannel: WorkerChannel,\n metadata?: Record<string, any>\n ): Promise<void> {\n if (!this.mp3Parser) {\n this.mp3Parser = new MP3FrameParser();\n }\n\n const reader = stream.getReader();\n let currentConfig: MP3Config | null = null;\n let configured = false;\n const bufferedFrames: MP3Frame[] = [];\n let writer: WritableStreamDefaultWriter<EncodedAudioChunk> | null = null;\n\n const ensureWriter = async (): Promise<WritableStreamDefaultWriter<EncodedAudioChunk>> => {\n if (!writer) {\n const cfg = currentConfig;\n if (!cfg) {\n throw new Error('MP3 config missing while creating writer');\n }\n const transform = new TransformStream<EncodedAudioChunk, EncodedAudioChunk>();\n writer = transform.writable.getWriter();\n await decoderChannel.sendStream(transform.readable, {\n streamType: 'audio',\n clipId: metadata?.clipId ?? 'default',\n trackId: metadata?.trackId ?? 'main',\n codec: 'mp3',\n sampleRate: cfg.sampleRate,\n numberOfChannels: cfg.channels,\n description: undefined,\n });\n }\n return writer!;\n };\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n\n if (!value) {\n continue;\n }\n\n const { frames, config } = this.mp3Parser.push(value);\n\n if (config) {\n currentConfig = config;\n }\n\n if (config && !configured) {\n await decoderChannel.send('configure' as any, {\n streamType: 'audio',\n clipId: metadata?.clipId ?? 'default',\n codec: 'mp3',\n sampleRate: config.sampleRate,\n numberOfChannels: config.channels,\n description: undefined,\n });\n this.channel.notify('demux_configured', {\n clipId: metadata?.clipId ?? 'default',\n codec: 'mp3',\n sampleRate: config.sampleRate,\n numberOfChannels: config.channels,\n });\n configured = true;\n }\n\n if (config) {\n this.currentFormat = 'mp3';\n }\n\n if (!configured) {\n bufferedFrames.push(...frames);\n continue;\n }\n\n const targetWriter = await ensureWriter();\n const readyFrames = bufferedFrames.splice(0, bufferedFrames.length);\n readyFrames.push(...frames);\n for (const frame of readyFrames) {\n const chunk = new EncodedAudioChunk({\n type: 'key',\n timestamp: frame.timestampUs,\n duration: frame.durationUs,\n data: frame.data.buffer.slice(\n frame.data.byteOffset,\n frame.data.byteOffset + frame.data.byteLength\n ),\n });\n await targetWriter.write(chunk);\n }\n }\n\n const remaining = this.mp3Parser.flush();\n if (remaining.length) {\n if (!configured) {\n throw new Error('MP3 stream ended before configuration');\n }\n const targetWriter = await ensureWriter();\n for (const frame of remaining) {\n const chunk = new EncodedAudioChunk({\n type: 'key',\n timestamp: frame.timestampUs,\n duration: frame.durationUs,\n data: frame.data.buffer.slice(\n frame.data.byteOffset,\n frame.data.byteOffset + frame.data.byteLength\n ),\n });\n await targetWriter.write(chunk);\n }\n }\n\n if (writer) {\n await (writer as WritableStreamDefaultWriter<EncodedAudioChunk>).close();\n }\n\n this.channel.notify('demux_complete', {\n tracksProcessed: 1,\n });\n } finally {\n reader.releaseLock();\n }\n }\n\n /**\n * Get demuxer statistics\n */\n private async handleGetStats(): Promise<{\n queueSize?: number;\n tracksInfo?: any[];\n format?: string;\n state?: WorkerState;\n }> {\n if (this.currentFormat === 'mp3') {\n return {\n tracksInfo: this.mp3Parser ? [{ id: 1, type: 'audio', codec: 'mp3' }] : [],\n format: 'mp3',\n state: this.channel.state,\n };\n }\n\n if (this.demuxer) {\n return {\n tracksInfo: Array.from(this.demuxer.tracks.values()),\n format: 'mp4',\n state: this.channel.state,\n };\n }\n\n return { state: this.channel.state };\n }\n\n /**\n * Dispose worker and cleanup resources\n */\n private async handleDispose(): Promise<{ success: boolean }> {\n if (this.demuxer) {\n this.demuxer.destroy();\n }\n this.demuxer = null;\n this.audioStream = null;\n this.mp3Parser = null;\n this.currentFormat = null;\n\n this.decoderPort?.close();\n this.decoderPort = null;\n\n this.channel.state = WorkerState.Disposed;\n\n return { success: true };\n }\n}\n\n// Initialize worker\nconst worker = new AudioDemuxWorker();\n\n// Handle worker termination\nself.addEventListener('beforeunload', () => {\n worker['handleDispose']();\n});\n\nexport default null; // Required for TypeScript worker compilation\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,77 @@
1
+ export interface DemuxConfig {
2
+ codec?: string;
3
+ trackId?: string;
4
+ container?: 'mp4' | 'webm';
5
+ highWaterMark?: number;
6
+ streaming?: {
7
+ batchSize?: number;
8
+ highWaterMark?: number;
9
+ sizeStrategy?: 'count' | 'bytes';
10
+ progressive?: boolean;
11
+ minBufferSize?: number;
12
+ };
13
+ performance?: {
14
+ immediateRelease?: boolean;
15
+ maxMemory?: number;
16
+ hardwareAcceleration?: boolean;
17
+ };
18
+ tracks?: {
19
+ videoTracks?: number[];
20
+ audioTracks?: number[];
21
+ };
22
+ skipVideo?: boolean;
23
+ skipAudio?: boolean;
24
+ }
25
+ export interface DemuxSample {
26
+ timestamp: number;
27
+ duration: number;
28
+ data: ArrayBuffer;
29
+ isKeyFrame: boolean;
30
+ trackId: string;
31
+ }
32
+ export interface TrackInfo {
33
+ id: number;
34
+ type: 'video' | 'audio';
35
+ codec: string;
36
+ width?: number;
37
+ height?: number;
38
+ sampleRate?: number;
39
+ numberOfChannels?: number;
40
+ bitrate?: number;
41
+ duration?: number;
42
+ timescale?: number;
43
+ description?: ArrayBuffer;
44
+ }
45
+ export interface DemuxerEvents {
46
+ onReady: (info: {
47
+ tracks: TrackInfo[];
48
+ }) => void;
49
+ onSamples: (samples: DemuxSample[]) => void;
50
+ onError: (error: Error) => void;
51
+ onComplete: () => void;
52
+ }
53
+ export interface BaseDemuxer {
54
+ configure(config: DemuxConfig): Promise<void>;
55
+ appendBuffer(buffer: ArrayBuffer): void;
56
+ flush(): void;
57
+ reset(): void;
58
+ destroy(): void;
59
+ }
60
+ export interface MP4DemuxInfo {
61
+ duration: number;
62
+ timescale: number;
63
+ isFragmented: boolean;
64
+ isProgressive: boolean;
65
+ hasIOD: boolean;
66
+ brands: string[];
67
+ created: Date;
68
+ modified: Date;
69
+ tracks: TrackInfo[];
70
+ }
71
+ export interface AudioDemuxConfig extends DemuxConfig {
72
+ codec: 'aac' | 'opus';
73
+ }
74
+ export interface VideoDemuxConfig extends DemuxConfig {
75
+ codec: 'h264' | 'h265' | 'vp9' | 'av1';
76
+ }
77
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/stages/demux/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * VideoDemuxWorker - First stage for video processing
3
+ * Extracts video tracks from container formats (MP4, etc.)
4
+ *
5
+ * Pipeline: ResourceLoader (Main Thread) → VideoDemuxWorker → DecodeWorker
6
+ *
7
+ * Features:
8
+ * - MP4 container demuxing with mp4box.js
9
+ * - Stream-based processing with backpressure
10
+ * - Direct streaming to DecodeWorker
11
+ */
12
+ export declare class VideoDemuxWorker {
13
+ private channel;
14
+ private demuxer;
15
+ private resourceId;
16
+ private clipId?;
17
+ private downstreamPort;
18
+ private range?;
19
+ constructor();
20
+ protected setupHandlers(): void;
21
+ /**
22
+ * Handle connection from orchestrator
23
+ */
24
+ private handleConnect;
25
+ /**
26
+ * Configure demuxer with format settings
27
+ * @param payload.config - Demuxer configuration
28
+ * @param payload.initial - If true, initialize worker state; otherwise just update config
29
+ */
30
+ private handleConfigure;
31
+ /**
32
+ * Handle input stream from ResourceLoader (main thread)
33
+ * Strategy: Stream immediately, send codec info when ready
34
+ */
35
+ private handleReceiveStream;
36
+ private handleDemuxerReady;
37
+ /**
38
+ * Get demuxer statistics
39
+ */
40
+ private handleGetStats;
41
+ /**
42
+ * Dispose worker and cleanup resources
43
+ */
44
+ private handleDispose;
45
+ }
46
+ declare const _default: null;
47
+ export default _default;
48
+ //# sourceMappingURL=video-demux.worker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"video-demux.worker.d.ts","sourceRoot":"","sources":["../../../src/stages/demux/video-demux.worker.ts"],"names":[],"mappings":"AAaA;;;;;;;;;;GAUG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,OAAO,CAA2B;IAC1C,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,MAAM,CAAC,CAAS;IACxB,OAAO,CAAC,cAAc,CAA4B;IAClD,OAAO,CAAC,KAAK,CAAC,CAAiC;;IAY/C,SAAS,CAAC,aAAa,IAAI,IAAI;IAW/B;;OAEG;YACW,aAAa;IAkB3B;;;;OAIG;YACW,eAAe;IAuC7B;;;OAGG;YACW,mBAAmB;IA+DjC,OAAO,CAAC,kBAAkB;IA2B1B;;OAEG;YACW,cAAc;IAe5B;;OAEG;YACW,aAAa;CAc5B;;AASD,wBAAoB"}
@@ -0,0 +1,173 @@
1
+ import { WorkerChannel } from "../../worker/WorkerChannel.js";
2
+ import { WorkerMessageType, WorkerState } from "../../worker/types.js";
3
+ import { MP4Demuxer } from "./MP4Demuxer.js";
4
+ class VideoDemuxWorker {
5
+ channel;
6
+ demuxer = null;
7
+ resourceId = null;
8
+ clipId;
9
+ downstreamPort = null;
10
+ range;
11
+ constructor() {
12
+ this.channel = new WorkerChannel(self, {
13
+ name: "VideoDemuxWorker",
14
+ timeout: 3e4
15
+ });
16
+ this.setupHandlers();
17
+ }
18
+ /* @better-ai.mdc For test visibility */
19
+ setupHandlers() {
20
+ this.channel.registerHandler("configure", this.handleConfigure.bind(this));
21
+ this.channel.registerHandler("connect", this.handleConnect.bind(this));
22
+ this.channel.registerHandler("get_stats", this.handleGetStats.bind(this));
23
+ this.channel.registerHandler(WorkerMessageType.Dispose, this.handleDispose.bind(this));
24
+ this.channel.receiveStream(this.handleReceiveStream.bind(this));
25
+ }
26
+ /**
27
+ * Handle connection from orchestrator
28
+ */
29
+ async handleConnect(payload) {
30
+ const { port, clipId } = payload;
31
+ if (!port) {
32
+ return { success: false };
33
+ }
34
+ this.downstreamPort = port;
35
+ this.clipId = clipId;
36
+ return { success: true };
37
+ }
38
+ /**
39
+ * Configure demuxer with format settings
40
+ * @param payload.config - Demuxer configuration
41
+ * @param payload.initial - If true, initialize worker state; otherwise just update config
42
+ */
43
+ async handleConfigure(payload) {
44
+ const { config, initial = false } = payload;
45
+ try {
46
+ if (initial) {
47
+ this.channel.state = WorkerState.Ready;
48
+ if (this.demuxer) {
49
+ this.demuxer.destroy();
50
+ }
51
+ this.demuxer = new MP4Demuxer({
52
+ ...config,
53
+ skipAudio: true,
54
+ // Video only
55
+ onReady: () => this.handleDemuxerReady()
56
+ });
57
+ this.channel.notify("configured");
58
+ return { success: true };
59
+ } else {
60
+ this.demuxer?.updateConfig(config);
61
+ return { success: true };
62
+ }
63
+ } catch (error) {
64
+ throw {
65
+ code: error.code || "CONFIG_ERROR",
66
+ message: error.message
67
+ };
68
+ }
69
+ }
70
+ /**
71
+ * Handle input stream from ResourceLoader (main thread)
72
+ * Strategy: Stream immediately, send codec info when ready
73
+ */
74
+ async handleReceiveStream(stream, metadata) {
75
+ console.log("[VideoDemuxWorker] handleReceiveStream", metadata?.clipId, metadata?.resourceId);
76
+ const currentResourceId = metadata?.resourceId || metadata?.clipId || this.resourceId || "default";
77
+ const clipId = metadata?.clipId;
78
+ if (this.resourceId && this.resourceId !== currentResourceId) {
79
+ throw new Error(
80
+ `[VideoDemuxWorker] BUG: Resource ID changed from ${this.resourceId} to ${currentResourceId}. Each VideoDemuxWorker instance should only handle one resource.`
81
+ );
82
+ }
83
+ if (!this.resourceId) {
84
+ this.resourceId = currentResourceId;
85
+ }
86
+ if (!this.demuxer) {
87
+ this.demuxer = new MP4Demuxer({
88
+ highWaterMark: 10,
89
+ skipAudio: true,
90
+ // Video only
91
+ onReady: () => this.handleDemuxerReady()
92
+ });
93
+ }
94
+ if (!this.downstreamPort) {
95
+ throw new Error("Decoder not connected");
96
+ }
97
+ if (clipId) {
98
+ this.clipId = clipId;
99
+ }
100
+ if (metadata?.range) {
101
+ this.range = metadata.range;
102
+ }
103
+ const videoStream = this.demuxer.createVideoStream();
104
+ const downstreamChannel = new WorkerChannel(this.downstreamPort, {
105
+ name: "VideoDemux-Decoder",
106
+ timeout: 3e4
107
+ });
108
+ downstreamChannel.sendStream(videoStream.readable, {
109
+ streamType: "video",
110
+ clipId: this.clipId,
111
+ ...this.range && { range: this.range }
112
+ // codec info will be sent separately when ready
113
+ });
114
+ await stream.pipeTo(videoStream.writable);
115
+ }
116
+ handleDemuxerReady() {
117
+ if (!this.demuxer || !this.downstreamPort) {
118
+ return;
119
+ }
120
+ const videoTrackInfo = this.demuxer.videoTrackInfo;
121
+ if (!videoTrackInfo) {
122
+ console.error("[VideoDemuxWorker] No video track found after ready");
123
+ return;
124
+ }
125
+ const downstreamChannel = new WorkerChannel(this.downstreamPort, {
126
+ name: "VideoDemux-Decoder",
127
+ timeout: 3e4
128
+ });
129
+ downstreamChannel.send("configure", {
130
+ clipId: this.clipId,
131
+ streamType: "video",
132
+ codec: videoTrackInfo.codec,
133
+ width: videoTrackInfo.width,
134
+ height: videoTrackInfo.height,
135
+ ...this.range && { range: this.range },
136
+ description: videoTrackInfo.description
137
+ });
138
+ }
139
+ /**
140
+ * Get demuxer statistics
141
+ */
142
+ async handleGetStats() {
143
+ if (!this.demuxer) {
144
+ return { state: this.channel.state };
145
+ }
146
+ return {
147
+ tracksInfo: Array.from(this.demuxer.tracks.values()),
148
+ state: this.channel.state
149
+ };
150
+ }
151
+ /**
152
+ * Dispose worker and cleanup resources
153
+ */
154
+ async handleDispose() {
155
+ this.demuxer?.destroy();
156
+ this.demuxer = null;
157
+ this.resourceId = null;
158
+ this.downstreamPort?.close();
159
+ this.downstreamPort = null;
160
+ this.channel.state = WorkerState.Disposed;
161
+ return { success: true };
162
+ }
163
+ }
164
+ const worker = new VideoDemuxWorker();
165
+ self.addEventListener("beforeunload", () => {
166
+ worker["handleDispose"]();
167
+ });
168
+ const videoDemux_worker = null;
169
+ export {
170
+ VideoDemuxWorker,
171
+ videoDemux_worker as default
172
+ };
173
+ //# sourceMappingURL=video-demux.worker.js.map