@editframe/elements 0.16.8-beta.0 → 0.18.3-beta.0

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 (267) hide show
  1. package/README.md +30 -0
  2. package/dist/DecoderResetFrequency.test.d.ts +1 -0
  3. package/dist/DecoderResetRecovery.test.d.ts +1 -0
  4. package/dist/DelayedLoadingState.d.ts +48 -0
  5. package/dist/DelayedLoadingState.integration.test.d.ts +1 -0
  6. package/dist/DelayedLoadingState.js +113 -0
  7. package/dist/DelayedLoadingState.test.d.ts +1 -0
  8. package/dist/EF_FRAMEGEN.d.ts +10 -1
  9. package/dist/EF_FRAMEGEN.js +199 -179
  10. package/dist/EF_INTERACTIVE.js +2 -6
  11. package/dist/EF_RENDERING.js +1 -3
  12. package/dist/LoadingDebounce.test.d.ts +1 -0
  13. package/dist/LoadingIndicator.browsertest.d.ts +0 -0
  14. package/dist/ManualScrubTest.test.d.ts +1 -0
  15. package/dist/ScrubResolvedFlashing.test.d.ts +1 -0
  16. package/dist/ScrubTrackManager.d.ts +96 -0
  17. package/dist/ScrubTrackManager.test.d.ts +1 -0
  18. package/dist/VideoSeekFlashing.browsertest.d.ts +0 -0
  19. package/dist/VideoStuckDiagnostic.test.d.ts +1 -0
  20. package/dist/elements/CrossUpdateController.js +13 -15
  21. package/dist/elements/EFAudio.browsertest.d.ts +0 -0
  22. package/dist/elements/EFAudio.d.ts +22 -3
  23. package/dist/elements/EFAudio.js +60 -43
  24. package/dist/elements/EFCaptions.js +337 -373
  25. package/dist/elements/EFImage.d.ts +1 -0
  26. package/dist/elements/EFImage.js +73 -91
  27. package/dist/elements/EFMedia/AssetIdMediaEngine.d.ts +18 -0
  28. package/dist/elements/EFMedia/AssetIdMediaEngine.js +41 -0
  29. package/dist/elements/EFMedia/AssetIdMediaEngine.test.d.ts +1 -0
  30. package/dist/elements/EFMedia/AssetMediaEngine.d.ts +47 -0
  31. package/dist/elements/EFMedia/AssetMediaEngine.js +116 -0
  32. package/dist/elements/EFMedia/BaseMediaEngine.d.ts +55 -0
  33. package/dist/elements/EFMedia/BaseMediaEngine.js +96 -0
  34. package/dist/elements/EFMedia/BaseMediaEngine.test.d.ts +1 -0
  35. package/dist/elements/EFMedia/BufferedSeekingInput.browsertest.d.ts +1 -0
  36. package/dist/elements/EFMedia/BufferedSeekingInput.d.ts +43 -0
  37. package/dist/elements/EFMedia/BufferedSeekingInput.js +159 -0
  38. package/dist/elements/EFMedia/JitMediaEngine.browsertest.d.ts +0 -0
  39. package/dist/elements/EFMedia/JitMediaEngine.d.ts +31 -0
  40. package/dist/elements/EFMedia/JitMediaEngine.js +62 -0
  41. package/dist/elements/EFMedia/audioTasks/makeAudioBufferTask.browsertest.d.ts +9 -0
  42. package/dist/elements/EFMedia/audioTasks/makeAudioBufferTask.d.ts +16 -0
  43. package/dist/elements/EFMedia/audioTasks/makeAudioBufferTask.js +48 -0
  44. package/dist/elements/EFMedia/audioTasks/makeAudioFrequencyAnalysisTask.d.ts +3 -0
  45. package/dist/elements/EFMedia/audioTasks/makeAudioFrequencyAnalysisTask.js +138 -0
  46. package/dist/elements/EFMedia/audioTasks/makeAudioInitSegmentFetchTask.browsertest.d.ts +9 -0
  47. package/dist/elements/EFMedia/audioTasks/makeAudioInitSegmentFetchTask.d.ts +4 -0
  48. package/dist/elements/EFMedia/audioTasks/makeAudioInitSegmentFetchTask.js +16 -0
  49. package/dist/elements/EFMedia/audioTasks/makeAudioInputTask.browsertest.d.ts +9 -0
  50. package/dist/elements/EFMedia/audioTasks/makeAudioInputTask.d.ts +3 -0
  51. package/dist/elements/EFMedia/audioTasks/makeAudioInputTask.js +22 -0
  52. package/dist/elements/EFMedia/audioTasks/makeAudioSeekTask.d.ts +7 -0
  53. package/dist/elements/EFMedia/audioTasks/makeAudioSeekTask.js +24 -0
  54. package/dist/elements/EFMedia/audioTasks/makeAudioSegmentFetchTask.d.ts +4 -0
  55. package/dist/elements/EFMedia/audioTasks/makeAudioSegmentFetchTask.js +18 -0
  56. package/dist/elements/EFMedia/audioTasks/makeAudioSegmentIdTask.d.ts +4 -0
  57. package/dist/elements/EFMedia/audioTasks/makeAudioSegmentIdTask.js +16 -0
  58. package/dist/elements/EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.d.ts +3 -0
  59. package/dist/elements/EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.js +104 -0
  60. package/dist/elements/EFMedia/services/AudioElementFactory.browsertest.d.ts +1 -0
  61. package/dist/elements/EFMedia/services/AudioElementFactory.d.ts +22 -0
  62. package/dist/elements/EFMedia/services/AudioElementFactory.js +72 -0
  63. package/dist/elements/EFMedia/services/MediaSourceService.browsertest.d.ts +1 -0
  64. package/dist/elements/EFMedia/services/MediaSourceService.d.ts +47 -0
  65. package/dist/elements/EFMedia/services/MediaSourceService.js +73 -0
  66. package/dist/elements/EFMedia/shared/AudioSpanUtils.d.ts +7 -0
  67. package/dist/elements/EFMedia/shared/AudioSpanUtils.js +54 -0
  68. package/dist/elements/EFMedia/shared/BufferUtils.d.ts +70 -0
  69. package/dist/elements/EFMedia/shared/BufferUtils.js +89 -0
  70. package/dist/elements/EFMedia/shared/MediaTaskUtils.d.ts +23 -0
  71. package/dist/elements/EFMedia/shared/RenditionHelpers.browsertest.d.ts +1 -0
  72. package/dist/elements/EFMedia/shared/RenditionHelpers.d.ts +19 -0
  73. package/dist/elements/EFMedia/tasks/makeMediaEngineTask.browsertest.d.ts +1 -0
  74. package/dist/elements/EFMedia/tasks/makeMediaEngineTask.d.ts +18 -0
  75. package/dist/elements/EFMedia/tasks/makeMediaEngineTask.js +60 -0
  76. package/dist/elements/EFMedia/tasks/makeMediaEngineTask.test.d.ts +1 -0
  77. package/dist/elements/EFMedia/videoTasks/makeVideoBufferTask.browsertest.d.ts +9 -0
  78. package/dist/elements/EFMedia/videoTasks/makeVideoBufferTask.d.ts +16 -0
  79. package/dist/elements/EFMedia/videoTasks/makeVideoBufferTask.js +46 -0
  80. package/dist/elements/EFMedia/videoTasks/makeVideoInitSegmentFetchTask.browsertest.d.ts +9 -0
  81. package/dist/elements/EFMedia/videoTasks/makeVideoInitSegmentFetchTask.d.ts +4 -0
  82. package/dist/elements/EFMedia/videoTasks/makeVideoInitSegmentFetchTask.js +16 -0
  83. package/dist/elements/EFMedia/videoTasks/makeVideoInputTask.browsertest.d.ts +9 -0
  84. package/dist/elements/EFMedia/videoTasks/makeVideoInputTask.d.ts +3 -0
  85. package/dist/elements/EFMedia/videoTasks/makeVideoInputTask.js +27 -0
  86. package/dist/elements/EFMedia/videoTasks/makeVideoSeekTask.d.ts +7 -0
  87. package/dist/elements/EFMedia/videoTasks/makeVideoSeekTask.js +25 -0
  88. package/dist/elements/EFMedia/videoTasks/makeVideoSegmentFetchTask.browsertest.d.ts +9 -0
  89. package/dist/elements/EFMedia/videoTasks/makeVideoSegmentFetchTask.d.ts +4 -0
  90. package/dist/elements/EFMedia/videoTasks/makeVideoSegmentFetchTask.js +18 -0
  91. package/dist/elements/EFMedia/videoTasks/makeVideoSegmentIdTask.browsertest.d.ts +9 -0
  92. package/dist/elements/EFMedia/videoTasks/makeVideoSegmentIdTask.d.ts +4 -0
  93. package/dist/elements/EFMedia/videoTasks/makeVideoSegmentIdTask.js +16 -0
  94. package/dist/elements/EFMedia.browsertest.d.ts +1 -0
  95. package/dist/elements/EFMedia.d.ts +95 -66
  96. package/dist/elements/EFMedia.js +204 -683
  97. package/dist/elements/EFSourceMixin.js +31 -48
  98. package/dist/elements/EFTemporal.d.ts +2 -1
  99. package/dist/elements/EFTemporal.js +266 -360
  100. package/dist/elements/EFTimegroup.d.ts +14 -1
  101. package/dist/elements/EFTimegroup.js +337 -323
  102. package/dist/elements/EFVideo.browsertest.d.ts +0 -0
  103. package/dist/elements/EFVideo.d.ts +123 -4
  104. package/dist/elements/EFVideo.js +308 -111
  105. package/dist/elements/EFWaveform.js +375 -411
  106. package/dist/elements/FetchMixin.js +14 -24
  107. package/dist/elements/MediaController.d.ts +30 -0
  108. package/dist/elements/SampleBuffer.d.ts +14 -0
  109. package/dist/elements/SampleBuffer.js +52 -0
  110. package/dist/elements/TargetController.js +130 -156
  111. package/dist/elements/TimegroupController.js +17 -19
  112. package/dist/elements/durationConverter.js +15 -4
  113. package/dist/elements/parseTimeToMs.js +4 -10
  114. package/dist/elements/printTaskStatus.d.ts +2 -0
  115. package/dist/elements/updateAnimations.js +39 -59
  116. package/dist/getRenderInfo.d.ts +2 -2
  117. package/dist/getRenderInfo.js +59 -67
  118. package/dist/gui/ContextMixin.js +150 -288
  119. package/dist/gui/EFConfiguration.js +27 -43
  120. package/dist/gui/EFFilmstrip.d.ts +3 -3
  121. package/dist/gui/EFFilmstrip.js +440 -620
  122. package/dist/gui/EFFitScale.d.ts +2 -2
  123. package/dist/gui/EFFitScale.js +112 -135
  124. package/dist/gui/EFFocusOverlay.js +45 -61
  125. package/dist/gui/EFPreview.js +30 -49
  126. package/dist/gui/EFScrubber.js +78 -99
  127. package/dist/gui/EFTimeDisplay.js +49 -70
  128. package/dist/gui/EFToggleLoop.js +17 -34
  129. package/dist/gui/EFTogglePlay.js +37 -58
  130. package/dist/gui/EFWorkbench.js +66 -88
  131. package/dist/gui/TWMixin.js +2 -48
  132. package/dist/gui/TWMixin2.js +31 -0
  133. package/dist/gui/efContext.js +2 -6
  134. package/dist/gui/fetchContext.js +1 -3
  135. package/dist/gui/focusContext.js +1 -3
  136. package/dist/gui/focusedElementContext.js +2 -6
  137. package/dist/gui/playingContext.js +1 -4
  138. package/dist/gui/services/ElementConnectionManager.browsertest.d.ts +1 -0
  139. package/dist/gui/services/ElementConnectionManager.d.ts +59 -0
  140. package/dist/gui/services/ElementConnectionManager.js +128 -0
  141. package/dist/gui/services/PlaybackController.browsertest.d.ts +1 -0
  142. package/dist/gui/services/PlaybackController.d.ts +103 -0
  143. package/dist/gui/services/PlaybackController.js +290 -0
  144. package/dist/index.js +5 -30
  145. package/dist/msToTimeCode.js +11 -13
  146. package/dist/services/MediaSourceManager.d.ts +62 -0
  147. package/dist/services/MediaSourceManager.js +211 -0
  148. package/dist/style.css +2 -1
  149. package/dist/transcoding/cache/CacheManager.d.ts +73 -0
  150. package/dist/transcoding/cache/RequestDeduplicator.d.ts +29 -0
  151. package/dist/transcoding/cache/RequestDeduplicator.js +53 -0
  152. package/dist/transcoding/cache/RequestDeduplicator.test.d.ts +1 -0
  153. package/dist/transcoding/types/index.d.ts +242 -0
  154. package/dist/transcoding/utils/MediaUtils.d.ts +9 -0
  155. package/dist/transcoding/utils/UrlGenerator.d.ts +26 -0
  156. package/dist/transcoding/utils/UrlGenerator.js +45 -0
  157. package/dist/transcoding/utils/constants.d.ts +27 -0
  158. package/dist/utils/LRUCache.d.ts +34 -0
  159. package/dist/utils/LRUCache.js +115 -0
  160. package/package.json +4 -3
  161. package/src/elements/EFAudio.browsertest.ts +709 -0
  162. package/src/elements/EFAudio.ts +59 -15
  163. package/src/elements/EFCaptions.browsertest.ts +0 -1
  164. package/src/elements/EFImage.browsertest.ts +42 -1
  165. package/src/elements/EFImage.ts +23 -3
  166. package/src/elements/EFMedia/AssetIdMediaEngine.test.ts +222 -0
  167. package/src/elements/EFMedia/AssetIdMediaEngine.ts +70 -0
  168. package/src/elements/EFMedia/AssetMediaEngine.ts +210 -0
  169. package/src/elements/EFMedia/BaseMediaEngine.test.ts +164 -0
  170. package/src/elements/EFMedia/BaseMediaEngine.ts +170 -0
  171. package/src/elements/EFMedia/BufferedSeekingInput.browsertest.ts +400 -0
  172. package/src/elements/EFMedia/BufferedSeekingInput.ts +267 -0
  173. package/src/elements/EFMedia/JitMediaEngine.browsertest.ts +165 -0
  174. package/src/elements/EFMedia/JitMediaEngine.ts +110 -0
  175. package/src/elements/EFMedia/audioTasks/makeAudioBufferTask.browsertest.ts +554 -0
  176. package/src/elements/EFMedia/audioTasks/makeAudioBufferTask.ts +81 -0
  177. package/src/elements/EFMedia/audioTasks/makeAudioFrequencyAnalysisTask.ts +241 -0
  178. package/src/elements/EFMedia/audioTasks/makeAudioInitSegmentFetchTask.browsertest.ts +59 -0
  179. package/src/elements/EFMedia/audioTasks/makeAudioInitSegmentFetchTask.ts +23 -0
  180. package/src/elements/EFMedia/audioTasks/makeAudioInputTask.browsertest.ts +55 -0
  181. package/src/elements/EFMedia/audioTasks/makeAudioInputTask.ts +35 -0
  182. package/src/elements/EFMedia/audioTasks/makeAudioSeekTask.ts +42 -0
  183. package/src/elements/EFMedia/audioTasks/makeAudioSegmentFetchTask.ts +34 -0
  184. package/src/elements/EFMedia/audioTasks/makeAudioSegmentIdTask.ts +23 -0
  185. package/src/elements/EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.ts +174 -0
  186. package/src/elements/EFMedia/services/AudioElementFactory.browsertest.ts +325 -0
  187. package/src/elements/EFMedia/services/AudioElementFactory.ts +119 -0
  188. package/src/elements/EFMedia/services/MediaSourceService.browsertest.ts +257 -0
  189. package/src/elements/EFMedia/services/MediaSourceService.ts +102 -0
  190. package/src/elements/EFMedia/shared/AudioSpanUtils.ts +128 -0
  191. package/src/elements/EFMedia/shared/BufferUtils.ts +310 -0
  192. package/src/elements/EFMedia/shared/MediaTaskUtils.ts +44 -0
  193. package/src/elements/EFMedia/shared/RenditionHelpers.browsertest.ts +247 -0
  194. package/src/elements/EFMedia/shared/RenditionHelpers.ts +79 -0
  195. package/src/elements/EFMedia/tasks/makeMediaEngineTask.browsertest.ts +128 -0
  196. package/src/elements/EFMedia/tasks/makeMediaEngineTask.test.ts +233 -0
  197. package/src/elements/EFMedia/tasks/makeMediaEngineTask.ts +89 -0
  198. package/src/elements/EFMedia/videoTasks/makeVideoBufferTask.browsertest.ts +555 -0
  199. package/src/elements/EFMedia/videoTasks/makeVideoBufferTask.ts +79 -0
  200. package/src/elements/EFMedia/videoTasks/makeVideoInitSegmentFetchTask.browsertest.ts +59 -0
  201. package/src/elements/EFMedia/videoTasks/makeVideoInitSegmentFetchTask.ts +23 -0
  202. package/src/elements/EFMedia/videoTasks/makeVideoInputTask.browsertest.ts +55 -0
  203. package/src/elements/EFMedia/videoTasks/makeVideoInputTask.ts +45 -0
  204. package/src/elements/EFMedia/videoTasks/makeVideoSeekTask.ts +44 -0
  205. package/src/elements/EFMedia/videoTasks/makeVideoSegmentFetchTask.browsertest.ts +57 -0
  206. package/src/elements/EFMedia/videoTasks/makeVideoSegmentFetchTask.ts +32 -0
  207. package/src/elements/EFMedia/videoTasks/makeVideoSegmentIdTask.browsertest.ts +56 -0
  208. package/src/elements/EFMedia/videoTasks/makeVideoSegmentIdTask.ts +23 -0
  209. package/src/elements/EFMedia.browsertest.ts +696 -271
  210. package/src/elements/EFMedia.ts +218 -776
  211. package/src/elements/EFTemporal.browsertest.ts +0 -1
  212. package/src/elements/EFTemporal.ts +13 -3
  213. package/src/elements/EFTimegroup.browsertest.ts +6 -3
  214. package/src/elements/EFTimegroup.ts +221 -27
  215. package/src/elements/EFVideo.browsertest.ts +758 -0
  216. package/src/elements/EFVideo.ts +418 -68
  217. package/src/elements/EFWaveform.ts +5 -5
  218. package/src/elements/MediaController.ts +98 -0
  219. package/src/elements/SampleBuffer.ts +97 -0
  220. package/src/elements/printTaskStatus.ts +16 -0
  221. package/src/elements/updateAnimations.ts +6 -0
  222. package/src/gui/ContextMixin.ts +23 -104
  223. package/src/gui/TWMixin.ts +10 -3
  224. package/src/gui/services/ElementConnectionManager.browsertest.ts +263 -0
  225. package/src/gui/services/ElementConnectionManager.ts +224 -0
  226. package/src/gui/services/PlaybackController.browsertest.ts +437 -0
  227. package/src/gui/services/PlaybackController.ts +521 -0
  228. package/src/services/MediaSourceManager.ts +333 -0
  229. package/src/transcoding/cache/CacheManager.ts +208 -0
  230. package/src/transcoding/cache/RequestDeduplicator.test.ts +170 -0
  231. package/src/transcoding/cache/RequestDeduplicator.ts +65 -0
  232. package/src/transcoding/types/index.ts +265 -0
  233. package/src/transcoding/utils/MediaUtils.ts +63 -0
  234. package/src/transcoding/utils/UrlGenerator.ts +68 -0
  235. package/src/transcoding/utils/constants.ts +36 -0
  236. package/src/utils/LRUCache.ts +153 -0
  237. package/test/EFVideo.framegen.browsertest.ts +127 -0
  238. package/test/__cache__/GET__api_v1_transcode_audio_1_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__32da3954ba60c96ad732020c65a08ebc/data.bin +0 -0
  239. package/test/__cache__/GET__api_v1_transcode_audio_1_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__32da3954ba60c96ad732020c65a08ebc/metadata.json +21 -0
  240. package/test/__cache__/GET__api_v1_transcode_audio_2_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__b0b2b07efcf607de8ee0f650328c32f7/data.bin +0 -0
  241. package/test/__cache__/GET__api_v1_transcode_audio_2_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__b0b2b07efcf607de8ee0f650328c32f7/metadata.json +21 -0
  242. package/test/__cache__/GET__api_v1_transcode_audio_3_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__a75c2252b542e0c152c780e9a8d7b154/data.bin +0 -0
  243. package/test/__cache__/GET__api_v1_transcode_audio_3_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__a75c2252b542e0c152c780e9a8d7b154/metadata.json +21 -0
  244. package/test/__cache__/GET__api_v1_transcode_audio_4_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__a64ff1cfb1b52cae14df4b5dfa1e222b/data.bin +0 -0
  245. package/test/__cache__/GET__api_v1_transcode_audio_4_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__a64ff1cfb1b52cae14df4b5dfa1e222b/metadata.json +21 -0
  246. package/test/__cache__/GET__api_v1_transcode_audio_5_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__91e8a522f950809b9f09f4173113b4b0/data.bin +0 -0
  247. package/test/__cache__/GET__api_v1_transcode_audio_5_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__91e8a522f950809b9f09f4173113b4b0/metadata.json +21 -0
  248. package/test/__cache__/GET__api_v1_transcode_audio_init_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__e66d2c831d951e74ad0aeaa6489795d0/data.bin +0 -0
  249. package/test/__cache__/GET__api_v1_transcode_audio_init_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__e66d2c831d951e74ad0aeaa6489795d0/metadata.json +21 -0
  250. package/test/__cache__/GET__api_v1_transcode_high_1_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__26197f6f7c46cacb0a71134131c3f775/data.bin +0 -0
  251. package/test/__cache__/GET__api_v1_transcode_high_1_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__26197f6f7c46cacb0a71134131c3f775/metadata.json +21 -0
  252. package/test/__cache__/GET__api_v1_transcode_high_2_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__4cb6774cd3650ccf59c8f8dc6678c0b9/data.bin +0 -0
  253. package/test/__cache__/GET__api_v1_transcode_high_2_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__4cb6774cd3650ccf59c8f8dc6678c0b9/metadata.json +21 -0
  254. package/test/__cache__/GET__api_v1_transcode_high_3_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__0b3b2b1c8933f7fcf8a9ecaa88d58b41/data.bin +0 -0
  255. package/test/__cache__/GET__api_v1_transcode_high_3_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__0b3b2b1c8933f7fcf8a9ecaa88d58b41/metadata.json +21 -0
  256. package/test/__cache__/GET__api_v1_transcode_high_init_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__0798c479b44aaeef850609a430f6e613/data.bin +0 -0
  257. package/test/__cache__/GET__api_v1_transcode_high_init_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__0798c479b44aaeef850609a430f6e613/metadata.json +21 -0
  258. package/test/__cache__/GET__api_v1_transcode_manifest_json_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__3be92a0437de726b431ed5af2369158a/data.bin +1 -0
  259. package/test/__cache__/GET__api_v1_transcode_manifest_json_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__3be92a0437de726b431ed5af2369158a/metadata.json +19 -0
  260. package/test/createJitTestClips.ts +425 -0
  261. package/test/recordReplayProxyPlugin.js +302 -0
  262. package/test/useAssetMSW.ts +49 -0
  263. package/test/useMSW.ts +44 -0
  264. package/types.json +1 -1
  265. package/dist/gui/TWMixin.css.js +0 -4
  266. /package/dist/elements/{TargetController.test.d.ts → TargetController.browsertest.d.ts} +0 -0
  267. /package/src/elements/{TargetController.test.ts → TargetController.browsertest.ts} +0 -0
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Manages dynamic connection/disconnection of media elements to AudioContext
3
+ * Extracted from ContextMixin to improve separation of concerns and testability
4
+ */
5
+ export declare class ElementConnectionManager {
6
+ private connectedMediaSources;
7
+ private lookaheadMs;
8
+ constructor(lookaheadMs?: number);
9
+ /**
10
+ * Update connected media elements based on current playhead position
11
+ * Connects upcoming elements and disconnects past elements
12
+ */
13
+ updateConnectedElements(audioContext: AudioContext, timegroup: any, // EFTimegroup type
14
+ currentMs: number): Promise<void>;
15
+ /**
16
+ * Find elements that should be connected based on timeline position
17
+ */
18
+ private getElementsToConnect;
19
+ /**
20
+ * Connect new elements that aren't already connected
21
+ */
22
+ private connectNewElements;
23
+ /**
24
+ * Update connection states for all managed elements
25
+ */
26
+ private updateElementStates;
27
+ /**
28
+ * Activate an element (connect to destination and start playback)
29
+ */
30
+ private activateElement;
31
+ /**
32
+ * Deactivate an element (disconnect but keep prepared)
33
+ */
34
+ private deactivateElement;
35
+ /**
36
+ * Clean up elements that are far in the past
37
+ */
38
+ private cleanupOldElements;
39
+ /**
40
+ * Clear all connected media sources (for cleanup)
41
+ */
42
+ clearAll(): void;
43
+ /**
44
+ * Get connection status for testing/debugging
45
+ */
46
+ getConnectionInfo(): {
47
+ total: number;
48
+ connected: number;
49
+ prepared: number;
50
+ };
51
+ /**
52
+ * Set lookahead time
53
+ */
54
+ setLookaheadMs(lookaheadMs: number): void;
55
+ /**
56
+ * Get current lookahead time
57
+ */
58
+ getLookaheadMs(): number;
59
+ }
@@ -0,0 +1,128 @@
1
+ /**
2
+ * Manages dynamic connection/disconnection of media elements to AudioContext
3
+ * Extracted from ContextMixin to improve separation of concerns and testability
4
+ */
5
+ var ElementConnectionManager = class {
6
+ constructor(lookaheadMs = 3e3) {
7
+ this.connectedMediaSources = /* @__PURE__ */ new Map();
8
+ this.lookaheadMs = lookaheadMs;
9
+ }
10
+ /**
11
+ * Update connected media elements based on current playhead position
12
+ * Connects upcoming elements and disconnects past elements
13
+ */
14
+ async updateConnectedElements(audioContext, timegroup, currentMs) {
15
+ if (!audioContext || audioContext.state === "closed") return;
16
+ const allMediaElements = Array.from(timegroup.querySelectorAll("ef-audio, ef-video"));
17
+ const lookaheadMs = currentMs + this.lookaheadMs;
18
+ const elementsToConnect = this.getElementsToConnect(allMediaElements, currentMs, lookaheadMs);
19
+ await this.connectNewElements(audioContext, elementsToConnect);
20
+ await this.updateElementStates(currentMs);
21
+ this.cleanupOldElements(currentMs);
22
+ }
23
+ /**
24
+ * Find elements that should be connected based on timeline position
25
+ */
26
+ getElementsToConnect(allElements, currentMs, lookaheadMs) {
27
+ return allElements.filter((mediaElement) => {
28
+ const startTime = mediaElement.startTimeMs;
29
+ const endTime = mediaElement.endTimeMs;
30
+ const isCurrentlyActive = currentMs >= startTime && currentMs < endTime;
31
+ const isStartingSoon = startTime > currentMs && startTime <= lookaheadMs;
32
+ return isCurrentlyActive || isStartingSoon;
33
+ });
34
+ }
35
+ /**
36
+ * Connect new elements that aren't already connected
37
+ */
38
+ async connectNewElements(audioContext, elementsToConnect) {
39
+ for (const mediaElement of elementsToConnect) if (!this.connectedMediaSources.has(mediaElement)) {
40
+ const mediaElementSource = await mediaElement.getMediaElementSource(audioContext);
41
+ this.connectedMediaSources.set(mediaElement, {
42
+ mediaElementSource,
43
+ connected: false
44
+ });
45
+ }
46
+ }
47
+ /**
48
+ * Update connection states for all managed elements
49
+ */
50
+ async updateElementStates(currentMs) {
51
+ for (const [mediaElement, sourceInfo] of this.connectedMediaSources.entries()) {
52
+ const startTime = mediaElement.startTimeMs;
53
+ const endTime = mediaElement.endTimeMs;
54
+ const isCurrentlyActive = currentMs >= startTime && currentMs < endTime;
55
+ if (isCurrentlyActive && !sourceInfo.connected) await this.activateElement(mediaElement, sourceInfo);
56
+ else if (!isCurrentlyActive && sourceInfo.connected) await this.deactivateElement(mediaElement, sourceInfo);
57
+ }
58
+ }
59
+ /**
60
+ * Activate an element (connect to destination and start playback)
61
+ */
62
+ async activateElement(mediaElement, sourceInfo) {
63
+ sourceInfo.mediaElementSource.connect(sourceInfo.mediaElementSource.context.destination);
64
+ sourceInfo.connected = true;
65
+ if (mediaElement.audioElement) {
66
+ const mediaTimeMs = mediaElement.currentSourceTimeMs;
67
+ mediaElement.audioElement.currentTime = mediaTimeMs / 1e3;
68
+ await mediaElement.audioElement.play();
69
+ }
70
+ }
71
+ /**
72
+ * Deactivate an element (disconnect but keep prepared)
73
+ */
74
+ async deactivateElement(mediaElement, sourceInfo) {
75
+ sourceInfo.mediaElementSource.disconnect();
76
+ sourceInfo.connected = false;
77
+ if (mediaElement.audioElement) mediaElement.audioElement.pause();
78
+ }
79
+ /**
80
+ * Clean up elements that are far in the past
81
+ */
82
+ cleanupOldElements(currentMs) {
83
+ const cleanupThresholdMs = currentMs - this.lookaheadMs;
84
+ for (const [mediaElement, sourceInfo] of this.connectedMediaSources.entries()) {
85
+ const endTime = mediaElement.endTimeMs;
86
+ if (endTime < cleanupThresholdMs) {
87
+ if (sourceInfo.connected) sourceInfo.mediaElementSource.disconnect();
88
+ this.connectedMediaSources.delete(mediaElement);
89
+ }
90
+ }
91
+ }
92
+ /**
93
+ * Clear all connected media sources (for cleanup)
94
+ */
95
+ clearAll() {
96
+ for (const [, sourceInfo] of this.connectedMediaSources.entries()) try {
97
+ if (sourceInfo.connected) sourceInfo.mediaElementSource.disconnect();
98
+ } catch (_error) {}
99
+ this.connectedMediaSources.clear();
100
+ }
101
+ /**
102
+ * Get connection status for testing/debugging
103
+ */
104
+ getConnectionInfo() {
105
+ let connected = 0;
106
+ let prepared = 0;
107
+ for (const [, sourceInfo] of this.connectedMediaSources.entries()) if (sourceInfo.connected) connected++;
108
+ else prepared++;
109
+ return {
110
+ total: this.connectedMediaSources.size,
111
+ connected,
112
+ prepared
113
+ };
114
+ }
115
+ /**
116
+ * Set lookahead time
117
+ */
118
+ setLookaheadMs(lookaheadMs) {
119
+ this.lookaheadMs = lookaheadMs;
120
+ }
121
+ /**
122
+ * Get current lookahead time
123
+ */
124
+ getLookaheadMs() {
125
+ return this.lookaheadMs;
126
+ }
127
+ };
128
+ export { ElementConnectionManager };
@@ -0,0 +1,103 @@
1
+ export interface PlaybackControllerOptions {
2
+ fps?: number;
3
+ onTimeUpdate?: (timeMs: number) => void;
4
+ onPlayStateChange?: (playing: boolean) => void;
5
+ onError?: (error: Error) => void;
6
+ }
7
+ /**
8
+ * Manages playback timing, AudioContext lifecycle, and timeline synchronization
9
+ * Extracted from ContextMixin to improve separation of concerns and testability
10
+ */
11
+ export declare class PlaybackController {
12
+ private playbackAudioContext;
13
+ private animationFrameRequest;
14
+ private options;
15
+ private playing;
16
+ private currentTimeMs;
17
+ private msPerFrame;
18
+ private audioStartTime;
19
+ private playbackStartTimeMs;
20
+ private activeChunks;
21
+ private chunkDurationMs;
22
+ private lookaheadChunks;
23
+ private currentChunkIndex;
24
+ private renderingChunks;
25
+ constructor(options?: PlaybackControllerOptions);
26
+ /**
27
+ * Start playback for the given timegroup
28
+ */
29
+ startPlayback(timegroup: any, fromMs?: number): Promise<void>;
30
+ /**
31
+ * Stop playback and clean up resources
32
+ */
33
+ stopPlayback(): Promise<void>;
34
+ /**
35
+ * Pause playback (can be resumed)
36
+ */
37
+ pausePlayback(): Promise<void>;
38
+ /**
39
+ * Resume paused playback
40
+ */
41
+ resumePlayback(): Promise<void>;
42
+ /**
43
+ * Seek to a specific time (restarts progressive playback from new position)
44
+ */
45
+ seekTo(timeMs: number, timegroup?: any): Promise<void>;
46
+ /**
47
+ * Internal method to sync playhead with unified audio buffer timing
48
+ */
49
+ private syncPlayheadToAudioBuffer;
50
+ /**
51
+ * Update playing state and notify observers
52
+ */
53
+ private setPlaying;
54
+ /**
55
+ * Get current playback state
56
+ */
57
+ isPlaying(): boolean;
58
+ /**
59
+ * Get current time
60
+ */
61
+ getCurrentTime(): number;
62
+ /**
63
+ * Get current AudioContext
64
+ */
65
+ getAudioContext(): AudioContext | null;
66
+ /**
67
+ * Check if AudioContext is ready
68
+ */
69
+ isAudioContextReady(): boolean;
70
+ /**
71
+ * Get playback statistics for debugging
72
+ */
73
+ getPlaybackInfo(): {
74
+ playing: boolean;
75
+ currentTimeMs: number;
76
+ audioContextState: string | null;
77
+ hasElementManager: boolean;
78
+ };
79
+ /**
80
+ * Update playback options
81
+ */
82
+ updateOptions(options: Partial<PlaybackControllerOptions>): void;
83
+ /**
84
+ * Start progressive chunk rendering and playback
85
+ */
86
+ private startProgressivePlayback;
87
+ /**
88
+ * Render and schedule a single audio chunk
89
+ */
90
+ private renderAndScheduleChunk;
91
+ /**
92
+ * Update chunk rendering as playhead advances - now handles all chunk management
93
+ */
94
+ private updateProgressiveChunks;
95
+ /**
96
+ * Systematically ensure chunks are ready ahead of current playback (synchronous)
97
+ */
98
+ private ensureChunksAhead;
99
+ /**
100
+ * Clean up chunks that are behind the current playhead
101
+ */
102
+ private cleanupOldChunks;
103
+ }
@@ -0,0 +1,290 @@
1
+ /**
2
+ * Manages playback timing, AudioContext lifecycle, and timeline synchronization
3
+ * Extracted from ContextMixin to improve separation of concerns and testability
4
+ */
5
+ var PlaybackController = class {
6
+ constructor(options = {}) {
7
+ this.playbackAudioContext = null;
8
+ this.animationFrameRequest = null;
9
+ this.playing = false;
10
+ this.currentTimeMs = 0;
11
+ this.audioStartTime = 0;
12
+ this.playbackStartTimeMs = 0;
13
+ this.activeChunks = /* @__PURE__ */ new Map();
14
+ this.chunkDurationMs = 4e3;
15
+ this.lookaheadChunks = 2;
16
+ this.currentChunkIndex = 0;
17
+ this.renderingChunks = /* @__PURE__ */ new Set();
18
+ this.options = {
19
+ fps: 30,
20
+ onTimeUpdate: () => {},
21
+ onPlayStateChange: () => {},
22
+ onError: () => {},
23
+ ...options
24
+ };
25
+ this.msPerFrame = 1e3 / this.options.fps;
26
+ }
27
+ /**
28
+ * Start playback for the given timegroup
29
+ */
30
+ async startPlayback(timegroup, fromMs) {
31
+ await this.stopPlayback();
32
+ if (!timegroup) {
33
+ this.setPlaying(false);
34
+ this.options.onPlayStateChange(false);
35
+ this.options.onError(/* @__PURE__ */ new Error("No timegroup provided"));
36
+ return;
37
+ }
38
+ await timegroup.waitForMediaDurations?.();
39
+ const currentMs = fromMs ?? timegroup.currentTimeMs ?? 0;
40
+ const toMs = timegroup.endTimeMs;
41
+ if (currentMs >= toMs) {
42
+ this.setPlaying(false);
43
+ this.options.onPlayStateChange(false);
44
+ return;
45
+ }
46
+ try {
47
+ this.playbackAudioContext = new AudioContext({ latencyHint: "playback" });
48
+ if (this.playbackAudioContext.state === "suspended") {
49
+ console.warn("AudioContext is suspended, attempting to resume...");
50
+ try {
51
+ await Promise.race([this.playbackAudioContext.resume(), new Promise((_, reject) => setTimeout(() => reject(/* @__PURE__ */ new Error("AudioContext resume timeout")), 2e3))]);
52
+ } catch (error) {
53
+ console.warn("AudioContext resume failed:", error);
54
+ }
55
+ } else await this.playbackAudioContext.resume();
56
+ this.audioStartTime = this.playbackAudioContext.currentTime;
57
+ this.playbackStartTimeMs = currentMs;
58
+ this.currentChunkIndex = Math.floor(currentMs / this.chunkDurationMs);
59
+ await this.startProgressivePlayback(timegroup, currentMs, toMs);
60
+ if (this.isAudioContextReady()) {
61
+ this.setPlaying(true);
62
+ this.currentTimeMs = currentMs;
63
+ this.options.onTimeUpdate(currentMs);
64
+ this.syncPlayheadToAudioBuffer(timegroup, currentMs);
65
+ } else {
66
+ this.setPlaying(false);
67
+ this.options.onPlayStateChange(false);
68
+ console.warn("AudioContext not ready for playback, state:", this.playbackAudioContext?.state);
69
+ }
70
+ } catch (error) {
71
+ console.error("🎵 [PLAYBACK_ERROR] Failed to setup progressive audio playback:", error);
72
+ this.setPlaying(false);
73
+ this.options.onPlayStateChange(false);
74
+ this.options.onError(error);
75
+ }
76
+ }
77
+ /**
78
+ * Stop playback and clean up resources
79
+ */
80
+ async stopPlayback() {
81
+ for (const [_chunkIndex, bufferSource] of this.activeChunks.entries()) try {
82
+ bufferSource.stop();
83
+ } catch (_error) {}
84
+ this.activeChunks.clear();
85
+ this.renderingChunks.clear();
86
+ if (this.playbackAudioContext) {
87
+ if (this.playbackAudioContext.state !== "closed") await this.playbackAudioContext.close();
88
+ }
89
+ if (this.animationFrameRequest) {
90
+ cancelAnimationFrame(this.animationFrameRequest);
91
+ this.animationFrameRequest = null;
92
+ }
93
+ this.playbackAudioContext = null;
94
+ this.setPlaying(false);
95
+ }
96
+ /**
97
+ * Pause playback (can be resumed)
98
+ */
99
+ async pausePlayback() {
100
+ if (this.playbackAudioContext && this.playbackAudioContext.state === "running") try {
101
+ await Promise.race([this.playbackAudioContext.suspend(), new Promise((_, reject) => setTimeout(() => reject(/* @__PURE__ */ new Error("AudioContext suspend timeout")), 2e3))]);
102
+ } catch (error) {
103
+ console.warn("AudioContext suspend failed:", error);
104
+ }
105
+ if (this.animationFrameRequest) {
106
+ cancelAnimationFrame(this.animationFrameRequest);
107
+ this.animationFrameRequest = null;
108
+ }
109
+ this.setPlaying(false);
110
+ }
111
+ /**
112
+ * Resume paused playback
113
+ */
114
+ async resumePlayback() {
115
+ if (this.playbackAudioContext && this.playbackAudioContext.state === "suspended") {
116
+ try {
117
+ await Promise.race([this.playbackAudioContext.resume(), new Promise((_, reject) => setTimeout(() => reject(/* @__PURE__ */ new Error("AudioContext resume timeout")), 2e3))]);
118
+ } catch (error) {
119
+ console.warn("AudioContext resume failed:", error);
120
+ }
121
+ this.setPlaying(true);
122
+ }
123
+ }
124
+ /**
125
+ * Seek to a specific time (restarts progressive playback from new position)
126
+ */
127
+ async seekTo(timeMs, timegroup) {
128
+ this.currentTimeMs = timeMs;
129
+ this.options.onTimeUpdate(timeMs);
130
+ if (this.playing && timegroup) {
131
+ for (const bufferSource of this.activeChunks.values()) try {
132
+ bufferSource.stop();
133
+ } catch (_error) {}
134
+ this.activeChunks.clear();
135
+ this.renderingChunks.clear();
136
+ this.audioStartTime = this.playbackAudioContext?.currentTime ?? 0;
137
+ this.playbackStartTimeMs = timeMs;
138
+ this.currentChunkIndex = Math.floor(timeMs / this.chunkDurationMs);
139
+ await this.startProgressivePlayback(timegroup, timeMs, timegroup.endTimeMs);
140
+ }
141
+ }
142
+ /**
143
+ * Internal method to sync playhead with unified audio buffer timing
144
+ */
145
+ syncPlayheadToAudioBuffer(timegroup, startMs) {
146
+ if (!this.playbackAudioContext || !this.playing) return;
147
+ const elapsedAudioTime = this.playbackAudioContext.currentTime - this.audioStartTime;
148
+ const rawTimeMs = startMs + elapsedAudioTime * 1e3;
149
+ const nextTimeMs = Math.round(rawTimeMs / this.msPerFrame) * this.msPerFrame;
150
+ if (nextTimeMs !== this.currentTimeMs) {
151
+ this.currentTimeMs = nextTimeMs;
152
+ this.options.onTimeUpdate(nextTimeMs);
153
+ if (timegroup && timegroup.currentTimeMs !== nextTimeMs) timegroup.currentTimeMs = nextTimeMs;
154
+ this.updateProgressiveChunks(timegroup, nextTimeMs, timegroup.endTimeMs);
155
+ }
156
+ this.animationFrameRequest = requestAnimationFrame(() => {
157
+ this.syncPlayheadToAudioBuffer(timegroup, startMs);
158
+ });
159
+ }
160
+ /**
161
+ * Update playing state and notify observers
162
+ */
163
+ setPlaying(playing) {
164
+ if (this.playing !== playing) {
165
+ this.playing = playing;
166
+ this.options.onPlayStateChange(playing);
167
+ }
168
+ }
169
+ /**
170
+ * Get current playback state
171
+ */
172
+ isPlaying() {
173
+ return this.playing;
174
+ }
175
+ /**
176
+ * Get current time
177
+ */
178
+ getCurrentTime() {
179
+ return this.currentTimeMs;
180
+ }
181
+ /**
182
+ * Get current AudioContext
183
+ */
184
+ getAudioContext() {
185
+ return this.playbackAudioContext;
186
+ }
187
+ /**
188
+ * Check if AudioContext is ready
189
+ */
190
+ isAudioContextReady() {
191
+ return this.playbackAudioContext != null && this.playbackAudioContext.state !== "closed";
192
+ }
193
+ /**
194
+ * Get playback statistics for debugging
195
+ */
196
+ getPlaybackInfo() {
197
+ return {
198
+ playing: this.playing,
199
+ currentTimeMs: this.currentTimeMs,
200
+ audioContextState: this.playbackAudioContext?.state || null,
201
+ hasElementManager: false
202
+ };
203
+ }
204
+ /**
205
+ * Update playback options
206
+ */
207
+ updateOptions(options) {
208
+ Object.assign(this.options, options);
209
+ if (options.fps) this.msPerFrame = 1e3 / options.fps;
210
+ }
211
+ /**
212
+ * Start progressive chunk rendering and playback
213
+ */
214
+ async startProgressivePlayback(timegroup, fromMs, _toMs) {
215
+ const firstChunkIndex = Math.floor(fromMs / this.chunkDurationMs);
216
+ const firstChunkStart = firstChunkIndex * this.chunkDurationMs;
217
+ const offsetInChunk = fromMs - firstChunkStart;
218
+ await this.renderAndScheduleChunk(timegroup, firstChunkStart, firstChunkIndex, offsetInChunk);
219
+ }
220
+ /**
221
+ * Render and schedule a single audio chunk
222
+ */
223
+ async renderAndScheduleChunk(timegroup, chunkStartMs, chunkIndex, offsetInChunk = 0) {
224
+ if (this.renderingChunks.has(chunkIndex) || this.activeChunks.has(chunkIndex)) return;
225
+ this.renderingChunks.add(chunkIndex);
226
+ try {
227
+ const chunkEndMs = chunkStartMs + this.chunkDurationMs;
228
+ const chunkBuffer = await timegroup.renderAudio(chunkStartMs, chunkEndMs);
229
+ const bufferSource = this.playbackAudioContext?.createBufferSource();
230
+ if (!bufferSource || !this.playbackAudioContext?.destination) throw new Error("Audio context or buffer source not available");
231
+ bufferSource.buffer = chunkBuffer;
232
+ bufferSource.connect(this.playbackAudioContext.destination);
233
+ const chunkTimelineStartMs = chunkIndex * this.chunkDurationMs;
234
+ const relativeDelayMs = Math.max(0, chunkTimelineStartMs - this.playbackStartTimeMs);
235
+ const chunkStartTime = this.audioStartTime + relativeDelayMs / 1e3;
236
+ const startOffset = offsetInChunk / 1e3;
237
+ const now = this.playbackAudioContext?.currentTime ?? 0;
238
+ if (chunkStartTime <= now) console.warn(`🎵 [CHUNK_TIMING_WARNING] Chunk ${chunkIndex} scheduled in the past! startTime=${chunkStartTime.toFixed(3)}s, currentTime=${now.toFixed(3)}s`);
239
+ bufferSource.start(chunkStartTime, startOffset);
240
+ this.activeChunks.set(chunkIndex, bufferSource);
241
+ bufferSource.onended = () => {
242
+ this.activeChunks.delete(chunkIndex);
243
+ };
244
+ } catch (error) {
245
+ console.error(`🎵 [CHUNK_ERROR] Failed to render chunk ${chunkIndex}:`, error);
246
+ } finally {
247
+ this.renderingChunks.delete(chunkIndex);
248
+ }
249
+ }
250
+ /**
251
+ * Update chunk rendering as playhead advances - now handles all chunk management
252
+ */
253
+ updateProgressiveChunks(timegroup, currentTimeMs, maxTimeMs) {
254
+ const newChunkIndex = Math.floor(currentTimeMs / this.chunkDurationMs);
255
+ if (newChunkIndex !== this.currentChunkIndex) {
256
+ this.currentChunkIndex = newChunkIndex;
257
+ this.cleanupOldChunks();
258
+ }
259
+ this.ensureChunksAhead(timegroup, maxTimeMs);
260
+ }
261
+ /**
262
+ * Systematically ensure chunks are ready ahead of current playback (synchronous)
263
+ */
264
+ ensureChunksAhead(timegroup, maxTimeMs) {
265
+ for (let i = 1; i <= this.lookaheadChunks; i++) {
266
+ const targetChunkIndex = this.currentChunkIndex + i;
267
+ const targetChunkStartMs = targetChunkIndex * this.chunkDurationMs;
268
+ if (targetChunkStartMs >= maxTimeMs) break;
269
+ if (!this.renderingChunks.has(targetChunkIndex) && !this.activeChunks.has(targetChunkIndex)) {
270
+ const offsetInChunk = 0;
271
+ this.renderAndScheduleChunk(timegroup, targetChunkStartMs, targetChunkIndex, offsetInChunk).catch((error) => {
272
+ console.error(`🎵 [ENSURE_CHUNKS_ERROR] Failed to render chunk ${targetChunkIndex}:`, error);
273
+ });
274
+ }
275
+ }
276
+ }
277
+ /**
278
+ * Clean up chunks that are behind the current playhead
279
+ */
280
+ cleanupOldChunks() {
281
+ const cutoffChunkIndex = this.currentChunkIndex - 1;
282
+ for (const [chunkIndex, bufferSource] of this.activeChunks.entries()) if (chunkIndex < cutoffChunkIndex) {
283
+ try {
284
+ bufferSource.stop();
285
+ } catch (_error) {}
286
+ this.activeChunks.delete(chunkIndex);
287
+ }
288
+ }
289
+ };
290
+ export { PlaybackController };
package/dist/index.js CHANGED
@@ -1,12 +1,12 @@
1
- /* empty css */
1
+ /* empty css */
2
+ import { EFConfiguration } from "./gui/EFConfiguration.js";
3
+ import "./elements/EFMedia.js";
2
4
  import { EFTimegroup } from "./elements/EFTimegroup.js";
