@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,554 @@
1
+ import { TaskStatus } from "@lit/task";
2
+ import { customElement } from "lit/decorators.js";
3
+ import { afterEach, describe, vi } from "vitest";
4
+ import { test as baseTest } from "../../../../test/useMSW.js";
5
+ import type { AudioRendition } from "../../../transcoding/types";
6
+ import { EFMedia } from "../../EFMedia";
7
+ import {
8
+ computeBufferQueue,
9
+ computeSegmentRange,
10
+ computeSegmentRangeAsync,
11
+ getCachedSegment,
12
+ getCachedSegments,
13
+ getMissingSegments,
14
+ handleSeekTimeChange,
15
+ type MediaBufferDependencies,
16
+ type MediaBufferState,
17
+ manageMediaBuffer,
18
+ } from "../shared/BufferUtils";
19
+ import {
20
+ type AudioBufferConfig,
21
+ type AudioBufferState,
22
+ makeAudioBufferTask,
23
+ } from "./makeAudioBufferTask";
24
+
25
+ @customElement("test-media-audio-buffer")
26
+ class TestMediaAudioBuffer extends EFMedia {}
27
+
28
+ declare global {
29
+ interface HTMLElementTagNameMap {
30
+ "test-media-audio-buffer": TestMediaAudioBuffer;
31
+ }
32
+ }
33
+
34
+ // Test that shows the task should use EFMedia properties directly
35
+ describe("makeAudioBufferTask - EFMedia Property Integration", () => {
36
+ test("should allow creating task without hardcoded config parameter", ({
37
+ expect,
38
+ }) => {
39
+ const element = document.createElement("test-media-audio-buffer");
40
+
41
+ // Set custom values on the element
42
+ element.audioBufferDurationMs = 45000;
43
+ element.maxAudioBufferFetches = 5;
44
+ element.enableAudioBuffering = false;
45
+
46
+ // This should work without passing a config parameter
47
+ expect(() => {
48
+ const task = makeAudioBufferTask(element);
49
+ expect(task).toBeDefined();
50
+ }).not.toThrow();
51
+
52
+ element.remove();
53
+ });
54
+ });
55
+
56
+ const test = baseTest.extend<{
57
+ element: TestMediaAudioBuffer;
58
+ mockAudioRendition: {
59
+ segmentDurationMs: number;
60
+ trackId: number;
61
+ src: string;
62
+ };
63
+ mockConfig: AudioBufferConfig;
64
+ mockState: AudioBufferState;
65
+ mockDeps: MediaBufferDependencies<AudioRendition>;
66
+ mockSignal: AbortSignal;
67
+ }>({
68
+ element: async ({}, use) => {
69
+ const element = document.createElement("test-media-audio-buffer");
70
+ await use(element);
71
+ element.remove();
72
+ },
73
+
74
+ mockAudioRendition: async ({}, use) => {
75
+ const rendition = {
76
+ segmentDurationMs: 1000, // 1 second per segment
77
+ trackId: 1,
78
+ src: "test-audio.mp4",
79
+ };
80
+ await use(rendition);
81
+ },
82
+
83
+ mockConfig: async ({}, use) => {
84
+ const config = {
85
+ bufferDurationMs: 5000, // 5 seconds
86
+ maxParallelFetches: 2,
87
+ enableBuffering: true,
88
+ enableContinuousBuffering: false, // Disable for predictable testing
89
+ };
90
+ await use(config);
91
+ },
92
+
93
+ mockState: async ({}, use) => {
94
+ const state = {
95
+ currentSeekTimeMs: 0,
96
+ activeRequests: new Set<number>(),
97
+ cachedSegments: new Set<number>(),
98
+ requestQueue: [],
99
+ };
100
+ await use(state);
101
+ },
102
+
103
+ mockDeps: async ({ mockAudioRendition }, use) => {
104
+ const deps = {
105
+ computeSegmentId: vi.fn(
106
+ async (timeMs: number, rendition: { segmentDurationMs?: number }) => {
107
+ return Math.floor(timeMs / (rendition.segmentDurationMs || 1000));
108
+ },
109
+ ),
110
+ fetchSegment: vi.fn().mockResolvedValue(new ArrayBuffer(1024)),
111
+ getRendition: vi.fn().mockResolvedValue(mockAudioRendition),
112
+ logError: vi.fn(),
113
+ };
114
+ await use(deps);
115
+ },
116
+
117
+ mockSignal: async ({}, use) => {
118
+ const mockSignal = new AbortController().signal;
119
+ await use(mockSignal);
120
+ },
121
+ });
122
+
123
+ describe("computeSegmentRange", () => {
124
+ test("computes segment range correctly", ({ mockAudioRendition, expect }) => {
125
+ const computeSegmentId = (
126
+ timeMs: number,
127
+ rendition: { segmentDurationMs: number },
128
+ ) => Math.floor(timeMs / (rendition.segmentDurationMs || 1000));
129
+
130
+ const segments = computeSegmentRange(
131
+ 2000, // start at 2 seconds
132
+ 5000, // end at 5 seconds
133
+ mockAudioRendition,
134
+ computeSegmentId,
135
+ );
136
+
137
+ expect(segments).toEqual([2, 3, 4, 5]); // segments 2, 3, 4, 5
138
+ });
139
+
140
+ test("returns empty array when segment IDs are undefined", ({
141
+ mockAudioRendition,
142
+ expect,
143
+ }) => {
144
+ const computeSegmentId = () => undefined;
145
+
146
+ const segments = computeSegmentRange(
147
+ 2000,
148
+ 5000,
149
+ mockAudioRendition,
150
+ computeSegmentId,
151
+ );
152
+
153
+ expect(segments).toEqual([]);
154
+ });
155
+
156
+ test("uses default segment duration when missing", ({ expect }) => {
157
+ const rendition = {}; // Missing segmentDurationMs
158
+ const computeSegmentId = () => 1;
159
+
160
+ const segments = computeSegmentRange(
161
+ 2000,
162
+ 5000,
163
+ rendition as any,
164
+ computeSegmentId,
165
+ );
166
+
167
+ // Should use default 1000ms duration and call computeSegmentId for segments 2, 3, 4, 5
168
+ // Since computeSegmentId always returns 1, and duplicates are filtered out, result is [1]
169
+ expect(segments).toEqual([1]); // duplicates filtered out
170
+ });
171
+ });
172
+
173
+ describe("computeSegmentRangeAsync", () => {
174
+ test("computes segment range with video duration limit", async ({
175
+ mockAudioRendition,
176
+ expect,
177
+ }) => {
178
+ const computeSegmentId = async (timeMs: number) =>
179
+ Math.floor(timeMs / 1000);
180
+
181
+ const segments = await computeSegmentRangeAsync(
182
+ 8000, // start at 8 seconds
183
+ 12000, // want to end at 12 seconds
184
+ 10000, // but video only lasts 10 seconds
185
+ mockAudioRendition,
186
+ computeSegmentId,
187
+ );
188
+
189
+ expect(segments).toEqual([8, 9]); // Limited to video duration, segment 10 would be at 10000ms which is not < 10000
190
+ });
191
+
192
+ test("handles large duration limit", async ({
193
+ mockAudioRendition,
194
+ expect,
195
+ }) => {
196
+ const computeSegmentId = async (timeMs: number) =>
197
+ Math.floor(timeMs / 1000);
198
+
199
+ const segments = await computeSegmentRangeAsync(
200
+ 2000,
201
+ 5000,
202
+ 100000, // Large duration limit - effectively unlimited
203
+ mockAudioRendition,
204
+ computeSegmentId,
205
+ );
206
+
207
+ expect(segments).toEqual([2, 3, 4, 5]);
208
+ });
209
+ });
210
+
211
+ describe("computeBufferQueue", () => {
212
+ test("filters out active and cached segments", ({ expect }) => {
213
+ const desiredSegments = [1, 2, 3, 4, 5];
214
+ const activeRequests = new Set([2, 4]);
215
+ const cachedSegments = new Set([1]);
216
+
217
+ const queue = computeBufferQueue(
218
+ desiredSegments,
219
+ activeRequests,
220
+ cachedSegments,
221
+ );
222
+
223
+ expect(queue).toEqual([3, 5]); // Only segments not active or cached
224
+ });
225
+
226
+ test("returns empty queue when all segments handled", ({ expect }) => {
227
+ const desiredSegments = [1, 2, 3];
228
+ const activeRequests = new Set([2]);
229
+ const cachedSegments = new Set([1, 3]);
230
+
231
+ const queue = computeBufferQueue(
232
+ desiredSegments,
233
+ activeRequests,
234
+ cachedSegments,
235
+ );
236
+
237
+ expect(queue).toEqual([]);
238
+ });
239
+ });
240
+
241
+ describe("handleSeekTimeChange", () => {
242
+ test("computes new queue for seek time change", ({
243
+ mockAudioRendition,
244
+ expect,
245
+ }) => {
246
+ const computeSegmentId = (timeMs: number) => Math.floor(timeMs / 1000);
247
+ const currentState = {
248
+ currentSeekTimeMs: 0,
249
+ activeRequests: new Set([1]),
250
+ cachedSegments: new Set([0]),
251
+ requestQueue: [],
252
+ };
253
+
254
+ const result = handleSeekTimeChange(
255
+ 3000, // seek to 3 seconds
256
+ 2000, // buffer 2 seconds ahead
257
+ mockAudioRendition,
258
+ currentState,
259
+ computeSegmentId,
260
+ );
261
+
262
+ expect(result.newQueue).toEqual([3, 4, 5]); // segments 3, 4, 5 needed, none in cache/active
263
+ expect(result.overlappingRequests).toEqual([]); // no overlap with active requests
264
+ });
265
+
266
+ test("identifies overlapping requests", ({ mockAudioRendition, expect }) => {
267
+ const computeSegmentId = (timeMs: number) => Math.floor(timeMs / 1000);
268
+ const currentState = {
269
+ currentSeekTimeMs: 0,
270
+ activeRequests: new Set([3, 4]),
271
+ cachedSegments: new Set([]),
272
+ requestQueue: [],
273
+ };
274
+
275
+ const result = handleSeekTimeChange(
276
+ 3000, // seek to 3 seconds
277
+ 2000, // buffer 2 seconds ahead
278
+ mockAudioRendition,
279
+ currentState,
280
+ computeSegmentId,
281
+ );
282
+
283
+ expect(result.overlappingRequests).toEqual([3, 4]); // both are already being fetched
284
+ expect(result.newQueue).toEqual([5]); // only segment 5 needs fetching
285
+ });
286
+ });
287
+
288
+ describe("manageMediaBuffer (Audio)", () => {
289
+ test("manages buffer state successfully", async ({
290
+ mockConfig,
291
+ mockState,
292
+ mockDeps,
293
+ mockSignal,
294
+ expect,
295
+ }) => {
296
+ const seekTimeMs = 3000;
297
+
298
+ const newState = await manageMediaBuffer(
299
+ seekTimeMs,
300
+ mockConfig,
301
+ mockState,
302
+ 10000, // durationMs
303
+ mockSignal,
304
+ mockDeps,
305
+ );
306
+
307
+ expect(newState.currentSeekTimeMs).toBe(seekTimeMs);
308
+ expect(mockDeps.getRendition).toHaveBeenCalled();
309
+ expect(mockDeps.fetchSegment).toHaveBeenCalledTimes(2); // maxParallelFetches = 2
310
+ });
311
+
312
+ test("respects maxParallelFetches limit", async ({
313
+ mockState,
314
+ mockDeps,
315
+ mockSignal,
316
+ expect,
317
+ }) => {
318
+ const config = {
319
+ bufferDurationMs: 10000, // 10 seconds = 10 segments
320
+ maxParallelFetches: 3,
321
+ enableBuffering: true,
322
+ enableContinuousBuffering: false, // Disable for predictable testing
323
+ };
324
+
325
+ await manageMediaBuffer(
326
+ 0,
327
+ config,
328
+ mockState,
329
+ 10000, // durationMs
330
+ mockSignal,
331
+ mockDeps,
332
+ );
333
+
334
+ expect(mockDeps.fetchSegment).toHaveBeenCalledTimes(3); // Should only fetch 3 despite needing 10
335
+ });
336
+
337
+ test("does nothing when buffering disabled", async ({
338
+ mockState,
339
+ mockDeps,
340
+ mockSignal,
341
+ expect,
342
+ }) => {
343
+ const config = {
344
+ bufferDurationMs: 5000,
345
+ maxParallelFetches: 2,
346
+ enableBuffering: false,
347
+ };
348
+
349
+ const newState = await manageMediaBuffer(
350
+ 1000,
351
+ config,
352
+ mockState,
353
+ 10000, // durationMs
354
+ mockSignal,
355
+ mockDeps,
356
+ );
357
+
358
+ expect(newState).toBe(mockState); // Should return same state
359
+ expect(mockDeps.fetchSegment).not.toHaveBeenCalled();
360
+ });
361
+
362
+ test("handles fetch errors gracefully", async ({
363
+ mockConfig,
364
+ mockState,
365
+ mockSignal,
366
+ expect,
367
+ }) => {
368
+ const mockDeps = {
369
+ computeSegmentId: vi.fn().mockResolvedValue(1),
370
+ fetchSegment: vi.fn().mockRejectedValue(new Error("Network error")),
371
+ getRendition: vi.fn().mockResolvedValue({ segmentDurationMs: 1000 }),
372
+ logError: vi.fn(),
373
+ };
374
+
375
+ const newState = await manageMediaBuffer(
376
+ 1000,
377
+ mockConfig,
378
+ mockState,
379
+ 10000, // durationMs
380
+ mockSignal,
381
+ mockDeps,
382
+ );
383
+
384
+ // Wait for async error handling to complete
385
+ await new Promise((resolve) => setTimeout(resolve, 10));
386
+
387
+ expect(newState.currentSeekTimeMs).toBe(1000);
388
+ expect(mockDeps.logError).toHaveBeenCalledWith(
389
+ "Failed to fetch segment 1",
390
+ expect.any(Error),
391
+ );
392
+ });
393
+ });
394
+
395
+ describe("makeAudioBufferTask", () => {
396
+ afterEach(() => {
397
+ const elements = document.querySelectorAll("test-media-audio-buffer");
398
+ for (const element of elements) {
399
+ element.remove();
400
+ }
401
+ vi.restoreAllMocks();
402
+ });
403
+
404
+ test("creates task with correct configuration", ({ element, expect }) => {
405
+ const task = makeAudioBufferTask(element);
406
+
407
+ expect(task).toBeDefined();
408
+ expect(task.status).toBe(TaskStatus.INITIAL);
409
+ expect(task.value).toBeUndefined();
410
+ expect(task.error).toBeUndefined();
411
+ });
412
+
413
+ test("task integrates with element seek time", ({ element, expect }) => {
414
+ element.desiredSeekTimeMs = 5000;
415
+
416
+ const task = makeAudioBufferTask(element);
417
+ expect(task).toBeDefined();
418
+ expect(task.status).toBe(TaskStatus.INITIAL);
419
+ });
420
+ });
421
+
422
+ describe("Cache Access Methods", () => {
423
+ test("getCachedSegment returns true for cached segments", ({ expect }) => {
424
+ const bufferState: MediaBufferState = {
425
+ currentSeekTimeMs: 0,
426
+ activeRequests: new Set(),
427
+ cachedSegments: new Set([1, 2, 3]),
428
+ requestQueue: [],
429
+ };
430
+
431
+ expect(getCachedSegment(1, bufferState)).toBe(true);
432
+ expect(getCachedSegment(2, bufferState)).toBe(true);
433
+ expect(getCachedSegment(4, bufferState)).toBe(false);
434
+ });
435
+
436
+ test("getCachedSegment returns false for undefined buffer state", ({
437
+ expect,
438
+ }) => {
439
+ expect(getCachedSegment(1, undefined)).toBe(false);
440
+ });
441
+
442
+ test("getCachedSegments returns correct cached segment set", ({ expect }) => {
443
+ const bufferState: MediaBufferState = {
444
+ currentSeekTimeMs: 0,
445
+ activeRequests: new Set(),
446
+ cachedSegments: new Set([2, 4, 6]),
447
+ requestQueue: [],
448
+ };
449
+
450
+ const requestedSegments = [1, 2, 3, 4, 5, 6];
451
+ const cachedSegments = getCachedSegments(requestedSegments, bufferState);
452
+
453
+ expect(cachedSegments).toEqual(new Set([2, 4, 6]));
454
+ });
455
+
456
+ test("getCachedSegments returns empty set for undefined buffer state", ({
457
+ expect,
458
+ }) => {
459
+ const requestedSegments = [1, 2, 3];
460
+ const cachedSegments = getCachedSegments(requestedSegments, undefined);
461
+
462
+ expect(cachedSegments).toEqual(new Set());
463
+ });
464
+
465
+ test("getMissingSegments returns correct missing segments", ({ expect }) => {
466
+ const bufferState: MediaBufferState = {
467
+ currentSeekTimeMs: 0,
468
+ activeRequests: new Set(),
469
+ cachedSegments: new Set([2, 4, 6]),
470
+ requestQueue: [],
471
+ };
472
+
473
+ const requestedSegments = [1, 2, 3, 4, 5, 6];
474
+ const missingSegments = getMissingSegments(requestedSegments, bufferState);
475
+
476
+ expect(missingSegments).toEqual([1, 3, 5]);
477
+ });
478
+
479
+ test("getMissingSegments returns all segments for undefined buffer state", ({
480
+ expect,
481
+ }) => {
482
+ const requestedSegments = [1, 2, 3];
483
+ const missingSegments = getMissingSegments(requestedSegments, undefined);
484
+
485
+ expect(missingSegments).toEqual([1, 2, 3]);
486
+ });
487
+ });
488
+
489
+ describe("Continuous Buffering", () => {
490
+ test("enables continuous segment loading when enabled", async ({
491
+ mockState,
492
+ mockDeps,
493
+ mockSignal,
494
+ expect,
495
+ }) => {
496
+ const configWithContinuous = {
497
+ bufferDurationMs: 10000, // 10 seconds = 10 segments
498
+ maxParallelFetches: 2,
499
+ enableBuffering: true,
500
+ enableContinuousBuffering: true, // Enable continuous buffering
501
+ };
502
+
503
+ let fetchCount = 0;
504
+ const mockFetchWithDelay = vi.fn().mockImplementation(() => {
505
+ fetchCount++;
506
+ return Promise.resolve(new ArrayBuffer(1000));
507
+ });
508
+
509
+ const mockDepsWithContinuous = {
510
+ ...mockDeps,
511
+ fetchSegment: mockFetchWithDelay,
512
+ };
513
+
514
+ await manageMediaBuffer(
515
+ 0,
516
+ configWithContinuous,
517
+ mockState,
518
+ 10000, // durationMs
519
+ mockSignal,
520
+ mockDepsWithContinuous,
521
+ );
522
+
523
+ // Should start with initial maxParallelFetches (2) and continue with more requests
524
+ // Continuous buffering should fetch more segments as previous ones complete
525
+ expect(mockFetchWithDelay).toHaveBeenCalledTimes(4); // More than initial batch due to continuous buffering
526
+ expect(fetchCount).toBe(4);
527
+ });
528
+
529
+ test("disabled when flag is false", async ({
530
+ mockState,
531
+ mockDeps,
532
+ mockSignal,
533
+ expect,
534
+ }) => {
535
+ const configWithoutContinuous = {
536
+ bufferDurationMs: 10000, // 10 seconds = 10 segments
537
+ maxParallelFetches: 2,
538
+ enableBuffering: true,
539
+ enableContinuousBuffering: false, // Disable continuous buffering
540
+ };
541
+
542
+ await manageMediaBuffer(
543
+ 0,
544
+ configWithoutContinuous,
545
+ mockState,
546
+ 10000, // durationMs
547
+ mockSignal,
548
+ mockDeps,
549
+ );
550
+
551
+ // Should only fetch initial maxParallelFetches and stop
552
+ expect(mockDeps.fetchSegment).toHaveBeenCalledTimes(2);
553
+ });
554
+ });
@@ -0,0 +1,81 @@
1
+ import { Task } from "@lit/task";
2
+
3
+ import { EF_INTERACTIVE } from "../../../EF_INTERACTIVE";
4
+ import { EF_RENDERING } from "../../../EF_RENDERING";
5
+ import type { AudioRendition } from "../../../transcoding/types";
6
+ import type { EFMedia } from "../../EFMedia";
7
+ import {
8
+ type MediaBufferConfig,
9
+ type MediaBufferState,
10
+ manageMediaBuffer,
11
+ } from "../shared/BufferUtils";
12
+ import { getLatestMediaEngine } from "../tasks/makeMediaEngineTask";
13
+
14
+ /**
15
+ * Configuration for audio buffering - extends the generic interface
16
+ */
17
+ export interface AudioBufferConfig extends MediaBufferConfig {}
18
+
19
+ /**
20
+ * State of the audio buffer - uses the generic interface
21
+ */
22
+ export interface AudioBufferState extends MediaBufferState {}
23
+
24
+ type AudioBufferTask = Task<readonly [number], AudioBufferState>;
25
+ export const makeAudioBufferTask = (host: EFMedia): AudioBufferTask => {
26
+ let currentState: AudioBufferState = {
27
+ currentSeekTimeMs: 0,
28
+ activeRequests: new Set(),
29
+ cachedSegments: new Set(),
30
+ requestQueue: [],
31
+ };
32
+
33
+ return new Task(host, {
34
+ autoRun: EF_INTERACTIVE, // Start buffering automatically when media is ready
35
+ args: () => [host.desiredSeekTimeMs] as const,
36
+ onError: (error) => {
37
+ console.error("audioBufferTask error", error);
38
+ },
39
+ onComplete: (value) => {
40
+ currentState = value;
41
+ },
42
+ task: async ([seekTimeMs], { signal }) => {
43
+ // Use EFMedia properties directly - no hardcoded duplication!
44
+ const currentConfig: AudioBufferConfig = {
45
+ bufferDurationMs: host.audioBufferDurationMs,
46
+ maxParallelFetches: host.maxAudioBufferFetches,
47
+ enableBuffering: host.enableAudioBuffering && !EF_RENDERING,
48
+ };
49
+
50
+ return manageMediaBuffer<AudioRendition>(
51
+ seekTimeMs,
52
+ currentConfig,
53
+ currentState,
54
+ (host as any).intrinsicDurationMs || 10000,
55
+ signal,
56
+ {
57
+ computeSegmentId: async (timeMs, rendition) => {
58
+ // Use media engine's computeSegmentId
59
+ const mediaEngine = await getLatestMediaEngine(host, signal);
60
+ return mediaEngine.computeSegmentId(timeMs, rendition);
61
+ },
62
+ fetchSegment: async (segmentId, rendition) => {
63
+ // SIMPLIFIED: Direct call to mediaEngine - deduplication is built-in
64
+ const mediaEngine = await getLatestMediaEngine(host, signal);
65
+ return mediaEngine.fetchMediaSegment(segmentId, rendition);
66
+ },
67
+ getRendition: async () => {
68
+ // Get real audio rendition from media engine
69
+ const mediaEngine = await getLatestMediaEngine(host, signal);
70
+ const audioRendition = mediaEngine.audioRendition;
71
+ if (!audioRendition) {
72
+ throw new Error("Audio rendition not available");
73
+ }
74
+ return audioRendition;
75
+ },
76
+ logError: console.error,
77
+ },
78
+ );
79
+ },
80
+ });
81
+ };