@editframe/elements 0.17.6-beta.0 → 0.18.7-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 (211) hide show
  1. package/dist/EF_FRAMEGEN.js +1 -1
  2. package/dist/elements/EFAudio.d.ts +21 -2
  3. package/dist/elements/EFAudio.js +41 -11
  4. package/dist/elements/EFImage.d.ts +1 -0
  5. package/dist/elements/EFImage.js +11 -3
  6. package/dist/elements/EFMedia/AssetIdMediaEngine.d.ts +18 -0
  7. package/dist/elements/EFMedia/AssetIdMediaEngine.js +41 -0
  8. package/dist/elements/EFMedia/AssetMediaEngine.browsertest.d.ts +0 -0
  9. package/dist/elements/EFMedia/AssetMediaEngine.d.ts +45 -0
  10. package/dist/elements/EFMedia/AssetMediaEngine.js +135 -0
  11. package/dist/elements/EFMedia/BaseMediaEngine.d.ts +55 -0
  12. package/dist/elements/EFMedia/BaseMediaEngine.js +115 -0
  13. package/dist/elements/EFMedia/BufferedSeekingInput.d.ts +43 -0
  14. package/dist/elements/EFMedia/BufferedSeekingInput.js +179 -0
  15. package/dist/elements/EFMedia/JitMediaEngine.browsertest.d.ts +0 -0
  16. package/dist/elements/EFMedia/JitMediaEngine.d.ts +31 -0
  17. package/dist/elements/EFMedia/JitMediaEngine.js +81 -0
  18. package/dist/elements/EFMedia/audioTasks/makeAudioBufferTask.browsertest.d.ts +9 -0
  19. package/dist/elements/EFMedia/audioTasks/makeAudioBufferTask.d.ts +16 -0
  20. package/dist/elements/EFMedia/audioTasks/makeAudioBufferTask.js +48 -0
  21. package/dist/elements/EFMedia/audioTasks/makeAudioFrequencyAnalysisTask.d.ts +3 -0
  22. package/dist/elements/EFMedia/audioTasks/makeAudioFrequencyAnalysisTask.js +141 -0
  23. package/dist/elements/EFMedia/audioTasks/makeAudioInitSegmentFetchTask.browsertest.d.ts +9 -0
  24. package/dist/elements/EFMedia/audioTasks/makeAudioInitSegmentFetchTask.d.ts +4 -0
  25. package/dist/elements/EFMedia/audioTasks/makeAudioInitSegmentFetchTask.js +16 -0
  26. package/dist/elements/EFMedia/audioTasks/makeAudioInputTask.browsertest.d.ts +9 -0
  27. package/dist/elements/EFMedia/audioTasks/makeAudioInputTask.d.ts +3 -0
  28. package/dist/elements/EFMedia/audioTasks/makeAudioInputTask.js +30 -0
  29. package/dist/elements/EFMedia/audioTasks/makeAudioSeekTask.chunkboundary.regression.browsertest.d.ts +0 -0
  30. package/dist/elements/EFMedia/audioTasks/makeAudioSeekTask.d.ts +7 -0
  31. package/dist/elements/EFMedia/audioTasks/makeAudioSeekTask.js +32 -0
  32. package/dist/elements/EFMedia/audioTasks/makeAudioSegmentFetchTask.d.ts +4 -0
  33. package/dist/elements/EFMedia/audioTasks/makeAudioSegmentFetchTask.js +28 -0
  34. package/dist/elements/EFMedia/audioTasks/makeAudioSegmentIdTask.d.ts +4 -0
  35. package/dist/elements/EFMedia/audioTasks/makeAudioSegmentIdTask.js +17 -0
  36. package/dist/elements/EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.d.ts +3 -0
  37. package/dist/elements/EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.js +107 -0
  38. package/dist/elements/EFMedia/shared/AudioSpanUtils.d.ts +7 -0
  39. package/dist/elements/EFMedia/shared/AudioSpanUtils.js +54 -0
  40. package/dist/elements/EFMedia/shared/BufferUtils.d.ts +70 -0
  41. package/dist/elements/EFMedia/shared/BufferUtils.js +89 -0
  42. package/dist/elements/EFMedia/shared/MediaTaskUtils.d.ts +23 -0
  43. package/dist/elements/EFMedia/shared/PrecisionUtils.d.ts +28 -0
  44. package/dist/elements/EFMedia/shared/PrecisionUtils.js +29 -0
  45. package/dist/elements/EFMedia/shared/RenditionHelpers.d.ts +19 -0
  46. package/dist/elements/EFMedia/tasks/makeMediaEngineTask.d.ts +18 -0
  47. package/dist/elements/EFMedia/tasks/makeMediaEngineTask.js +60 -0
  48. package/dist/elements/EFMedia/videoTasks/makeVideoBufferTask.browsertest.d.ts +9 -0
  49. package/dist/elements/EFMedia/videoTasks/makeVideoBufferTask.d.ts +16 -0
  50. package/dist/elements/EFMedia/videoTasks/makeVideoBufferTask.js +46 -0
  51. package/dist/elements/EFMedia/videoTasks/makeVideoInitSegmentFetchTask.browsertest.d.ts +9 -0
  52. package/dist/elements/EFMedia/videoTasks/makeVideoInitSegmentFetchTask.d.ts +4 -0
  53. package/dist/elements/EFMedia/videoTasks/makeVideoInitSegmentFetchTask.js +16 -0
  54. package/dist/elements/EFMedia/videoTasks/makeVideoInputTask.browsertest.d.ts +9 -0
  55. package/dist/elements/EFMedia/videoTasks/makeVideoInputTask.d.ts +3 -0
  56. package/dist/elements/EFMedia/videoTasks/makeVideoInputTask.js +27 -0
  57. package/dist/elements/EFMedia/videoTasks/makeVideoSeekTask.d.ts +7 -0
  58. package/dist/elements/EFMedia/videoTasks/makeVideoSeekTask.js +34 -0
  59. package/dist/elements/EFMedia/videoTasks/makeVideoSegmentFetchTask.browsertest.d.ts +9 -0
  60. package/dist/elements/EFMedia/videoTasks/makeVideoSegmentFetchTask.d.ts +4 -0
  61. package/dist/elements/EFMedia/videoTasks/makeVideoSegmentFetchTask.js +28 -0
  62. package/dist/elements/EFMedia/videoTasks/makeVideoSegmentIdTask.browsertest.d.ts +9 -0
  63. package/dist/elements/EFMedia/videoTasks/makeVideoSegmentIdTask.d.ts +4 -0
  64. package/dist/elements/EFMedia/videoTasks/makeVideoSegmentIdTask.js +17 -0
  65. package/dist/elements/EFMedia.browsertest.d.ts +1 -0
  66. package/dist/elements/EFMedia.d.ts +63 -111
  67. package/dist/elements/EFMedia.js +117 -1113
  68. package/dist/elements/EFTemporal.d.ts +1 -1
  69. package/dist/elements/EFTemporal.js +1 -1
  70. package/dist/elements/EFTimegroup.d.ts +11 -0
  71. package/dist/elements/EFTimegroup.js +83 -13
  72. package/dist/elements/EFVideo.d.ts +54 -32
  73. package/dist/elements/EFVideo.js +100 -207
  74. package/dist/elements/EFWaveform.js +2 -2
  75. package/dist/elements/SampleBuffer.d.ts +14 -0
  76. package/dist/elements/SampleBuffer.js +52 -0
  77. package/dist/getRenderInfo.js +2 -1
  78. package/dist/gui/ContextMixin.js +3 -2
  79. package/dist/gui/EFFilmstrip.d.ts +3 -3
  80. package/dist/gui/EFFilmstrip.js +1 -1
  81. package/dist/gui/EFFitScale.d.ts +2 -2
  82. package/dist/gui/TWMixin.js +1 -1
  83. package/dist/style.css +1 -1
  84. package/dist/transcoding/cache/CacheManager.d.ts +73 -0
  85. package/dist/transcoding/cache/RequestDeduplicator.d.ts +29 -0
  86. package/dist/transcoding/cache/RequestDeduplicator.js +53 -0
  87. package/dist/transcoding/cache/RequestDeduplicator.test.d.ts +1 -0
  88. package/dist/transcoding/types/index.d.ts +242 -0
  89. package/dist/transcoding/utils/MediaUtils.d.ts +9 -0
  90. package/dist/transcoding/utils/UrlGenerator.d.ts +26 -0
  91. package/dist/transcoding/utils/UrlGenerator.js +45 -0
  92. package/dist/transcoding/utils/constants.d.ts +27 -0
  93. package/dist/utils/LRUCache.d.ts +34 -0
  94. package/dist/utils/LRUCache.js +115 -0
  95. package/package.json +3 -3
  96. package/src/elements/EFAudio.browsertest.ts +189 -49
  97. package/src/elements/EFAudio.ts +59 -13
  98. package/src/elements/EFImage.browsertest.ts +42 -0
  99. package/src/elements/EFImage.ts +23 -3
  100. package/src/elements/EFMedia/AssetIdMediaEngine.test.ts +222 -0
  101. package/src/elements/EFMedia/AssetIdMediaEngine.ts +70 -0
  102. package/src/elements/EFMedia/AssetMediaEngine.browsertest.ts +100 -0
  103. package/src/elements/EFMedia/AssetMediaEngine.ts +255 -0
  104. package/src/elements/EFMedia/BaseMediaEngine.test.ts +164 -0
  105. package/src/elements/EFMedia/BaseMediaEngine.ts +219 -0
  106. package/src/elements/EFMedia/BufferedSeekingInput.browsertest.ts +481 -0
  107. package/src/elements/EFMedia/BufferedSeekingInput.ts +324 -0
  108. package/src/elements/EFMedia/JitMediaEngine.browsertest.ts +165 -0
  109. package/src/elements/EFMedia/JitMediaEngine.ts +166 -0
  110. package/src/elements/EFMedia/audioTasks/makeAudioBufferTask.browsertest.ts +554 -0
  111. package/src/elements/EFMedia/audioTasks/makeAudioBufferTask.ts +81 -0
  112. package/src/elements/EFMedia/audioTasks/makeAudioFrequencyAnalysisTask.ts +250 -0
  113. package/src/elements/EFMedia/audioTasks/makeAudioInitSegmentFetchTask.browsertest.ts +59 -0
  114. package/src/elements/EFMedia/audioTasks/makeAudioInitSegmentFetchTask.ts +23 -0
  115. package/src/elements/EFMedia/audioTasks/makeAudioInputTask.browsertest.ts +55 -0
  116. package/src/elements/EFMedia/audioTasks/makeAudioInputTask.ts +43 -0
  117. package/src/elements/EFMedia/audioTasks/makeAudioSeekTask.chunkboundary.regression.browsertest.ts +199 -0
  118. package/src/elements/EFMedia/audioTasks/makeAudioSeekTask.ts +64 -0
  119. package/src/elements/EFMedia/audioTasks/makeAudioSegmentFetchTask.ts +45 -0
  120. package/src/elements/EFMedia/audioTasks/makeAudioSegmentIdTask.ts +24 -0
  121. package/src/elements/EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.ts +183 -0
  122. package/src/elements/EFMedia/shared/AudioSpanUtils.ts +128 -0
  123. package/src/elements/EFMedia/shared/BufferUtils.ts +310 -0
  124. package/src/elements/EFMedia/shared/MediaTaskUtils.ts +44 -0
  125. package/src/elements/EFMedia/shared/PrecisionUtils.ts +46 -0
  126. package/src/elements/EFMedia/shared/RenditionHelpers.browsertest.ts +247 -0
  127. package/src/elements/EFMedia/shared/RenditionHelpers.ts +79 -0
  128. package/src/elements/EFMedia/tasks/makeMediaEngineTask.browsertest.ts +128 -0
  129. package/src/elements/EFMedia/tasks/makeMediaEngineTask.test.ts +233 -0
  130. package/src/elements/EFMedia/tasks/makeMediaEngineTask.ts +89 -0
  131. package/src/elements/EFMedia/videoTasks/makeVideoBufferTask.browsertest.ts +555 -0
  132. package/src/elements/EFMedia/videoTasks/makeVideoBufferTask.ts +79 -0
  133. package/src/elements/EFMedia/videoTasks/makeVideoInitSegmentFetchTask.browsertest.ts +59 -0
  134. package/src/elements/EFMedia/videoTasks/makeVideoInitSegmentFetchTask.ts +23 -0
  135. package/src/elements/EFMedia/videoTasks/makeVideoInputTask.browsertest.ts +55 -0
  136. package/src/elements/EFMedia/videoTasks/makeVideoInputTask.ts +45 -0
  137. package/src/elements/EFMedia/videoTasks/makeVideoSeekTask.ts +68 -0
  138. package/src/elements/EFMedia/videoTasks/makeVideoSegmentFetchTask.browsertest.ts +57 -0
  139. package/src/elements/EFMedia/videoTasks/makeVideoSegmentFetchTask.ts +43 -0
  140. package/src/elements/EFMedia/videoTasks/makeVideoSegmentIdTask.browsertest.ts +56 -0
  141. package/src/elements/EFMedia/videoTasks/makeVideoSegmentIdTask.ts +24 -0
  142. package/src/elements/EFMedia.browsertest.ts +706 -273
  143. package/src/elements/EFMedia.ts +136 -1769
  144. package/src/elements/EFTemporal.ts +3 -4
  145. package/src/elements/EFTimegroup.browsertest.ts +6 -3
  146. package/src/elements/EFTimegroup.ts +147 -21
  147. package/src/elements/EFVideo.browsertest.ts +980 -169
  148. package/src/elements/EFVideo.ts +113 -458
  149. package/src/elements/EFWaveform.ts +1 -1
  150. package/src/elements/MediaController.ts +2 -12
  151. package/src/elements/SampleBuffer.ts +95 -0
  152. package/src/gui/ContextMixin.ts +3 -6
  153. package/src/transcoding/cache/CacheManager.ts +208 -0
  154. package/src/transcoding/cache/RequestDeduplicator.test.ts +170 -0
  155. package/src/transcoding/cache/RequestDeduplicator.ts +65 -0
  156. package/src/transcoding/types/index.ts +269 -0
  157. package/src/transcoding/utils/MediaUtils.ts +63 -0
  158. package/src/transcoding/utils/UrlGenerator.ts +68 -0
  159. package/src/transcoding/utils/constants.ts +36 -0
  160. package/src/utils/LRUCache.ts +153 -0
  161. package/test/EFVideo.framegen.browsertest.ts +39 -30
  162. 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
  163. 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
  164. package/test/__cache__/GET__api_v1_transcode_audio_1_mp4_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4_bytes_0__9ed2d25c675aa6bb6ff5b3ae23887c71/data.bin +0 -0
  165. package/test/__cache__/GET__api_v1_transcode_audio_1_mp4_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4_bytes_0__9ed2d25c675aa6bb6ff5b3ae23887c71/metadata.json +22 -0
  166. 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
  167. 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
  168. package/test/__cache__/GET__api_v1_transcode_audio_2_mp4_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4_bytes_0__d5a3309a2bf756dd6e304807eb402f56/data.bin +0 -0
  169. package/test/__cache__/GET__api_v1_transcode_audio_2_mp4_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4_bytes_0__d5a3309a2bf756dd6e304807eb402f56/metadata.json +22 -0
  170. 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
  171. 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
  172. package/test/__cache__/GET__api_v1_transcode_audio_3_mp4_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4_bytes_0__773254bb671e3466fca8677139fb239e/data.bin +0 -0
  173. package/test/__cache__/GET__api_v1_transcode_audio_3_mp4_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4_bytes_0__773254bb671e3466fca8677139fb239e/metadata.json +22 -0
  174. 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
  175. 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
  176. 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
  177. 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
  178. 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
  179. 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
  180. 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
  181. 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
  182. 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
  183. 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
  184. 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
  185. 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
  186. package/test/__cache__/GET__api_v1_transcode_high_4_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__a6fb05a22b18d850f7f2950bbcdbdeed/data.bin +0 -0
  187. package/test/__cache__/GET__api_v1_transcode_high_4_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__a6fb05a22b18d850f7f2950bbcdbdeed/metadata.json +21 -0
  188. package/test/__cache__/GET__api_v1_transcode_high_5_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__a50058c7c3602e90879fe3428ed891f4/data.bin +0 -0
  189. package/test/__cache__/GET__api_v1_transcode_high_5_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__a50058c7c3602e90879fe3428ed891f4/metadata.json +21 -0
  190. 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
  191. 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
  192. package/test/__cache__/GET__api_v1_transcode_manifest_json_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__3be92a0437de726b431ed5af2369158a/data.bin +1 -0
  193. package/test/__cache__/GET__api_v1_transcode_manifest_json_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__3be92a0437de726b431ed5af2369158a/metadata.json +19 -0
  194. package/test/createJitTestClips.ts +320 -188
  195. package/test/recordReplayProxyPlugin.js +352 -0
  196. package/test/useAssetMSW.ts +1 -1
  197. package/test/useMSW.ts +35 -22
  198. package/types.json +1 -1
  199. package/dist/JitTranscodingClient.d.ts +0 -167
  200. package/dist/JitTranscodingClient.js +0 -373
  201. package/dist/ScrubTrackManager.d.ts +0 -96
  202. package/dist/ScrubTrackManager.js +0 -216
  203. package/dist/elements/printTaskStatus.js +0 -11
  204. package/src/elements/__screenshots__/EFMedia.browsertest.ts/EFMedia-JIT-audio-playback-audioBufferTask-should-work-in-JIT-mode-without-URL-errors-1.png +0 -0
  205. package/test/EFVideo.frame-tasks.browsertest.ts +0 -524
  206. /package/dist/{DecoderResetFrequency.test.d.ts → elements/EFMedia/AssetIdMediaEngine.test.d.ts} +0 -0
  207. /package/dist/{DecoderResetRecovery.test.d.ts → elements/EFMedia/BaseMediaEngine.test.d.ts} +0 -0
  208. /package/dist/{JitTranscodingClient.browsertest.d.ts → elements/EFMedia/BufferedSeekingInput.browsertest.d.ts} +0 -0
  209. /package/dist/{JitTranscodingClient.test.d.ts → elements/EFMedia/shared/RenditionHelpers.browsertest.d.ts} +0 -0
  210. /package/dist/{ScrubTrackIntegration.test.d.ts → elements/EFMedia/tasks/makeMediaEngineTask.browsertest.d.ts} +0 -0
  211. /package/dist/{SegmentSwitchLoading.test.d.ts → elements/EFMedia/tasks/makeMediaEngineTask.test.d.ts} +0 -0
