@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,102 @@
1
+ import {
2
+ MediaSourceManager,
3
+ type MediaSourceManagerOptions,
4
+ } from "../../../services/MediaSourceManager.js";
5
+
6
+ export interface MediaSourceServiceOptions {
7
+ onError?: (error: Error) => void;
8
+ onReady?: () => void;
9
+ onUpdateEnd?: () => void;
10
+ timeout?: number;
11
+ }
12
+
13
+ /**
14
+ * Service for managing MediaSource lifecycle and audio element creation
15
+ * Extracted from EFMedia to improve separation of concerns and testability
16
+ */
17
+ export class MediaSourceService {
18
+ private mediaSourceManager: MediaSourceManager | null = null;
19
+ private options: MediaSourceServiceOptions;
20
+
21
+ constructor(options: MediaSourceServiceOptions = {}) {
22
+ this.options = options;
23
+ }
24
+
25
+ /**
26
+ * Initialize MediaSource if not already initialized
27
+ */
28
+ async ensureInitialized(): Promise<void> {
29
+ if (this.mediaSourceManager?.isReady()) {
30
+ return;
31
+ }
32
+
33
+ await this.initialize();
34
+ }
35
+
36
+ /**
37
+ * Initialize fresh MediaSource
38
+ */
39
+ async initialize(): Promise<void> {
40
+ // Clean up existing instance
41
+ this.cleanup();
42
+
43
+ // Create new MediaSourceManager
44
+ const managerOptions: MediaSourceManagerOptions = {
45
+ onError: this.options.onError,
46
+ onReady: this.options.onReady,
47
+ onUpdateEnd: this.options.onUpdateEnd,
48
+ timeout: this.options.timeout,
49
+ };
50
+
51
+ this.mediaSourceManager = new MediaSourceManager(managerOptions);
52
+ await this.mediaSourceManager.initialize();
53
+ }
54
+
55
+ /**
56
+ * Get audio element for MediaElementSource creation
57
+ */
58
+ getAudioElement(): HTMLAudioElement | null {
59
+ return this.mediaSourceManager?.getAudioElement() || null;
60
+ }
61
+
62
+ /**
63
+ * Feed audio segments to MediaSource
64
+ */
65
+ async feedSegment(segmentBuffer: ArrayBuffer): Promise<void> {
66
+ await this.ensureInitialized();
67
+ if (this.mediaSourceManager) {
68
+ await this.mediaSourceManager.feedSegment(segmentBuffer);
69
+ }
70
+ }
71
+
72
+ /**
73
+ * Check if MediaSource is ready
74
+ */
75
+ isReady(): boolean {
76
+ return this.mediaSourceManager?.isReady() ?? false;
77
+ }
78
+
79
+ /**
80
+ * Get buffered time ranges
81
+ */
82
+ getBuffered(): TimeRanges | null {
83
+ return this.mediaSourceManager?.getBuffered() || null;
84
+ }
85
+
86
+ /**
87
+ * Set audio element current time
88
+ */
89
+ setCurrentTime(timeMs: number): void {
90
+ this.mediaSourceManager?.setCurrentTime(timeMs);
91
+ }
92
+
93
+ /**
94
+ * Clean up MediaSource resources
95
+ */
96
+ cleanup(): void {
97
+ if (this.mediaSourceManager) {
98
+ this.mediaSourceManager.cleanup();
99
+ this.mediaSourceManager = null;
100
+ }
101
+ }
102
+ }
@@ -0,0 +1,128 @@
1
+ import type {
2
+ AudioSpan,
3
+ MediaEngine,
4
+ SegmentTimeRange,
5
+ } from "../../../transcoding/types";
6
+ import type { EFMedia } from "../../EFMedia";
7
+
8
+ /**
9
+ * Fetch audio segment data using MediaEngine
10
+ * Pure function with explicit dependencies
11
+ */
12
+ const fetchAudioSegmentData = async (
13
+ segmentIds: number[],
14
+ mediaEngine: MediaEngine,
15
+ signal: AbortSignal,
16
+ ): Promise<Map<number, ArrayBuffer>> => {
17
+ const audioRendition = mediaEngine.audioRendition;
18
+ if (!audioRendition) {
19
+ throw new Error("Audio rendition not available");
20
+ }
21
+
22
+ const segmentData = new Map<number, ArrayBuffer>();
23
+
24
+ // Fetch all segments - MediaEngine handles deduplication internally
25
+ const fetchPromises = segmentIds.map(async (segmentId) => {
26
+ const arrayBuffer = await mediaEngine.fetchMediaSegment(
27
+ segmentId,
28
+ audioRendition,
29
+ signal,
30
+ );
31
+ return [segmentId, arrayBuffer] as [number, ArrayBuffer];
32
+ });
33
+
34
+ const fetchedSegments = await Promise.all(fetchPromises);
35
+ signal.throwIfAborted();
36
+
37
+ for (const [segmentId, arrayBuffer] of fetchedSegments) {
38
+ segmentData.set(segmentId, arrayBuffer);
39
+ }
40
+
41
+ return segmentData;
42
+ };
43
+
44
+ /**
45
+ * Create audio span blob from init segment and media segments
46
+ * Pure function for blob creation
47
+ */
48
+ const createAudioSpanBlob = (
49
+ initSegment: ArrayBuffer,
50
+ mediaSegments: ArrayBuffer[],
51
+ ): Blob => {
52
+ const chunks = [initSegment, ...mediaSegments];
53
+ return new Blob(chunks, { type: "audio/mp4" });
54
+ };
55
+
56
+ /**
57
+ * Fetch audio spanning a time range
58
+ * Main function that orchestrates segment calculation, fetching, and blob creation
59
+ */
60
+ export const fetchAudioSpanningTime = async (
61
+ host: EFMedia,
62
+ fromMs: number,
63
+ toMs: number,
64
+ signal: AbortSignal,
65
+ ): Promise<AudioSpan> => {
66
+ // Validate inputs
67
+ if (fromMs >= toMs || fromMs < 0) {
68
+ throw new Error(`Invalid time range: fromMs=${fromMs}, toMs=${toMs}`);
69
+ }
70
+
71
+ // Get dependencies from host
72
+ const mediaEngine = await host.mediaEngineTask.taskComplete;
73
+ const initSegment = await host.audioInitSegmentFetchTask.taskComplete;
74
+
75
+ if (!mediaEngine?.audioRendition) {
76
+ throw new Error("Audio rendition not available");
77
+ }
78
+
79
+ if (!initSegment) {
80
+ throw new Error("Audio init segment is not available");
81
+ }
82
+
83
+ // Calculate segments needed using the media engine's method
84
+ const segmentRanges = mediaEngine.calculateAudioSegmentRange(
85
+ fromMs,
86
+ toMs,
87
+ mediaEngine.audioRendition,
88
+ host.intrinsicDurationMs || 10000,
89
+ );
90
+
91
+ if (segmentRanges.length === 0) {
92
+ throw new Error(`No segments found for time range ${fromMs}-${toMs}ms`);
93
+ }
94
+
95
+ // Fetch segment data
96
+ const segmentIds = segmentRanges.map((r: SegmentTimeRange) => r.segmentId);
97
+ const segmentData = await fetchAudioSegmentData(
98
+ segmentIds,
99
+ mediaEngine,
100
+ signal,
101
+ );
102
+
103
+ // Create ordered array of segments
104
+ const orderedSegments = segmentIds.map((id: number) => {
105
+ const segment = segmentData.get(id);
106
+ if (!segment) {
107
+ throw new Error(`Missing segment data for segment ID ${id}`);
108
+ }
109
+ return segment;
110
+ });
111
+
112
+ // Create blob
113
+ const blob = createAudioSpanBlob(initSegment, orderedSegments);
114
+
115
+ // Calculate actual time boundaries
116
+ const actualStartMs = Math.min(
117
+ ...segmentRanges.map((r: SegmentTimeRange) => r.startMs),
118
+ );
119
+ const actualEndMs = Math.max(
120
+ ...segmentRanges.map((r: SegmentTimeRange) => r.endMs),
121
+ );
122
+
123
+ return {
124
+ startMs: actualStartMs,
125
+ endMs: actualEndMs,
126
+ blob,
127
+ };
128
+ };
@@ -0,0 +1,310 @@
1
+ import type {
2
+ AudioRendition,
3
+ VideoRendition,
4
+ } from "../../../transcoding/types";
5
+
6
+ /**
7
+ * State interface for media buffering - generic for both audio and video
8
+ */
9
+ export interface MediaBufferState {
10
+ currentSeekTimeMs: number;
11
+ activeRequests: Set<number>;
12
+ cachedSegments: Set<number>;
13
+ requestQueue: number[];
14
+ }
15
+
16
+ /**
17
+ * Configuration interface for media buffering - generic for both audio and video
18
+ */
19
+ export interface MediaBufferConfig {
20
+ bufferDurationMs: number;
21
+ maxParallelFetches: number;
22
+ enableBuffering: boolean;
23
+ enableContinuousBuffering?: boolean;
24
+ }
25
+
26
+ /**
27
+ * Dependencies interface for media buffering - generic for both audio and video
28
+ */
29
+ export interface MediaBufferDependencies<
30
+ T extends AudioRendition | VideoRendition,
31
+ > {
32
+ computeSegmentId: (
33
+ timeMs: number,
34
+ rendition: T,
35
+ ) => Promise<number | undefined>;
36
+ fetchSegment: (segmentId: number, rendition: T) => Promise<ArrayBuffer>;
37
+ getRendition: () => Promise<T>;
38
+ logError: (message: string, error: any) => void;
39
+ }
40
+
41
+ /**
42
+ * Compute segment range for a time window
43
+ * Pure function - determines which segments are needed for a time range
44
+ */
45
+ export const computeSegmentRange = <T extends AudioRendition | VideoRendition>(
46
+ startTimeMs: number,
47
+ endTimeMs: number,
48
+ rendition: T,
49
+ computeSegmentId: (timeMs: number, rendition: T) => number | undefined,
50
+ ): number[] => {
51
+ const segments: number[] = [];
52
+ const segmentDurationMs = (rendition as any).segmentDurationMs || 1000;
53
+
54
+ // Calculate segment indices that overlap with [startTimeMs, endTimeMs]
55
+ const startSegmentIndex = Math.floor(startTimeMs / segmentDurationMs);
56
+ const endSegmentIndex = Math.floor(endTimeMs / segmentDurationMs);
57
+
58
+ for (let i = startSegmentIndex; i <= endSegmentIndex; i++) {
59
+ const segmentId = computeSegmentId(i * segmentDurationMs, rendition);
60
+ if (segmentId !== undefined) {
61
+ segments.push(segmentId);
62
+ }
63
+ }
64
+
65
+ return segments.filter((id, index, arr) => arr.indexOf(id) === index); // Remove duplicates
66
+ };
67
+
68
+ /**
69
+ * Async version of computeSegmentRange for when computeSegmentId is async
70
+ */
71
+ export const computeSegmentRangeAsync = async <
72
+ T extends AudioRendition | VideoRendition,
73
+ >(
74
+ startTimeMs: number,
75
+ endTimeMs: number,
76
+ durationMs: number,
77
+ rendition: T,
78
+ computeSegmentId: (
79
+ timeMs: number,
80
+ rendition: T,
81
+ ) => Promise<number | undefined>,
82
+ ): Promise<number[]> => {
83
+ const segments: number[] = [];
84
+ const segmentDurationMs = (rendition as any).segmentDurationMs || 1000;
85
+
86
+ // Calculate segment indices that overlap with [startTimeMs, endTimeMs]
87
+ const startSegmentIndex = Math.floor(startTimeMs / segmentDurationMs);
88
+ const endSegmentIndex = Math.floor(
89
+ Math.min(endTimeMs, durationMs) / segmentDurationMs,
90
+ );
91
+
92
+ for (let i = startSegmentIndex; i <= endSegmentIndex; i++) {
93
+ const timeMs = i * segmentDurationMs;
94
+ if (timeMs < durationMs) {
95
+ const segmentId = await computeSegmentId(timeMs, rendition);
96
+ if (segmentId !== undefined) {
97
+ segments.push(segmentId);
98
+ }
99
+ }
100
+ }
101
+
102
+ return segments.filter((id, index, arr) => arr.indexOf(id) === index); // Remove duplicates
103
+ };
104
+
105
+ /**
106
+ * Compute buffer queue based on current state and desired segments
107
+ * Pure function - determines what segments should be fetched
108
+ */
109
+ export const computeBufferQueue = (
110
+ desiredSegments: number[],
111
+ activeRequests: Set<number>,
112
+ cachedSegments: Set<number>,
113
+ ): number[] => {
114
+ return desiredSegments.filter(
115
+ (segmentId) =>
116
+ !activeRequests.has(segmentId) && !cachedSegments.has(segmentId),
117
+ );
118
+ };
119
+
120
+ /**
121
+ * Handle seek time change and recompute buffer queue
122
+ * Pure function - computes new queue when seek time changes
123
+ */
124
+ export const handleSeekTimeChange = <T extends AudioRendition | VideoRendition>(
125
+ newSeekTimeMs: number,
126
+ bufferDurationMs: number,
127
+ rendition: T,
128
+ currentState: MediaBufferState,
129
+ computeSegmentId: (timeMs: number, rendition: T) => number | undefined,
130
+ ): { newQueue: number[]; overlappingRequests: number[] } => {
131
+ const endTimeMs = newSeekTimeMs + bufferDurationMs;
132
+ const desiredSegments = computeSegmentRange(
133
+ newSeekTimeMs,
134
+ endTimeMs,
135
+ rendition,
136
+ computeSegmentId,
137
+ );
138
+
139
+ // Find segments that are already being requested
140
+ const overlappingRequests = desiredSegments.filter((segmentId) =>
141
+ currentState.activeRequests.has(segmentId),
142
+ );
143
+
144
+ const newQueue = computeBufferQueue(
145
+ desiredSegments,
146
+ currentState.activeRequests,
147
+ currentState.cachedSegments,
148
+ );
149
+
150
+ return { newQueue, overlappingRequests };
151
+ };
152
+
153
+ /**
154
+ * Check if a specific segment is cached in the buffer
155
+ * Pure function for accessing buffer cache state
156
+ */
157
+ export const getCachedSegment = (
158
+ segmentId: number,
159
+ bufferState: MediaBufferState | undefined,
160
+ ): boolean => {
161
+ return bufferState?.cachedSegments.has(segmentId) ?? false;
162
+ };
163
+
164
+ /**
165
+ * Get cached segments from a list of segment IDs
166
+ * Pure function that returns which segments are available in cache
167
+ */
168
+ export const getCachedSegments = (
169
+ segmentIds: number[],
170
+ bufferState: MediaBufferState | undefined,
171
+ ): Set<number> => {
172
+ if (!bufferState) {
173
+ return new Set();
174
+ }
175
+ return new Set(segmentIds.filter((id) => bufferState.cachedSegments.has(id)));
176
+ };
177
+
178
+ /**
179
+ * Get missing segments from a list of segment IDs
180
+ * Pure function that returns which segments need to be fetched
181
+ */
182
+ export const getMissingSegments = (
183
+ segmentIds: number[],
184
+ bufferState: MediaBufferState | undefined,
185
+ ): number[] => {
186
+ if (!bufferState) {
187
+ return segmentIds;
188
+ }
189
+ return segmentIds.filter((id) => !bufferState.cachedSegments.has(id));
190
+ };
191
+
192
+ /**
193
+ * Core media buffering logic with explicit dependencies
194
+ * Generic implementation that works for both audio and video
195
+ */
196
+ export const manageMediaBuffer = async <
197
+ T extends AudioRendition | VideoRendition,
198
+ >(
199
+ seekTimeMs: number,
200
+ config: MediaBufferConfig,
201
+ currentState: MediaBufferState,
202
+ durationMs: number,
203
+ signal: AbortSignal,
204
+ deps: MediaBufferDependencies<T>,
205
+ ): Promise<MediaBufferState> => {
206
+ if (!config.enableBuffering) {
207
+ return currentState;
208
+ }
209
+
210
+ const rendition = await deps.getRendition();
211
+ const endTimeMs = seekTimeMs + config.bufferDurationMs;
212
+
213
+ const desiredSegments = await computeSegmentRangeAsync(
214
+ seekTimeMs,
215
+ endTimeMs,
216
+ durationMs,
217
+ rendition,
218
+ deps.computeSegmentId,
219
+ );
220
+
221
+ const newQueue = computeBufferQueue(
222
+ desiredSegments,
223
+ currentState.activeRequests,
224
+ currentState.cachedSegments,
225
+ );
226
+
227
+ // Start fetching segments up to maxParallelFetches limit
228
+ const segmentsToFetch = newQueue.slice(0, config.maxParallelFetches);
229
+ const newActiveRequests = new Set(currentState.activeRequests);
230
+ const newCachedSegments = new Set(currentState.cachedSegments);
231
+
232
+ // Function to start next individual segment when a slot becomes available
233
+ const startNextSegment = (remainingQueue: number[]): void => {
234
+ if (remainingQueue.length === 0 || signal.aborted) return;
235
+
236
+ const availableSlots = config.maxParallelFetches - newActiveRequests.size;
237
+ if (availableSlots <= 0) return;
238
+
239
+ const nextSegmentId = remainingQueue[0];
240
+ if (nextSegmentId === undefined) return;
241
+
242
+ if (
243
+ newActiveRequests.has(nextSegmentId) ||
244
+ newCachedSegments.has(nextSegmentId)
245
+ ) {
246
+ // Skip this segment and try the next
247
+ startNextSegment(remainingQueue.slice(1));
248
+ return;
249
+ }
250
+
251
+ newActiveRequests.add(nextSegmentId);
252
+
253
+ deps
254
+ .fetchSegment(nextSegmentId, rendition)
255
+ .then(() => {
256
+ if (signal.aborted) return;
257
+ newActiveRequests.delete(nextSegmentId);
258
+ newCachedSegments.add(nextSegmentId);
259
+ startNextSegment(remainingQueue.slice(1));
260
+ })
261
+ .catch((error) => {
262
+ if (signal.aborted) return;
263
+ newActiveRequests.delete(nextSegmentId);
264
+ deps.logError(`Failed to fetch segment ${nextSegmentId}`, error);
265
+ startNextSegment(remainingQueue.slice(1));
266
+ });
267
+ };
268
+
269
+ // Start fetch promises for new segments
270
+ for (const segmentId of segmentsToFetch) {
271
+ if (signal.aborted) break;
272
+
273
+ newActiveRequests.add(segmentId);
274
+
275
+ // Start fetch (don't await - let it run in background)
276
+ deps
277
+ .fetchSegment(segmentId, rendition)
278
+ .then(() => {
279
+ if (signal.aborted) return;
280
+ // On success, move from active to cached
281
+ newActiveRequests.delete(segmentId);
282
+ newCachedSegments.add(segmentId);
283
+
284
+ // Continue buffering if there are more segments needed and continuous buffering is enabled
285
+ if (config.enableContinuousBuffering ?? true) {
286
+ const remainingQueue = newQueue.slice(segmentsToFetch.length);
287
+ startNextSegment(remainingQueue);
288
+ }
289
+ })
290
+ .catch((error) => {
291
+ if (signal.aborted) return;
292
+ // On error, remove from active and continue
293
+ newActiveRequests.delete(segmentId);
294
+ deps.logError(`Failed to fetch segment ${segmentId}`, error);
295
+
296
+ // Continue buffering even after error if continuous buffering is enabled
297
+ if (config.enableContinuousBuffering ?? true) {
298
+ const remainingQueue = newQueue.slice(segmentsToFetch.length);
299
+ startNextSegment(remainingQueue);
300
+ }
301
+ });
302
+ }
303
+
304
+ return {
305
+ currentSeekTimeMs: seekTimeMs,
306
+ activeRequests: newActiveRequests,
307
+ cachedSegments: newCachedSegments,
308
+ requestQueue: newQueue.slice(segmentsToFetch.length), // Remaining queue
309
+ };
310
+ };
@@ -0,0 +1,44 @@
1
+ import type { Task } from "@lit/task";
2
+ import type {
3
+ AudioRendition,
4
+ MediaEngine,
5
+ VideoRendition,
6
+ } from "../../../transcoding/types";
7
+ import type { BufferedSeekingInput } from "../BufferedSeekingInput";
8
+
9
+ /**
10
+ * Generic rendition type that can be either audio or video
11
+ */
12
+ export type MediaRendition = AudioRendition | VideoRendition;
13
+
14
+ /**
15
+ * Generic task type for init segment fetch
16
+ */
17
+ export type InitSegmentFetchTask = Task<
18
+ readonly [MediaEngine | undefined],
19
+ ArrayBuffer
20
+ >;
21
+
22
+ /**
23
+ * Generic task type for segment ID calculation
24
+ */
25
+ export type SegmentIdTask = Task<
26
+ readonly [MediaEngine | undefined, number],
27
+ number | undefined
28
+ >;
29
+
30
+ /**
31
+ * Generic task type for segment fetch
32
+ */
33
+ export type SegmentFetchTask = Task<
34
+ readonly [MediaEngine | undefined, number | undefined],
35
+ ArrayBuffer
36
+ >;
37
+
38
+ /**
39
+ * Generic task type for input creation
40
+ */
41
+ export type InputTask = Task<
42
+ readonly [ArrayBuffer, ArrayBuffer],
43
+ BufferedSeekingInput
44
+ >;