3
5
  import { EFImage } from "./elements/EFImage.js";
4
- import "./elements/EFMedia.js";
5
6
  import { EFAudio } from "./elements/EFAudio.js";
6
7
  import { EFVideo } from "./elements/EFVideo.js";
7
8
  import { EFCaptions, EFCaptionsActiveWord, EFCaptionsAfterActiveWord, EFCaptionsBeforeActiveWord, EFCaptionsSegment } from "./elements/EFCaptions.js";
8
9
  import { EFWaveform } from "./elements/EFWaveform.js";
9
- import { EFConfiguration } from "./gui/EFConfiguration.js";
10
10
  import { EFWorkbench } from "./gui/EFWorkbench.js";
11
11
  import { EFPreview } from "./gui/EFPreview.js";
12
12
  import { EFFilmstrip } from "./gui/EFFilmstrip.js";
@@ -18,30 +18,5 @@ import { EFFocusOverlay } from "./gui/EFFocusOverlay.js";
18
18
  import { EFFitScale } from "./gui/EFFitScale.js";
19
19
  import "./EF_FRAMEGEN.js";
20
20
  import { RenderInfo, getRenderInfo } from "./getRenderInfo.js";
21
- if (typeof window !== "undefined") {
22
- window.EF_REGISTERED = true;
23
- }
24
- export {
25
- EFAudio,
26
- EFCaptions,
27
- EFCaptionsActiveWord,
28
- EFCaptionsAfterActiveWord,
29
- EFCaptionsBeforeActiveWord,
30
- EFCaptionsSegment,
31
- EFConfiguration,
32
- EFFilmstrip,
33
- EFFitScale,
34
- EFFocusOverlay,
35
- EFImage,
36
- EFPreview,
37
- EFScrubber,
38
- EFTimeDisplay,
39
- EFTimegroup,
40
- EFToggleLoop,
41
- EFTogglePlay,
42
- EFVideo,
43
- EFWaveform,
44
- EFWorkbench,
45
- RenderInfo,
46
- getRenderInfo
47
- };
21
+ if (typeof window !== "undefined") window.EF_REGISTERED = true;
22
+ export { EFAudio, EFCaptions, EFCaptionsActiveWord, EFCaptionsAfterActiveWord, EFCaptionsBeforeActiveWord, EFCaptionsSegment, EFConfiguration, EFFilmstrip, EFFitScale, EFFocusOverlay, EFImage, EFPreview, EFScrubber, EFTimeDisplay, EFTimegroup, EFToggleLoop, EFTogglePlay, EFVideo, EFWaveform, EFWorkbench, RenderInfo, getRenderInfo };
@@ -1,15 +1,13 @@
1
1
  const msToTimeCode = (ms, subSecond = false) => {
2
- const seconds = Math.floor(ms / 1e3);
3
- const minutes = Math.floor(seconds / 60);
4
- const hours = Math.floor(minutes / 60);
5
- const pad = (num) => num.toString().padStart(2, "0");
6
- let timecode = `${pad(hours)}:${pad(minutes % 60)}:${pad(seconds % 60)}`;
7
- if (subSecond) {
8
- const subSeconds = Math.floor(ms % 1e3 / 10);
9
- timecode += `.${subSeconds.toString().padStart(2, "0")}`;
10
- }
11
- return timecode;
12
- };
13
- export {
14
- msToTimeCode
2
+ const seconds = Math.floor(ms / 1e3);
3
+ const minutes = Math.floor(seconds / 60);
4
+ const hours = Math.floor(minutes / 60);
5
+ const pad = (num) => num.toString().padStart(2, "0");
6
+ let timecode = `${pad(hours)}:${pad(minutes % 60)}:${pad(seconds % 60)}`;
7
+ if (subSecond) {
8
+ const subSeconds = Math.floor(ms % 1e3 / 10);
9
+ timecode += `.${subSeconds.toString().padStart(2, "0")}`;
10
+ }
11
+ return timecode;
15
12
  };
13
+ export { msToTimeCode };