@@ -103,7 +103,7 @@ var EFFramegen = class {
103
103
  });
104
104
  }
105
105
  get showFrameBox() {
106
- return true;
106
+ return this.renderOptions?.showFrameBox ?? false;
107
107
  }
108
108
  async initialize(renderOptions) {
109
109
  this.renderOptions = renderOptions;
@@ -1,13 +1,32 @@
1
1
  import { Task } from '@lit/task';
2
2
  import { EFMedia } from './EFMedia.js';
3
- export declare class EFAudio extends EFMedia {
3
+ declare const EFAudio_base: typeof EFMedia;
4
+ export declare class EFAudio extends EFAudio_base {
5
+ static get observedAttributes(): string[];
6
+ attributeChangedCallback(name: string, old: string | null, value: string | null): void;
4
7
  audioElementRef: import('lit-html/directives/ref.js').Ref<HTMLAudioElement>;
5
8
  render(): import('lit-html').TemplateResult<1>;
6
- get audioElement(): HTMLAudioElement | undefined;
7
9
  frameTask: Task<readonly [import('@lit/task').TaskStatus, import('@lit/task').TaskStatus, import('@lit/task').TaskStatus, import('@lit/task').TaskStatus], void>;
10
+ /**
11
+ * Legacy getter for fragment index task (maps to audioSegmentIdTask)
12
+ */
13
+ get fragmentIndexTask(): Task<readonly [import('../transcoding/types/index.js').MediaEngine | undefined, number], number | undefined>;
14
+ /**
15
+ * Legacy getter for media segments task (maps to audioSegmentFetchTask)
16
+ */
17
+ get mediaSegmentsTask(): Task<readonly [import('../transcoding/types/index.js').MediaEngine | undefined, number | undefined], ArrayBuffer>;
18
+ /**
19
+ * Legacy getter for seek task (maps to audioSeekTask)
20
+ */
21
+ get seekTask(): Task<readonly [number, import('./EFMedia/BufferedSeekingInput.js').BufferedSeekingInput | undefined], import('mediabunny').VideoSample | undefined>;
22
+ /**
23
+ * Legacy getter for audio asset task (maps to audioBufferTask)
24
+ */
25
+ get videoAssetTask(): Task<readonly [number], import('./EFMedia/audioTasks/makeAudioBufferTask.js').AudioBufferState>;
8
26
  }
9
27
  declare global {
10
28
  interface HTMLElementTagNameMap {
11
29
  "ef-audio": EFAudio;
12
30
  }
13
31
  }
32
+ export {};
@@ -1,34 +1,64 @@
1
1
  import { EFMedia } from "./EFMedia.js";
2
+ import { TWMixin } from "../gui/TWMixin2.js";
2
3
  import { Task } from "@lit/task";
3
4
  import { html } from "lit";
4
5
  import { customElement } from "lit/decorators.js";
5
6
  import _decorate from "@oxc-project/runtime/helpers/decorate";
6
7
  import { createRef, ref } from "lit/directives/ref.js";
7
- let EFAudio = class EFAudio$1 extends EFMedia {
8
+ let EFAudio = class EFAudio$1 extends TWMixin(EFMedia) {
8
9
  constructor(..._args) {
9
10
  super(..._args);
10
11
  this.audioElementRef = createRef();
11
12
  this.frameTask = new Task(this, {
12
13
  args: () => [
13
- this.fragmentIndexTask.status,
14
- this.seekTask.status,
15
- this.mediaSegmentsTask.status,
16
- this.videoAssetTask.status
14
+ this.audioBufferTask.status,
15
+ this.audioSeekTask.status,
16
+ this.audioSegmentFetchTask.status,
17
+ this.mediaEngineTask.status
17
18
  ],
18
19
  task: async () => {
19
- await this.fragmentIndexTask.taskComplete;
20
- await this.seekTask.taskComplete;
21
- await this.mediaSegmentsTask.taskComplete;
22
- await this.videoAssetTask.taskComplete;
20
+ await this.mediaEngineTask.taskComplete;
21
+ await this.audioSegmentFetchTask.taskComplete;
22
+ await this.audioSeekTask.taskComplete;
23
+ await this.audioBufferTask.taskComplete;
23
24
  this.rootTimegroup?.requestUpdate();
24
25
  }
25
26
  });
26
27
  }
28
+ static get observedAttributes() {
29
+ const parentAttributes = super.observedAttributes || [];
30
+ return [...parentAttributes];
31
+ }
32
+ attributeChangedCallback(name, old, value) {
33
+ super.attributeChangedCallback(name, old, value);
34
+ if (name === "asset-id") this.assetId = value;
35
+ }
27
36
  render() {
28
37
  return html`<audio ${ref(this.audioElementRef)}></audio>`;
29
38
  }
30
- get audioElement() {
31
- return this.audioElementRef.value;
39
+ /**
40
+ * Legacy getter for fragment index task (maps to audioSegmentIdTask)
41
+ */
42
+ get fragmentIndexTask() {
43
+ return this.audioSegmentIdTask;
44
+ }
45
+ /**
46
+ * Legacy getter for media segments task (maps to audioSegmentFetchTask)
47
+ */
48
+ get mediaSegmentsTask() {
49
+ return this.audioSegmentFetchTask;
50
+ }
51
+ /**
52
+ * Legacy getter for seek task (maps to audioSeekTask)
53
+ */
54
+ get seekTask() {
55
+ return this.audioSeekTask;
56
+ }
57
+ /**
58
+ * Legacy getter for audio asset task (maps to audioBufferTask)
59
+ */
60
+ get videoAssetTask() {
61
+ return this.audioBufferTask;
32
62
  }
33
63
  };
34
64
  EFAudio = _decorate([customElement("ef-audio")], EFAudio);
@@ -9,6 +9,7 @@ export declare class EFImage extends EFImage_base {
9
9
  set assetId(value: string | null);
10
10
  get assetId(): string | null;
11
11
  render(): import('lit-html').TemplateResult<1>;
12
+ private isDirectUrl;
12
13
  assetPath(): string;
13
14
  get hasOwnDuration(): boolean;
14
15
  fetchImage: Task<readonly [string, typeof fetch], void>;
@@ -16,11 +16,13 @@ let EFImage = class EFImage$1 extends EFTemporal(EFSourceMixin(FetchMixin(LitEle
16
16
  autoRun: EF_INTERACTIVE,
17
17
  args: () => [this.assetPath(), this.fetch],
18
18
  task: async ([assetPath, fetch], { signal }) => {
19
+ if (this.isDirectUrl(assetPath)) return;
19
20
  const response = await fetch(assetPath, { signal });
20
21
  const image = new Image();
21
22
  image.src = URL.createObjectURL(await response.blob());
22
- await new Promise((resolve) => {
23
+ await new Promise((resolve, reject) => {
23
24
  image.onload = resolve;
25
+ image.onerror = reject;
24
26
  });
25
27
  if (!this.canvasRef.value) throw new Error("Canvas not ready");
26
28
  const ctx = this.canvasRef.value.getContext("2d");
@@ -46,7 +48,7 @@ let EFImage = class EFImage$1 extends EFTemporal(EFSourceMixin(FetchMixin(LitEle
46
48
  align-items: center;
47
49
  justify-content: center;
48
50
  }
49
- canvas {
51
+ canvas, img {
50
52
  all: inherit;
51
53
  }
52
54
  `];
@@ -59,10 +61,16 @@ let EFImage = class EFImage$1 extends EFTemporal(EFSourceMixin(FetchMixin(LitEle
59
61
  return this.#assetId ?? this.getAttribute("asset-id");
60
62
  }
61
63
  render() {
62
- return html`<canvas ${ref(this.canvasRef)}></canvas>`;
64
+ const assetPath = this.assetPath();
65
+ const isDirectUrl = this.isDirectUrl(assetPath);
66
+ return isDirectUrl ? html`<img ${ref(this.imageRef)} src=${assetPath} />` : html`<canvas ${ref(this.canvasRef)}></canvas>`;
67
+ }
68
+ isDirectUrl(src) {
69
+ return src.startsWith("http://") || src.startsWith("https://");
63
70
  }
64
71
  assetPath() {
65
72
  if (this.assetId) return `${this.apiHost}/api/v1/image_files/${this.assetId}`;
73
+ if (this.isDirectUrl(this.src)) return this.src;
66
74
  return `/@ef-image/${this.src}`;
67
75
  }
68
76
  get hasOwnDuration() {
@@ -0,0 +1,18 @@
1
+ import { TrackFragmentIndex } from '../../../../assets/src/index.ts';
2
+ import { InitSegmentPaths, MediaEngine } from '../../transcoding/types';
3
+ import { UrlGenerator } from '../../transcoding/utils/UrlGenerator';
4
+ import { EFMedia } from '../EFMedia';
5
+ import { AssetMediaEngine } from './AssetMediaEngine';
6
+ export declare class AssetIdMediaEngine extends AssetMediaEngine implements MediaEngine {
7
+ assetId: string;
8
+ private apiHost;
9
+ static fetchByAssetId(host: EFMedia, _urlGenerator: UrlGenerator, assetId: string, apiHost: string): Promise<AssetIdMediaEngine>;
10
+ constructor(host: EFMedia, assetId: string, data: Record<number, TrackFragmentIndex>, apiHost: string);
11
+ get initSegmentPaths(): InitSegmentPaths;
12
+ get templates(): {
13
+ initSegment: string;
14
+ mediaSegment: string;
15
+ };
16
+ buildInitSegmentUrl(trackId: number): string;
17
+ buildMediaSegmentUrl(trackId: number, _segmentId: number): string;
18
+ }
@@ -0,0 +1,41 @@
1
+ import { AssetMediaEngine } from "./AssetMediaEngine.js";
2
+ var AssetIdMediaEngine = class AssetIdMediaEngine extends AssetMediaEngine {
3
+ static async fetchByAssetId(host, _urlGenerator, assetId, apiHost) {
4
+ const url = `${apiHost}/api/v1/isobmff_files/${assetId}/index`;
5
+ const response = await host.fetch(url);
6
+ const data = await response.json();
7
+ return new AssetIdMediaEngine(host, assetId, data, apiHost);
8
+ }
9
+ constructor(host, assetId, data, apiHost) {
10
+ super(host, assetId, data);
11
+ this.assetId = assetId;
12
+ this.apiHost = apiHost;
13
+ }
14
+ get initSegmentPaths() {
15
+ const paths = {};
16
+ if (this.audioTrackIndex !== void 0) paths.audio = {
17
+ path: `${this.apiHost}/api/v1/isobmff_tracks/${this.assetId}/${this.audioTrackIndex.track}`,
18
+ pos: this.audioTrackIndex.initSegment.offset,
19
+ size: this.audioTrackIndex.initSegment.size
20
+ };
21
+ if (this.videoTrackIndex !== void 0) paths.video = {
22
+ path: `${this.apiHost}/api/v1/isobmff_tracks/${this.assetId}/${this.videoTrackIndex.track}`,
23
+ pos: this.videoTrackIndex.initSegment.offset,
24
+ size: this.videoTrackIndex.initSegment.size
25
+ };
26
+ return paths;
27
+ }
28
+ get templates() {
29
+ return {
30
+ initSegment: `${this.apiHost}/api/v1/isobmff_tracks/${this.assetId}/{trackId}`,
31
+ mediaSegment: `${this.apiHost}/api/v1/isobmff_tracks/${this.assetId}/{trackId}`
32
+ };
33
+ }
34
+ buildInitSegmentUrl(trackId) {
35
+ return `${this.apiHost}/api/v1/isobmff_tracks/${this.assetId}/${trackId}`;
36
+ }
37
+ buildMediaSegmentUrl(trackId, _segmentId) {
38
+ return `${this.apiHost}/api/v1/isobmff_tracks/${this.assetId}/${trackId}`;
39
+ }
40
+ };
41
+ export { AssetIdMediaEngine };
@@ -0,0 +1,45 @@
1
+ import { TrackFragmentIndex } from '../../../../assets/src/index.ts';
2
+ import { AudioRendition, InitSegmentPaths, MediaEngine, SegmentTimeRange } from '../../transcoding/types';
3
+ import { UrlGenerator } from '../../transcoding/utils/UrlGenerator';
4
+ import { EFMedia } from '../EFMedia';
5
+ import { BaseMediaEngine } from './BaseMediaEngine';
6
+ import { MediaRendition } from './shared/MediaTaskUtils';
7
+ export declare class AssetMediaEngine extends BaseMediaEngine implements MediaEngine {
8
+ host: EFMedia;
9
+ src: string;
10
+ protected data: Record<number, TrackFragmentIndex>;
11
+ static fetch(host: EFMedia, urlGenerator: UrlGenerator, src: string): Promise<AssetMediaEngine>;
12
+ durationMs: number;
13
+ constructor(host: EFMedia, src: string, data: Record<number, TrackFragmentIndex>);
14
+ get audioTrackIndex(): import('../../../../assets/src/index.ts').AudioTrackFragmentIndex | undefined;
15
+ get videoTrackIndex(): import('../../../../assets/src/index.ts').VideoTrackFragmentIndex | undefined;
16
+ get videoRendition(): {
17
+ trackId: number | undefined;
18
+ src: string;
19
+ startTimeOffsetMs: number | undefined;
20
+ };
21
+ get audioRendition(): {
22
+ trackId: number | undefined;
23
+ src: string;
24
+ };
25
+ get initSegmentPaths(): InitSegmentPaths;
26
+ get templates(): {
27
+ initSegment: string;
28
+ mediaSegment: string;
29
+ };
30
+ buildInitSegmentUrl(trackId: number): string;
31
+ buildMediaSegmentUrl(trackId: number, segmentId: number): string;
32
+ fetchInitSegment(rendition: {
33
+ trackId: number | undefined;
34
+ src: string;
35
+ }, signal: AbortSignal): Promise<ArrayBuffer>;
36
+ fetchMediaSegmentImpl(segmentId: number, rendition: {
37
+ trackId: number | undefined;
38
+ src: string;
39
+ }, signal?: AbortSignal): Promise<ArrayBuffer>;
40
+ /**
41
+ * Calculate audio segments for variable-duration segments using track fragment index
42
+ */
43
+ calculateAudioSegmentRange(fromMs: number, toMs: number, rendition: AudioRendition, _durationMs: number): SegmentTimeRange[];
44
+ computeSegmentId(desiredSeekTimeMs: number, rendition: MediaRendition): number;
45
+ }
@@ -0,0 +1,135 @@
1
+ import { BaseMediaEngine } from "./BaseMediaEngine.js";
2
+ import { convertToScaledTime, roundToMilliseconds } from "./shared/PrecisionUtils.js";
3
+ var AssetMediaEngine = class AssetMediaEngine extends BaseMediaEngine {
4
+ static async fetch(host, urlGenerator, src) {
5
+ const url = urlGenerator.generateTrackFragmentIndexUrl(src);
6
+ const response = await host.fetch(url);
7
+ const data = await response.json();
8
+ if (src.startsWith("/")) src = src.slice(1);
9
+ return new AssetMediaEngine(host, src, data);
10
+ }
11
+ constructor(host, src, data) {
12
+ super();
13
+ this.host = host;
14
+ this.src = src;
15
+ this.data = data;
16
+ const longestFragment = Object.values(data).reduce((max, fragment) => Math.max(max, fragment.duration / fragment.timescale), 0);
17
+ this.durationMs = longestFragment * 1e3;
18
+ }
19
+ get audioTrackIndex() {
20
+ return Object.values(this.data).find((track) => track.type === "audio");
21
+ }
22
+ get videoTrackIndex() {
23
+ return Object.values(this.data).find((track) => track.type === "video");
24
+ }
25
+ get videoRendition() {
26
+ return {
27
+ trackId: this.videoTrackIndex?.track,
28
+ src: this.src,
29
+ startTimeOffsetMs: this.videoTrackIndex?.startTimeOffsetMs
30
+ };
31
+ }
32
+ get audioRendition() {
33
+ return {
34
+ trackId: this.audioTrackIndex?.track,
35
+ src: this.src
36
+ };
37
+ }
38
+ get initSegmentPaths() {
39
+ const paths = {};
40
+ if (this.audioTrackIndex !== void 0) paths.audio = {
41
+ path: `@ef-track/${this.audioTrackIndex.track}.m4s`,
42
+ pos: this.audioTrackIndex.initSegment.offset,
43
+ size: this.audioTrackIndex.initSegment.size
44
+ };
45
+ if (this.videoTrackIndex !== void 0) paths.video = {
46
+ path: `/@ef-track/${this.videoTrackIndex.track}.m4s`,
47
+ pos: this.videoTrackIndex.initSegment.offset,
48
+ size: this.videoTrackIndex.initSegment.size
49
+ };
50
+ return paths;
51
+ }
52
+ get templates() {
53
+ return {
54
+ initSegment: "/@ef-track/{src}?trackId={trackId}",
55
+ mediaSegment: "/@ef-track/{src}?trackId={trackId}"
56
+ };
57
+ }
58
+ buildInitSegmentUrl(trackId) {
59
+ return `/@ef-track/${this.src}?trackId=${trackId}`;
60
+ }
61
+ buildMediaSegmentUrl(trackId, segmentId) {
62
+ return `/@ef-track/${this.src}?trackId=${trackId}&segmentId=${segmentId}`;
63
+ }
64
+ async fetchInitSegment(rendition, signal) {
65
+ if (!rendition.trackId) throw new Error("Track ID is required for asset metadata");
66
+ const url = this.buildInitSegmentUrl(rendition.trackId);
67
+ const initSegment = this.data[rendition.trackId]?.initSegment;
68
+ if (!initSegment) throw new Error("Init segment not found");
69
+ const headers = { Range: `bytes=${initSegment.offset}-${initSegment.offset + initSegment.size - 1}` };
70
+ return this.fetchMediaCacheWithHeaders(url, headers, signal);
71
+ }
72
+ async fetchMediaSegmentImpl(segmentId, rendition, signal) {
73
+ if (!rendition.trackId) throw new Error("Track ID is required for asset metadata");
74
+ if (segmentId === void 0) throw new Error("Segment ID is not available");
75
+ const url = this.buildMediaSegmentUrl(rendition.trackId, segmentId);
76
+ const mediaSegment = this.data[rendition.trackId]?.segments[segmentId];
77
+ if (!mediaSegment) throw new Error("Media segment not found");
78
+ const headers = { Range: `bytes=${mediaSegment.offset}-${mediaSegment.offset + mediaSegment.size - 1}` };
79
+ return this.fetchMediaCacheWithHeaders(url, headers, signal);
80
+ }
81
+ /**
82
+ * Calculate audio segments for variable-duration segments using track fragment index
83
+ */
84
+ calculateAudioSegmentRange(fromMs, toMs, rendition, _durationMs) {
85
+ if (fromMs >= toMs || !rendition.trackId) return [];
86
+ const track = this.data[rendition.trackId];
87
+ if (!track) return [];
88
+ const { timescale, segments } = track;
89
+ const segmentRanges = [];
90
+ for (let i = 0; i < segments.length; i++) {
91
+ const segment = segments[i];
92
+ const segmentStartTime = segment.cts;
93
+ const segmentEndTime = segment.cts + segment.duration;
94
+ const segmentStartMs = segmentStartTime / timescale * 1e3;
95
+ const segmentEndMs = segmentEndTime / timescale * 1e3;
96
+ if (segmentStartMs < toMs && segmentEndMs > fromMs) segmentRanges.push({
97
+ segmentId: i,
98
+ startMs: segmentStartMs,
99
+ endMs: segmentEndMs
100
+ });
101
+ }
102
+ return segmentRanges;
103
+ }
104
+ computeSegmentId(desiredSeekTimeMs, rendition) {
105
+ if (!rendition.trackId) throw new Error("Track ID is required for asset metadata");
106
+ const track = this.data[rendition.trackId];
107
+ if (!track) throw new Error("Track not found");
108
+ const { timescale, segments } = track;
109
+ const startTimeOffsetMs = "startTimeOffsetMs" in rendition && rendition.startTimeOffsetMs || 0;
110
+ const mediaTimeMs = roundToMilliseconds(desiredSeekTimeMs + startTimeOffsetMs);
111
+ const scaledSeekTime = convertToScaledTime(mediaTimeMs, timescale);
112
+ for (let i = segments.length - 1; i >= 0; i--) {
113
+ const segment = segments[i];
114
+ const segmentEndTime = segment.cts + segment.duration;
115
+ if (segment.cts <= scaledSeekTime && scaledSeekTime < segmentEndTime) return i;
116
+ }
117
+ let nearestSegmentIndex = 0;
118
+ let nearestDistance = Number.MAX_SAFE_INTEGER;
119
+ for (let i = 0; i < segments.length; i++) {
120
+ const segment = segments[i];
121
+ const segmentStartTime = segment.cts;
122
+ const segmentEndTime = segment.cts + segment.duration;
123
+ let distance;
124
+ if (scaledSeekTime < segmentStartTime) distance = segmentStartTime - scaledSeekTime;
125
+ else if (scaledSeekTime >= segmentEndTime) distance = scaledSeekTime - segmentEndTime;
126
+ else return i;
127
+ if (distance < nearestDistance) {
128
+ nearestDistance = distance;
129
+ nearestSegmentIndex = i;
130
+ }
131
+ }
132
+ return nearestSegmentIndex;
133
+ }
134
+ };
135
+ export { AssetMediaEngine };
@@ -0,0 +1,55 @@
1
+ import { AudioRendition, SegmentTimeRange, VideoRendition } from '../../transcoding/types';
2
+ import { EFMedia } from '../EFMedia.js';
3
+ export declare abstract class BaseMediaEngine {
4
+ private requestDeduplicator;
5
+ abstract get videoRendition(): VideoRendition | undefined;
6
+ abstract get audioRendition(): AudioRendition | undefined;
7
+ abstract get host(): EFMedia;
8
+ getVideoRendition(): VideoRendition;
9
+ getAudioRendition(): AudioRendition;
10
+ /**
11
+ * Generate cache key for segment requests
12
+ */
13
+ private getSegmentCacheKey;
14
+ /**
15
+ * Abstract method for actual segment fetching - implemented by subclasses
16
+ */
17
+ abstract fetchMediaSegmentImpl(segmentId: number, rendition: {
18
+ trackId: number | undefined;
19
+ src: string;
20
+ }): Promise<ArrayBuffer>;
21
+ /**
22
+ * Fetch media segment with built-in deduplication
23
+ * Eliminates the need for separate coordinators - cleaner architecture
24
+ */
25
+ fetchMediaSegment(segmentId: number, rendition: {
26
+ trackId: number | undefined;
27
+ src: string;
28
+ }, _signal?: AbortSignal): Promise<ArrayBuffer>;
29
+ /**
30
+ * Check if a segment is currently being fetched
31
+ */
32
+ isSegmentBeingFetched(segmentId: number, rendition: {
33
+ src: string;
34
+ trackId: number | undefined;
35
+ }): boolean;
36
+ /**
37
+ * Get count of active segment requests (for debugging/monitoring)
38
+ */
39
+ getActiveSegmentRequestCount(): number;
40
+ /**
41
+ * Cancel all active segment requests (for cleanup)
42
+ */
43
+ cancelAllSegmentRequests(): void;
44
+ fetchMediaCache(mediaUrl: string): Promise<ArrayBuffer>;
45
+ /**
46
+ * Enhanced caching method that supports custom headers (e.g., Range requests)
47
+ * Cache key includes both URL and headers for proper cache isolation
48
+ */
49
+ fetchMediaCacheWithHeaders(mediaUrl: string, headers?: Record<string, string>, signal?: AbortSignal): Promise<ArrayBuffer>;
50
+ /**
51
+ * Calculate audio segments needed for a time range
52
+ * Each media engine implements this based on their segment structure
53
+ */
54
+ calculateAudioSegmentRange(fromMs: number, toMs: number, rendition: AudioRendition, durationMs: number): SegmentTimeRange[];
55
+ }
@@ -0,0 +1,115 @@
1
+ import { RequestDeduplicator } from "../../transcoding/cache/RequestDeduplicator.js";
2
+ import { SizeAwareLRUCache } from "../../utils/LRUCache.js";
3
+ const mediaCache = new SizeAwareLRUCache(100 * 1024 * 1024);
4
+ var BaseMediaEngine = class {
5
+ constructor() {
6
+ this.requestDeduplicator = new RequestDeduplicator();
7
+ }
8
+ getVideoRendition() {
9
+ if (!this.videoRendition) throw new Error("No video rendition available");
10
+ return this.videoRendition;
11
+ }
12
+ getAudioRendition() {
13
+ if (!this.audioRendition) throw new Error("No audio rendition available");
14
+ return this.audioRendition;
15
+ }
16
+ /**
17
+ * Generate cache key for segment requests
18
+ */
19
+ getSegmentCacheKey(segmentId, rendition) {
20
+ return `${rendition.src}-${rendition.id}-${segmentId}-${rendition.trackId}`;
21
+ }
22
+ /**
23
+ * Fetch media segment with built-in deduplication
24
+ * Eliminates the need for separate coordinators - cleaner architecture
25
+ */
26
+ async fetchMediaSegment(segmentId, rendition, _signal) {
27
+ const cacheKey = this.getSegmentCacheKey(segmentId, rendition);
28
+ return this.requestDeduplicator.executeRequest(cacheKey, async () => {
29
+ return this.fetchMediaSegmentImpl(segmentId, rendition);
30
+ });
31
+ }
32
+ /**
33
+ * Check if a segment is currently being fetched
34
+ */
35
+ isSegmentBeingFetched(segmentId, rendition) {
36
+ const cacheKey = this.getSegmentCacheKey(segmentId, rendition);
37
+ return this.requestDeduplicator.isPending(cacheKey);
38
+ }
39
+ /**
40
+ * Get count of active segment requests (for debugging/monitoring)
41
+ */
42
+ getActiveSegmentRequestCount() {
43
+ return this.requestDeduplicator.getPendingCount();
44
+ }
45
+ /**
46
+ * Cancel all active segment requests (for cleanup)
47
+ */
48
+ cancelAllSegmentRequests() {
49
+ this.requestDeduplicator.clear();
50
+ }
51
+ async fetchMediaCache(mediaUrl) {
52
+ const cached = mediaCache.get(mediaUrl);
53
+ if (cached) return cached;
54
+ const promise = this.host.fetch(mediaUrl).then((response) => response.arrayBuffer());
55
+ mediaCache.set(mediaUrl, promise);
56
+ return promise;
57
+ }
58
+ /**
59
+ * Enhanced caching method that supports custom headers (e.g., Range requests)
60
+ * Cache key includes both URL and headers for proper cache isolation
61
+ */
62
+ async fetchMediaCacheWithHeaders(mediaUrl, headers, signal) {
63
+ const cacheKey = headers ? `${mediaUrl}:${JSON.stringify(headers)}` : mediaUrl;
64
+ const cached = mediaCache.get(cacheKey);
65
+ if (cached) return cached;
66
+ const promise = this.host.fetch(mediaUrl, {
67
+ headers,
68
+ signal
69
+ }).then((response) => response.arrayBuffer());
70
+ mediaCache.set(cacheKey, promise);
71
+ return promise;
72
+ }
73
+ /**
74
+ * Calculate audio segments needed for a time range
75
+ * Each media engine implements this based on their segment structure
76
+ */
77
+ calculateAudioSegmentRange(fromMs, toMs, rendition, durationMs) {
78
+ if (fromMs >= toMs) return [];
79
+ const segments = [];
80
+ if (rendition.segmentDurationsMs && rendition.segmentDurationsMs.length > 0) {
81
+ let cumulativeTime = 0;
82
+ for (let i = 0; i < rendition.segmentDurationsMs.length; i++) {
83
+ const segmentDuration = rendition.segmentDurationsMs[i];
84
+ if (segmentDuration === void 0) continue;
85
+ const segmentStartMs = cumulativeTime;
86
+ const segmentEndMs = Math.min(cumulativeTime + segmentDuration, durationMs);
87
+ if (segmentStartMs >= durationMs) break;
88
+ if (segmentStartMs < toMs && segmentEndMs > fromMs) segments.push({
89
+ segmentId: i + 1,
90
+ startMs: segmentStartMs,
91
+ endMs: segmentEndMs
92
+ });
93
+ cumulativeTime += segmentDuration;
94
+ if (cumulativeTime >= durationMs) break;
95
+ }
96
+ return segments;
97
+ }
98
+ const segmentDurationMs = rendition.segmentDurationMs || 1e3;
99
+ const startSegmentIndex = Math.floor(fromMs / segmentDurationMs);
100
+ const endSegmentIndex = Math.floor(toMs / segmentDurationMs);
101
+ for (let i = startSegmentIndex; i <= endSegmentIndex; i++) {
102
+ const segmentId = i + 1;
103
+ const segmentStartMs = i * segmentDurationMs;
104
+ const segmentEndMs = Math.min((i + 1) * segmentDurationMs, durationMs);
105
+ if (segmentStartMs >= durationMs) break;
106
+ if (segmentStartMs < toMs && segmentEndMs > fromMs) segments.push({
107
+ segmentId,
108
+ startMs: segmentStartMs,
109
+ endMs: segmentEndMs
110
+ });
111
+ }
112
+ return segments;
113
+ }
114
+ };
115
+ export { BaseMediaEngine };
@@ -0,0 +1,43 @@
1
+ import { MediaSample } from '../SampleBuffer';
2
+ interface BufferedSeekingInputOptions {
3
+ videoBufferSize?: number;
4
+ audioBufferSize?: number;
5
+ /**
6
+ * Timeline offset in milliseconds to map user timeline to media timeline.
7
+ * Applied during seeking to handle media that doesn't start at 0ms.
8
+ */
9
+ startTimeOffsetMs?: number;
10
+ }
11
+ export declare class NoSample extends RangeError {
12
+ }
13
+ export declare class BufferedSeekingInput {
14
+ private input;
15
+ private trackIterators;
16
+ private trackBuffers;
17
+ private options;
18
+ private trackIteratorCreationPromises;
19
+ private trackSeekPromises;
20
+ /**
21
+ * Timeline offset in milliseconds to map user timeline to media timeline.
22
+ * Applied during seeking to handle media that doesn't start at 0ms.
23
+ */
24
+ private readonly startTimeOffsetMs;
25
+ constructor(arrayBuffer: ArrayBuffer, options?: BufferedSeekingInputOptions);
26
+ getBufferSize(trackId: number): number;
27
+ getBufferContents(trackId: number): readonly MediaSample[];
28
+ getBufferTimestamps(trackId: number): number[];
29
+ clearBuffer(trackId: number): void;
30
+ computeDuration(): Promise<number>;
31
+ getTrack(trackId: number): Promise<import('mediabunny').InputTrack>;
32
+ getAudioTrack(trackId: number): Promise<import('mediabunny').InputAudioTrack>;
33
+ getVideoTrack(trackId: number): Promise<import('mediabunny').InputVideoTrack>;
34
+ getFirstVideoTrack(): Promise<import('mediabunny').InputVideoTrack | undefined>;
35
+ getFirstAudioTrack(): Promise<import('mediabunny').InputAudioTrack | undefined>;
36
+ getTrackIterator(trackId: number): Promise<AsyncIterator<MediaSample, any, undefined>>;
37
+ private createIteratorSafe;
38
+ createTrackBuffer(trackId: number): Promise<void>;
39
+ seek(trackId: number, timeMs: number): Promise<MediaSample | undefined>;
40
+ private resetIterator;
41
+ private seekSafe;
42
+ }
43
+ export {};