@editframe/elements 0.24.1-beta.0 → 0.25.0-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 (335) hide show
  1. package/dist/DelayedLoadingState.js +31 -0
  2. package/dist/DelayedLoadingState.js.map +1 -0
  3. package/dist/EF_FRAMEGEN.d.ts +50 -46
  4. package/dist/EF_FRAMEGEN.js +5 -1
  5. package/dist/EF_FRAMEGEN.js.map +1 -0
  6. package/dist/EF_INTERACTIVE.js +4 -0
  7. package/dist/EF_INTERACTIVE.js.map +1 -0
  8. package/dist/EF_RENDERING.js +4 -0
  9. package/dist/EF_RENDERING.js.map +1 -0
  10. package/dist/_virtual/_@oxc-project_runtime@0.94.0/helpers/decorate.js +4 -1
  11. package/dist/attachContextRoot.js +6 -1
  12. package/dist/attachContextRoot.js.map +1 -0
  13. package/dist/elements/CrossUpdateController.js +4 -0
  14. package/dist/elements/CrossUpdateController.js.map +1 -0
  15. package/dist/elements/EFAudio.d.ts +24 -16
  16. package/dist/elements/EFAudio.js +10 -1
  17. package/dist/elements/EFAudio.js.map +1 -0
  18. package/dist/elements/EFCaptions.d.ts +118 -109
  19. package/dist/elements/EFCaptions.js +11 -6
  20. package/dist/elements/EFCaptions.js.map +1 -0
  21. package/dist/elements/EFImage.d.ts +31 -20
  22. package/dist/elements/EFImage.js +6 -1
  23. package/dist/elements/EFImage.js.map +1 -0
  24. package/dist/elements/EFMedia/AssetIdMediaEngine.js +5 -0
  25. package/dist/elements/EFMedia/AssetIdMediaEngine.js.map +1 -0
  26. package/dist/elements/EFMedia/AssetMediaEngine.js +12 -0
  27. package/dist/elements/EFMedia/AssetMediaEngine.js.map +1 -0
  28. package/dist/elements/EFMedia/BaseMediaEngine.js +53 -0
  29. package/dist/elements/EFMedia/BaseMediaEngine.js.map +1 -0
  30. package/dist/elements/EFMedia/BufferedSeekingInput.d.ts +47 -46
  31. package/dist/elements/EFMedia/BufferedSeekingInput.js +6 -1
  32. package/dist/elements/EFMedia/BufferedSeekingInput.js.map +1 -0
  33. package/dist/elements/EFMedia/JitMediaEngine.js +12 -0
  34. package/dist/elements/EFMedia/JitMediaEngine.js.map +1 -0
  35. package/dist/elements/EFMedia/audioTasks/makeAudioBufferTask.d.ts +9 -13
  36. package/dist/elements/EFMedia/audioTasks/makeAudioBufferTask.js +5 -0
  37. package/dist/elements/EFMedia/audioTasks/makeAudioBufferTask.js.map +1 -0
  38. package/dist/elements/EFMedia/audioTasks/makeAudioFrequencyAnalysisTask.js +6 -1
  39. package/dist/elements/EFMedia/audioTasks/makeAudioFrequencyAnalysisTask.js.map +1 -0
  40. package/dist/elements/EFMedia/audioTasks/makeAudioInitSegmentFetchTask.js +5 -0
  41. package/dist/elements/EFMedia/audioTasks/makeAudioInitSegmentFetchTask.js.map +1 -0
  42. package/dist/elements/EFMedia/audioTasks/makeAudioInputTask.js +5 -0
  43. package/dist/elements/EFMedia/audioTasks/makeAudioInputTask.js.map +1 -0
  44. package/dist/elements/EFMedia/audioTasks/makeAudioSeekTask.js +5 -0
  45. package/dist/elements/EFMedia/audioTasks/makeAudioSeekTask.js.map +1 -0
  46. package/dist/elements/EFMedia/audioTasks/makeAudioSegmentFetchTask.js +5 -0
  47. package/dist/elements/EFMedia/audioTasks/makeAudioSegmentFetchTask.js.map +1 -0
  48. package/dist/elements/EFMedia/audioTasks/makeAudioSegmentIdTask.js +5 -0
  49. package/dist/elements/EFMedia/audioTasks/makeAudioSegmentIdTask.js.map +1 -0
  50. package/dist/elements/EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.js +6 -1
  51. package/dist/elements/EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.js.map +1 -0
  52. package/dist/elements/EFMedia/shared/AudioSpanUtils.js +18 -2
  53. package/dist/elements/EFMedia/shared/AudioSpanUtils.js.map +1 -0
  54. package/dist/elements/EFMedia/shared/BufferUtils.d.ts +9 -67
  55. package/dist/elements/EFMedia/shared/BufferUtils.js +15 -0
  56. package/dist/elements/EFMedia/shared/BufferUtils.js.map +1 -0
  57. package/dist/elements/EFMedia/shared/GlobalInputCache.js +29 -0
  58. package/dist/elements/EFMedia/shared/GlobalInputCache.js.map +1 -0
  59. package/dist/elements/EFMedia/shared/MediaTaskUtils.d.ts +11 -17
  60. package/dist/elements/EFMedia/shared/PrecisionUtils.js +25 -0
  61. package/dist/elements/EFMedia/shared/PrecisionUtils.js.map +1 -0
  62. package/dist/elements/EFMedia/shared/ThumbnailExtractor.js +22 -0
  63. package/dist/elements/EFMedia/shared/ThumbnailExtractor.js.map +1 -0
  64. package/dist/elements/EFMedia/tasks/makeMediaEngineTask.js +13 -0
  65. package/dist/elements/EFMedia/tasks/makeMediaEngineTask.js.map +1 -0
  66. package/dist/elements/EFMedia/videoTasks/MainVideoInputCache.js +21 -0
  67. package/dist/elements/EFMedia/videoTasks/MainVideoInputCache.js.map +1 -0
  68. package/dist/elements/EFMedia/videoTasks/ScrubInputCache.js +18 -0
  69. package/dist/elements/EFMedia/videoTasks/ScrubInputCache.js.map +1 -0
  70. package/dist/elements/EFMedia/videoTasks/makeScrubVideoBufferTask.js +10 -0
  71. package/dist/elements/EFMedia/videoTasks/makeScrubVideoBufferTask.js.map +1 -0
  72. package/dist/elements/EFMedia/videoTasks/makeScrubVideoInitSegmentFetchTask.js +5 -0
  73. package/dist/elements/EFMedia/videoTasks/makeScrubVideoInitSegmentFetchTask.js.map +1 -0
  74. package/dist/elements/EFMedia/videoTasks/makeScrubVideoInputTask.js +5 -0
  75. package/dist/elements/EFMedia/videoTasks/makeScrubVideoInputTask.js.map +1 -0
  76. package/dist/elements/EFMedia/videoTasks/makeScrubVideoSeekTask.js +6 -1
  77. package/dist/elements/EFMedia/videoTasks/makeScrubVideoSeekTask.js.map +1 -0
  78. package/dist/elements/EFMedia/videoTasks/makeScrubVideoSegmentFetchTask.js +5 -0
  79. package/dist/elements/EFMedia/videoTasks/makeScrubVideoSegmentFetchTask.js.map +1 -0
  80. package/dist/elements/EFMedia/videoTasks/makeScrubVideoSegmentIdTask.js +5 -0
  81. package/dist/elements/EFMedia/videoTasks/makeScrubVideoSegmentIdTask.js.map +1 -0
  82. package/dist/elements/EFMedia/videoTasks/makeUnifiedVideoSeekTask.js +16 -2
  83. package/dist/elements/EFMedia/videoTasks/makeUnifiedVideoSeekTask.js.map +1 -0
  84. package/dist/elements/EFMedia/videoTasks/makeVideoBufferTask.d.ts +9 -13
  85. package/dist/elements/EFMedia/videoTasks/makeVideoBufferTask.js +5 -0
  86. package/dist/elements/EFMedia/videoTasks/makeVideoBufferTask.js.map +1 -0
  87. package/dist/elements/EFMedia.d.ts +115 -104
  88. package/dist/elements/EFMedia.js +25 -1
  89. package/dist/elements/EFMedia.js.map +1 -0
  90. package/dist/elements/EFSourceMixin.d.ts +10 -11
  91. package/dist/elements/EFSourceMixin.js +5 -0
  92. package/dist/elements/EFSourceMixin.js.map +1 -0
  93. package/dist/elements/EFSurface.d.ts +35 -27
  94. package/dist/elements/EFSurface.js +6 -1
  95. package/dist/elements/EFSurface.js.map +1 -0
  96. package/dist/elements/EFTemporal.d.ts +200 -213
  97. package/dist/elements/EFTemporal.js +24 -4
  98. package/dist/elements/EFTemporal.js.map +1 -0
  99. package/dist/elements/EFThumbnailStrip.d.ts +91 -83
  100. package/dist/elements/EFThumbnailStrip.js +49 -4
  101. package/dist/elements/EFThumbnailStrip.js.map +1 -0
  102. package/dist/elements/EFTimegroup.d.ts +107 -101
  103. package/dist/elements/EFTimegroup.js +58 -3
  104. package/dist/elements/EFTimegroup.js.map +1 -0
  105. package/dist/elements/EFVideo.d.ts +120 -108
  106. package/dist/elements/EFVideo.js +46 -2
  107. package/dist/elements/EFVideo.js.map +1 -0
  108. package/dist/elements/EFWaveform.d.ts +48 -41
  109. package/dist/elements/EFWaveform.js +6 -1
  110. package/dist/elements/EFWaveform.js.map +1 -0
  111. package/dist/elements/FetchMixin.d.ts +8 -6
  112. package/dist/elements/FetchMixin.js +4 -0
  113. package/dist/elements/FetchMixin.js.map +1 -0
  114. package/dist/elements/SampleBuffer.d.ts +18 -13
  115. package/dist/elements/SampleBuffer.js +5 -0
  116. package/dist/elements/SampleBuffer.js.map +1 -0
  117. package/dist/elements/TargetController.d.ts +23 -24
  118. package/dist/elements/TargetController.js +8 -3
  119. package/dist/elements/TargetController.js.map +1 -0
  120. package/dist/elements/TimegroupController.d.ts +17 -12
  121. package/dist/elements/TimegroupController.js +4 -0
  122. package/dist/elements/TimegroupController.js.map +1 -0
  123. package/dist/elements/durationConverter.js +9 -4
  124. package/dist/elements/durationConverter.js.map +1 -0
  125. package/dist/elements/parseTimeToMs.js +4 -0
  126. package/dist/elements/parseTimeToMs.js.map +1 -0
  127. package/dist/elements/renderTemporalAudio.js +4 -0
  128. package/dist/elements/renderTemporalAudio.js.map +1 -0
  129. package/dist/elements/updateAnimations.js +29 -8
  130. package/dist/elements/updateAnimations.js.map +1 -0
  131. package/dist/elements-ZhsB7B5N.css +9 -0
  132. package/dist/elements-ZhsB7B5N.css.map +1 -0
  133. package/dist/getRenderInfo.d.ts +53 -47
  134. package/dist/getRenderInfo.js +5 -0
  135. package/dist/getRenderInfo.js.map +1 -0
  136. package/dist/gui/ContextMixin.d.ts +19 -20
  137. package/dist/gui/ContextMixin.js +32 -1
  138. package/dist/gui/ContextMixin.js.map +1 -0
  139. package/dist/gui/Controllable.d.ts +13 -14
  140. package/dist/gui/Controllable.js +5 -0
  141. package/dist/gui/Controllable.js.map +1 -0
  142. package/dist/gui/EFConfiguration.d.ts +18 -14
  143. package/dist/gui/EFConfiguration.js +6 -1
  144. package/dist/gui/EFConfiguration.js.map +1 -0
  145. package/dist/gui/EFControls.d.ts +35 -31
  146. package/dist/gui/EFControls.js +8 -3
  147. package/dist/gui/EFControls.js.map +1 -0
  148. package/dist/gui/EFDial.d.ts +23 -16
  149. package/dist/gui/EFDial.js +6 -1
  150. package/dist/gui/EFDial.js.map +1 -0
  151. package/dist/gui/EFFilmstrip.d.ts +183 -177
  152. package/dist/gui/EFFilmstrip.js +30 -25
  153. package/dist/gui/EFFilmstrip.js.map +1 -0
  154. package/dist/gui/EFFitScale.d.ts +30 -24
  155. package/dist/gui/EFFitScale.js +6 -1
  156. package/dist/gui/EFFitScale.js.map +1 -0
  157. package/dist/gui/EFFocusOverlay.d.ts +22 -14
  158. package/dist/gui/EFFocusOverlay.js +6 -1
  159. package/dist/gui/EFFocusOverlay.js.map +1 -0
  160. package/dist/gui/EFPause.d.ts +24 -18
  161. package/dist/gui/EFPause.js +6 -1
  162. package/dist/gui/EFPause.js.map +1 -0
  163. package/dist/gui/EFPlay.d.ts +24 -18
  164. package/dist/gui/EFPlay.js +6 -1
  165. package/dist/gui/EFPlay.js.map +1 -0
  166. package/dist/gui/EFPreview.d.ts +22 -15
  167. package/dist/gui/EFPreview.js +9 -1
  168. package/dist/gui/EFPreview.js.map +1 -0
  169. package/dist/gui/EFResizableBox.d.ts +39 -32
  170. package/dist/gui/EFResizableBox.js +8 -3
  171. package/dist/gui/EFResizableBox.js.map +1 -0
  172. package/dist/gui/EFScrubber.d.ts +31 -25
  173. package/dist/gui/EFScrubber.js +6 -1
  174. package/dist/gui/EFScrubber.js.map +1 -0
  175. package/dist/gui/EFTimeDisplay.d.ts +21 -14
  176. package/dist/gui/EFTimeDisplay.js +6 -1
  177. package/dist/gui/EFTimeDisplay.js.map +1 -0
  178. package/dist/gui/EFToggleLoop.d.ts +19 -13
  179. package/dist/gui/EFToggleLoop.js +6 -1
  180. package/dist/gui/EFToggleLoop.js.map +1 -0
  181. package/dist/gui/EFTogglePlay.d.ts +23 -17
  182. package/dist/gui/EFTogglePlay.js +6 -1
  183. package/dist/gui/EFTogglePlay.js.map +1 -0
  184. package/dist/gui/EFWorkbench.d.ts +24 -16
  185. package/dist/gui/EFWorkbench.js +6 -1
  186. package/dist/gui/EFWorkbench.js.map +1 -0
  187. package/dist/gui/PlaybackController.d.ts +54 -50
  188. package/dist/gui/PlaybackController.js +18 -0
  189. package/dist/gui/PlaybackController.js.map +1 -0
  190. package/dist/gui/TWMixin.js +5 -1
  191. package/dist/gui/TWMixin.js.map +1 -0
  192. package/dist/gui/TWMixin2.js +6 -1
  193. package/dist/gui/TWMixin2.js.map +1 -0
  194. package/dist/gui/TargetOrContextMixin.js +5 -0
  195. package/dist/gui/TargetOrContextMixin.js.map +1 -0
  196. package/dist/gui/currentTimeContext.js +5 -0
  197. package/dist/gui/currentTimeContext.js.map +1 -0
  198. package/dist/gui/durationContext.js +5 -0
  199. package/dist/gui/durationContext.js.map +1 -0
  200. package/dist/gui/efContext.js +5 -0
  201. package/dist/gui/efContext.js.map +1 -0
  202. package/dist/gui/fetchContext.js +5 -0
  203. package/dist/gui/fetchContext.js.map +1 -0
  204. package/dist/gui/focusContext.d.ts +6 -5
  205. package/dist/gui/focusContext.js +5 -0
  206. package/dist/gui/focusContext.js.map +1 -0
  207. package/dist/gui/focusedElementContext.js +5 -0
  208. package/dist/gui/focusedElementContext.js.map +1 -0
  209. package/dist/gui/playingContext.js +5 -0
  210. package/dist/gui/playingContext.js.map +1 -0
  211. package/dist/index.d.ts +27 -26
  212. package/dist/index.js +6 -1
  213. package/dist/index.js.map +1 -0
  214. package/dist/msToTimeCode.js +4 -0
  215. package/dist/msToTimeCode.js.map +1 -0
  216. package/dist/otel/BridgeSpanExporter.js +5 -0
  217. package/dist/otel/BridgeSpanExporter.js.map +1 -0
  218. package/dist/otel/setupBrowserTracing.js +7 -2
  219. package/dist/otel/setupBrowserTracing.js.map +1 -0
  220. package/dist/otel/tracingHelpers.d.ts +7 -34
  221. package/dist/otel/tracingHelpers.js +34 -2
  222. package/dist/otel/tracingHelpers.js.map +1 -0
  223. package/dist/transcoding/cache/RequestDeduplicator.js +25 -0
  224. package/dist/transcoding/cache/RequestDeduplicator.js.map +1 -0
  225. package/dist/transcoding/cache/URLTokenDeduplicator.js +23 -0
  226. package/dist/transcoding/cache/URLTokenDeduplicator.js.map +1 -0
  227. package/dist/transcoding/types/index.d.ts +96 -270
  228. package/dist/transcoding/utils/UrlGenerator.d.ts +30 -25
  229. package/dist/transcoding/utils/UrlGenerator.js +19 -0
  230. package/dist/transcoding/utils/UrlGenerator.js.map +1 -0
  231. package/dist/utils/LRUCache.js +44 -0
  232. package/dist/utils/LRUCache.js.map +1 -0
  233. package/package.json +11 -24
  234. package/tsdown.config.ts +36 -0
  235. package/dist/DelayedLoadingState.d.ts +0 -48
  236. package/dist/DelayedLoadingState.integration.test.d.ts +0 -1
  237. package/dist/DelayedLoadingState.test.d.ts +0 -1
  238. package/dist/EF_INTERACTIVE.d.ts +0 -1
  239. package/dist/EF_RENDERING.d.ts +0 -1
  240. package/dist/LoadingDebounce.test.d.ts +0 -1
  241. package/dist/ManualScrubTest.test.d.ts +0 -1
  242. package/dist/ScrubResolvedFlashing.test.d.ts +0 -1
  243. package/dist/ScrubTrackManager.test.d.ts +0 -1
  244. package/dist/VideoSeekFlashing.browsertest.d.ts +0 -0
  245. package/dist/VideoStuckDiagnostic.test.d.ts +0 -1
  246. package/dist/attachContextRoot.d.ts +0 -1
  247. package/dist/elements/ContextProxiesController.d.ts +0 -39
  248. package/dist/elements/CrossUpdateController.d.ts +0 -8
  249. package/dist/elements/EFAudio.browsertest.d.ts +0 -0
  250. package/dist/elements/EFCaptions.browsertest.d.ts +0 -0
  251. package/dist/elements/EFImage.browsertest.d.ts +0 -0
  252. package/dist/elements/EFMedia/AssetIdMediaEngine.d.ts +0 -19
  253. package/dist/elements/EFMedia/AssetIdMediaEngine.test.d.ts +0 -1
  254. package/dist/elements/EFMedia/AssetMediaEngine.browsertest.d.ts +0 -0
  255. package/dist/elements/EFMedia/AssetMediaEngine.d.ts +0 -56
  256. package/dist/elements/EFMedia/BaseMediaEngine.browsertest.d.ts +0 -1
  257. package/dist/elements/EFMedia/BaseMediaEngine.d.ts +0 -103
  258. package/dist/elements/EFMedia/BufferedSeekingInput.browsertest.d.ts +0 -1
  259. package/dist/elements/EFMedia/JitMediaEngine.browsertest.d.ts +0 -0
  260. package/dist/elements/EFMedia/JitMediaEngine.d.ts +0 -46
  261. package/dist/elements/EFMedia/audioTasks/makeAudioBufferTask.browsertest.d.ts +0 -9
  262. package/dist/elements/EFMedia/audioTasks/makeAudioFrequencyAnalysisTask.d.ts +0 -3
  263. package/dist/elements/EFMedia/audioTasks/makeAudioInitSegmentFetchTask.browsertest.d.ts +0 -9
  264. package/dist/elements/EFMedia/audioTasks/makeAudioInitSegmentFetchTask.d.ts +0 -4
  265. package/dist/elements/EFMedia/audioTasks/makeAudioInputTask.browsertest.d.ts +0 -9
  266. package/dist/elements/EFMedia/audioTasks/makeAudioInputTask.d.ts +0 -3
  267. package/dist/elements/EFMedia/audioTasks/makeAudioSeekTask.chunkboundary.regression.browsertest.d.ts +0 -0
  268. package/dist/elements/EFMedia/audioTasks/makeAudioSeekTask.d.ts +0 -7
  269. package/dist/elements/EFMedia/audioTasks/makeAudioSegmentFetchTask.d.ts +0 -4
  270. package/dist/elements/EFMedia/audioTasks/makeAudioSegmentIdTask.d.ts +0 -4
  271. package/dist/elements/EFMedia/audioTasks/makeAudioTasksVideoOnly.browsertest.d.ts +0 -1
  272. package/dist/elements/EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.d.ts +0 -3
  273. package/dist/elements/EFMedia/shared/AudioSpanUtils.d.ts +0 -7
  274. package/dist/elements/EFMedia/shared/GlobalInputCache.d.ts +0 -39
  275. package/dist/elements/EFMedia/shared/PrecisionUtils.d.ts +0 -28
  276. package/dist/elements/EFMedia/shared/RenditionHelpers.browsertest.d.ts +0 -1
  277. package/dist/elements/EFMedia/shared/RenditionHelpers.d.ts +0 -11
  278. package/dist/elements/EFMedia/shared/ThumbnailExtractor.d.ts +0 -27
  279. package/dist/elements/EFMedia/tasks/makeMediaEngineTask.browsertest.d.ts +0 -9
  280. package/dist/elements/EFMedia/tasks/makeMediaEngineTask.d.ts +0 -17
  281. package/dist/elements/EFMedia/videoTasks/MainVideoInputCache.d.ts +0 -29
  282. package/dist/elements/EFMedia/videoTasks/ScrubInputCache.d.ts +0 -25
  283. package/dist/elements/EFMedia/videoTasks/makeScrubVideoBufferTask.d.ts +0 -8
  284. package/dist/elements/EFMedia/videoTasks/makeScrubVideoInitSegmentFetchTask.d.ts +0 -4
  285. package/dist/elements/EFMedia/videoTasks/makeScrubVideoInputTask.d.ts +0 -3
  286. package/dist/elements/EFMedia/videoTasks/makeScrubVideoSeekTask.d.ts +0 -6
  287. package/dist/elements/EFMedia/videoTasks/makeScrubVideoSegmentFetchTask.d.ts +0 -4
  288. package/dist/elements/EFMedia/videoTasks/makeScrubVideoSegmentIdTask.d.ts +0 -4
  289. package/dist/elements/EFMedia/videoTasks/makeUnifiedVideoSeekTask.d.ts +0 -6
  290. package/dist/elements/EFMedia.browsertest.d.ts +0 -10
  291. package/dist/elements/EFSurface.browsertest.d.ts +0 -0
  292. package/dist/elements/EFTemporal.browsertest.d.ts +0 -22
  293. package/dist/elements/EFThumbnailStrip.browsertest.d.ts +0 -0
  294. package/dist/elements/EFThumbnailStrip.media-engine.browsertest.d.ts +0 -0
  295. package/dist/elements/EFTimegroup.browsertest.d.ts +0 -41
  296. package/dist/elements/EFVideo.browsertest.d.ts +0 -0
  297. package/dist/elements/FetchContext.browsertest.d.ts +0 -0
  298. package/dist/elements/TargetController.browsertest.d.ts +0 -19
  299. package/dist/elements/durationConverter.d.ts +0 -16
  300. package/dist/elements/parseTimeToMs.d.ts +0 -1
  301. package/dist/elements/printTaskStatus.d.ts +0 -2
  302. package/dist/elements/renderTemporalAudio.d.ts +0 -10
  303. package/dist/elements/updateAnimations.browsertest.d.ts +0 -13
  304. package/dist/elements/updateAnimations.d.ts +0 -24
  305. package/dist/elements/util.d.ts +0 -3
  306. package/dist/gui/ContextMixin.browsertest.d.ts +0 -15
  307. package/dist/gui/Controllable.browsertest.d.ts +0 -0
  308. package/dist/gui/EFControls.browsertest.d.ts +0 -11
  309. package/dist/gui/EFDial.browsertest.d.ts +0 -0
  310. package/dist/gui/EFFilmstrip.browsertest.d.ts +0 -11
  311. package/dist/gui/EFPause.browsertest.d.ts +0 -0
  312. package/dist/gui/EFPlay.browsertest.d.ts +0 -0
  313. package/dist/gui/EFResizableBox.browsertest.d.ts +0 -0
  314. package/dist/gui/EFTimeDisplay.browsertest.d.ts +0 -0
  315. package/dist/gui/TWMixin.d.ts +0 -2
  316. package/dist/gui/TargetOrContextMixin.d.ts +0 -10
  317. package/dist/gui/currentTimeContext.d.ts +0 -3
  318. package/dist/gui/durationContext.d.ts +0 -3
  319. package/dist/gui/efContext.d.ts +0 -4
  320. package/dist/gui/fetchContext.d.ts +0 -3
  321. package/dist/gui/focusedElementContext.d.ts +0 -3
  322. package/dist/gui/playingContext.d.ts +0 -6
  323. package/dist/msToTimeCode.d.ts +0 -1
  324. package/dist/otel/BridgeSpanExporter.d.ts +0 -13
  325. package/dist/otel/setupBrowserTracing.d.ts +0 -12
  326. package/dist/style.css +0 -2
  327. package/dist/transcoding/cache/RequestDeduplicator.d.ts +0 -29
  328. package/dist/transcoding/cache/RequestDeduplicator.test.d.ts +0 -1
  329. package/dist/transcoding/cache/URLTokenDeduplicator.d.ts +0 -38
  330. package/dist/transcoding/cache/URLTokenDeduplicator.test.d.ts +0 -1
  331. package/dist/transcoding/utils/MediaUtils.d.ts +0 -9
  332. package/dist/transcoding/utils/constants.d.ts +0 -27
  333. package/dist/utils/LRUCache.d.ts +0 -80
  334. package/dist/utils/LRUCache.test.d.ts +0 -1
  335. /package/dist/{LoadingIndicator.browsertest.d.ts → elements.js} +0 -0
@@ -1,119 +1,128 @@
1
- import { Task, TaskStatus } from '@lit/task';
2
- import { LitElement, PropertyValueMap } from 'lit';
3
- import { EFAudio } from './EFAudio.js';
4
- import { EFVideo } from './EFVideo.js';
5
- export interface WordSegment {
6
- text: string;
7
- start: number;
8
- end: number;
1
+ import { TemporalMixinInterface } from "./EFTemporal.js";
2
+ import { EFSourceMixinInterface } from "./EFSourceMixin.js";
3
+ import { FetchMixinInterface } from "./FetchMixin.js";
4
+ import { EFAudio } from "./EFAudio.js";
5
+ import { EFVideo } from "./EFVideo.js";
6
+ import { Task, TaskStatus } from "@lit/task";
7
+ import * as lit3 from "lit";
8
+ import { LitElement, PropertyValueMap } from "lit";
9
+ import * as lit_html3 from "lit-html";
10
+
11
+ //#region src/elements/EFCaptions.d.ts
12
+ interface WordSegment {
13
+ text: string;
14
+ start: number;
15
+ end: number;
9
16
  }
10
- export interface Segment {
11
- start: number;
12
- end: number;
13
- text: string;
17
+ interface Segment {
18
+ start: number;
19
+ end: number;
20
+ text: string;
14
21
  }
15
- export interface Caption {
16
- segments: Segment[];
17
- word_segments: WordSegment[];
22
+ interface Caption {
23
+ segments: Segment[];
24
+ word_segments: WordSegment[];
18
25
  }
19
- declare const EFCaptionsActiveWord_base: (new (...args: any[]) => import('./EFTemporal.js').TemporalMixinInterface) & typeof LitElement;
20
- export declare class EFCaptionsActiveWord extends EFCaptionsActiveWord_base {
21
- static styles: import('lit').CSSResult[];
22
- render(): import('lit-html').TemplateResult<1> | undefined;
23
- wordStartMs: number;
24
- wordEndMs: number;
25
- wordText: string;
26
- wordIndex: number;
27
- hidden: boolean;
28
- get startTimeMs(): number;
29
- get endTimeMs(): number;
30
- get durationMs(): number;
26
+ declare const EFCaptionsActiveWord_base: (new (...args: any[]) => TemporalMixinInterface) & typeof LitElement;
27
+ declare class EFCaptionsActiveWord extends EFCaptionsActiveWord_base {
28
+ static styles: lit3.CSSResult[];
29
+ render(): lit_html3.TemplateResult<1> | undefined;
30
+ wordStartMs: number;
31
+ wordEndMs: number;
32
+ wordText: string;
33
+ wordIndex: number;
34
+ hidden: boolean;
35
+ get startTimeMs(): number;
36
+ get endTimeMs(): number;
37
+ get durationMs(): number;
31
38
  }
32
- declare const EFCaptionsSegment_base: (new (...args: any[]) => import('./EFTemporal.js').TemporalMixinInterface) & typeof LitElement;
33
- export declare class EFCaptionsSegment extends EFCaptionsSegment_base {
34
- static styles: import('lit').CSSResult[];
35
- render(): import('lit-html').TemplateResult<1> | undefined;
36
- segmentStartMs: number;
37
- segmentEndMs: number;
38
- segmentText: string;
39
- hidden: boolean;
40
- get startTimeMs(): number;
41
- get endTimeMs(): number;
42
- get durationMs(): number;
39
+ declare const EFCaptionsSegment_base: (new (...args: any[]) => TemporalMixinInterface) & typeof LitElement;
40
+ declare class EFCaptionsSegment extends EFCaptionsSegment_base {
41
+ static styles: lit3.CSSResult[];
42
+ render(): lit_html3.TemplateResult<1> | undefined;
43
+ segmentStartMs: number;
44
+ segmentEndMs: number;
45
+ segmentText: string;
46
+ hidden: boolean;
47
+ get startTimeMs(): number;
48
+ get endTimeMs(): number;
49
+ get durationMs(): number;
43
50
  }
44
- export declare class EFCaptionsBeforeActiveWord extends EFCaptionsSegment {
45
- static styles: import('lit').CSSResult[];
46
- render(): import('lit-html').TemplateResult<1> | undefined;
47
- hidden: boolean;
48
- segmentText: string;
49
- segmentStartMs: number;
50
- segmentEndMs: number;
51
- get startTimeMs(): number;
52
- get endTimeMs(): number;
53
- get durationMs(): number;
51
+ declare class EFCaptionsBeforeActiveWord extends EFCaptionsSegment {
52
+ static styles: lit3.CSSResult[];
53
+ render(): lit_html3.TemplateResult<1> | undefined;
54
+ hidden: boolean;
55
+ segmentText: string;
56
+ segmentStartMs: number;
57
+ segmentEndMs: number;
58
+ get startTimeMs(): number;
59
+ get endTimeMs(): number;
60
+ get durationMs(): number;
54
61
  }
55
- export declare class EFCaptionsAfterActiveWord extends EFCaptionsSegment {
56
- static styles: import('lit').CSSResult[];
57
- render(): import('lit-html').TemplateResult<1> | undefined;
58
- hidden: boolean;
59
- segmentText: string;
60
- segmentStartMs: number;
61
- segmentEndMs: number;
62
- get startTimeMs(): number;
63
- get endTimeMs(): number;
64
- get durationMs(): number;
62
+ declare class EFCaptionsAfterActiveWord extends EFCaptionsSegment {
63
+ static styles: lit3.CSSResult[];
64
+ render(): lit_html3.TemplateResult<1> | undefined;
65
+ hidden: boolean;
66
+ segmentText: string;
67
+ segmentStartMs: number;
68
+ segmentEndMs: number;
69
+ get startTimeMs(): number;
70
+ get endTimeMs(): number;
71
+ get durationMs(): number;
65
72
  }
66
- declare const EFCaptions_base: (new (...args: any[]) => import('./EFSourceMixin.js').EFSourceMixinInterface) & (new (...args: any[]) => import('./EFTemporal.js').TemporalMixinInterface) & (new (...args: any[]) => import('./FetchMixin.js').FetchMixinInterface) & typeof LitElement;
67
- export declare class EFCaptions extends EFCaptions_base {
68
- static styles: import('lit').CSSResult[];
69
- targetSelector: string;
70
- set target(value: string);
71
- wordStyle: string;
72
- /**
73
- * URL or path to a JSON file containing custom captions data.
74
- * The JSON should conform to the Caption interface with 'segments' and 'word_segments' arrays.
75
- */
76
- captionsSrc: string;
77
- /**
78
- * Direct captions data object. Takes priority over captions-src and captions-script.
79
- * Should conform to the Caption interface with 'segments' and 'word_segments' arrays.
80
- */
81
- captionsData: Caption | null;
82
- /**
83
- * ID of a <script> element containing JSON captions data.
84
- * The script's textContent should be valid JSON conforming to the Caption interface.
85
- */
86
- captionsScript: string;
87
- activeWordContainers: HTMLCollectionOf<EFCaptionsActiveWord>;
88
- segmentContainers: HTMLCollectionOf<EFCaptionsSegment>;
89
- beforeActiveWordContainers: HTMLCollectionOf<EFCaptionsBeforeActiveWord>;
90
- afterActiveWordContainers: HTMLCollectionOf<EFCaptionsAfterActiveWord>;
91
- render(): import('lit-html').TemplateResult<1>;
92
- transcriptionsPath(): string | null;
93
- captionsPath(): string | null;
94
- protected md5SumLoader: Task<readonly [string, typeof fetch], string | null | undefined>;
95
- private transcriptionDataTask;
96
- private transcriptionFragmentPath;
97
- private fragmentIndexTask;
98
- private customCaptionsDataTask;
99
- private transcriptionFragmentDataTask;
100
- unifiedCaptionsDataTask: Task<readonly [Caption | null | undefined, Caption | null | undefined], Caption | null | undefined>;
101
- frameTask: Task<readonly [TaskStatus, number], void>;
102
- connectedCallback(): void;
103
- protected updated(changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>): void;
104
- updateTextContainers(): void;
105
- get targetElement(): EFAudio | EFVideo | null;
106
- get hasCustomCaptionsData(): boolean;
107
- get intrinsicDurationMs(): number | undefined;
108
- get hasOwnDuration(): boolean;
73
+ declare const EFCaptions_base: (new (...args: any[]) => EFSourceMixinInterface) & (new (...args: any[]) => TemporalMixinInterface) & (new (...args: any[]) => FetchMixinInterface) & typeof LitElement;
74
+ declare class EFCaptions extends EFCaptions_base {
75
+ static styles: lit3.CSSResult[];
76
+ targetSelector: string;
77
+ set target(value: string);
78
+ wordStyle: string;
79
+ /**
80
+ * URL or path to a JSON file containing custom captions data.
81
+ * The JSON should conform to the Caption interface with 'segments' and 'word_segments' arrays.
82
+ */
83
+ captionsSrc: string;
84
+ /**
85
+ * Direct captions data object. Takes priority over captions-src and captions-script.
86
+ * Should conform to the Caption interface with 'segments' and 'word_segments' arrays.
87
+ */
88
+ captionsData: Caption | null;
89
+ /**
90
+ * ID of a <script> element containing JSON captions data.
91
+ * The script's textContent should be valid JSON conforming to the Caption interface.
92
+ */
93
+ captionsScript: string;
94
+ activeWordContainers: HTMLCollectionOf<EFCaptionsActiveWord>;
95
+ segmentContainers: HTMLCollectionOf<EFCaptionsSegment>;
96
+ beforeActiveWordContainers: HTMLCollectionOf<EFCaptionsBeforeActiveWord>;
97
+ afterActiveWordContainers: HTMLCollectionOf<EFCaptionsAfterActiveWord>;
98
+ render(): lit_html3.TemplateResult<1>;
99
+ transcriptionsPath(): string | null;
100
+ captionsPath(): string | null;
101
+ protected md5SumLoader: Task<readonly [string, typeof fetch], string | null | undefined>;
102
+ private transcriptionDataTask;
103
+ private transcriptionFragmentPath;
104
+ private fragmentIndexTask;
105
+ private customCaptionsDataTask;
106
+ private transcriptionFragmentDataTask;
107
+ unifiedCaptionsDataTask: Task<readonly [Caption | null | undefined, Caption | null | undefined], Caption | null | undefined>;
108
+ frameTask: Task<readonly [TaskStatus, number], void>;
109
+ connectedCallback(): void;
110
+ protected updated(changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>): void;
111
+ updateTextContainers(): void;
112
+ get targetElement(): EFAudio | EFVideo | null;
113
+ get hasCustomCaptionsData(): boolean;
114
+ get intrinsicDurationMs(): number | undefined;
115
+ get hasOwnDuration(): boolean;
109
116
  }
110
117
  declare global {
111
- interface HTMLElementTagNameMap {
112
- "ef-captions": EFCaptions;
113
- "ef-captions-active-word": EFCaptionsActiveWord;
114
- "ef-captions-segment": EFCaptionsSegment;
115
- "ef-captions-before-active-word": EFCaptionsBeforeActiveWord;
116
- "ef-captions-after-active-word": EFCaptionsAfterActiveWord;
117
- }
118
+ interface HTMLElementTagNameMap {
119
+ "ef-captions": EFCaptions;
120
+ "ef-captions-active-word": EFCaptionsActiveWord;
121
+ "ef-captions-segment": EFCaptionsSegment;
122
+ "ef-captions-before-active-word": EFCaptionsBeforeActiveWord;
123
+ "ef-captions-after-active-word": EFCaptionsAfterActiveWord;
124
+ }
118
125
  }
119
- export {};
126
+ //#endregion
127
+ export { Caption, EFCaptions, EFCaptionsActiveWord, EFCaptionsAfterActiveWord, EFCaptionsBeforeActiveWord, EFCaptionsSegment };
128
+ //# sourceMappingURL=EFCaptions.d.ts.map
@@ -10,14 +10,16 @@ import { CrossUpdateController } from "./CrossUpdateController.js";
10
10
  import { Task, TaskStatus } from "@lit/task";
11
11
  import { LitElement, css, html } from "lit";
12
12
  import { customElement, property } from "lit/decorators.js";
13
- var stopWords = new Set([
13
+
14
+ //#region src/elements/EFCaptions.ts
15
+ const stopWords = new Set([
14
16
  "",
15
17
  ".",
16
18
  "!",
17
19
  "?",
18
20
  ","
19
21
  ]);
20
- var EFCaptionsActiveWord = class EFCaptionsActiveWord$1 extends EFTemporal(LitElement) {
22
+ let EFCaptionsActiveWord = class EFCaptionsActiveWord$1 extends EFTemporal(LitElement) {
21
23
  constructor(..._args) {
22
24
  super(..._args);
23
25
  this.wordStartMs = 0;
@@ -80,7 +82,7 @@ __decorate([property({
80
82
  reflect: true
81
83
  })], EFCaptionsActiveWord.prototype, "hidden", void 0);
82
84
  EFCaptionsActiveWord = __decorate([customElement("ef-captions-active-word")], EFCaptionsActiveWord);
83
- var EFCaptionsSegment = class EFCaptionsSegment$1 extends EFTemporal(LitElement) {
85
+ let EFCaptionsSegment = class EFCaptionsSegment$1 extends EFTemporal(LitElement) {
84
86
  constructor(..._args2) {
85
87
  super(..._args2);
86
88
  this.segmentStartMs = 0;
@@ -132,7 +134,7 @@ __decorate([property({
132
134
  reflect: true
133
135
  })], EFCaptionsSegment.prototype, "hidden", void 0);
134
136
  EFCaptionsSegment = __decorate([customElement("ef-captions-segment")], EFCaptionsSegment);
135
- var EFCaptionsBeforeActiveWord = class EFCaptionsBeforeActiveWord$1 extends EFCaptionsSegment {
137
+ let EFCaptionsBeforeActiveWord = class EFCaptionsBeforeActiveWord$1 extends EFCaptionsSegment {
136
138
  constructor(..._args3) {
137
139
  super(..._args3);
138
140
  this.hidden = false;
@@ -190,7 +192,7 @@ __decorate([property({
190
192
  attribute: false
191
193
  })], EFCaptionsBeforeActiveWord.prototype, "segmentEndMs", void 0);
192
194
  EFCaptionsBeforeActiveWord = __decorate([customElement("ef-captions-before-active-word")], EFCaptionsBeforeActiveWord);
193
- var EFCaptionsAfterActiveWord = class EFCaptionsAfterActiveWord$1 extends EFCaptionsSegment {
195
+ let EFCaptionsAfterActiveWord = class EFCaptionsAfterActiveWord$1 extends EFCaptionsSegment {
194
196
  constructor(..._args4) {
195
197
  super(..._args4);
196
198
  this.hidden = false;
@@ -247,7 +249,7 @@ __decorate([property({
247
249
  attribute: false
248
250
  })], EFCaptionsAfterActiveWord.prototype, "segmentEndMs", void 0);
249
251
  EFCaptionsAfterActiveWord = __decorate([customElement("ef-captions-after-active-word")], EFCaptionsAfterActiveWord);
250
- var EFCaptions = class EFCaptions$1 extends EFSourceMixin(EFTemporal(FetchMixin(LitElement)), { assetType: "caption_files" }) {
252
+ let EFCaptions = class EFCaptions$1 extends EFSourceMixin(EFTemporal(FetchMixin(LitElement)), { assetType: "caption_files" }) {
251
253
  constructor(..._args5) {
252
254
  super(..._args5);
253
255
  this.targetSelector = "";
@@ -557,4 +559,7 @@ __decorate([property({
557
559
  reflect: true
558
560
  })], EFCaptions.prototype, "captionsScript", void 0);
559
561
  EFCaptions = __decorate([customElement("ef-captions")], EFCaptions);
562
+
563
+ //#endregion
560
564
  export { EFCaptions, EFCaptionsActiveWord, EFCaptionsAfterActiveWord, EFCaptionsBeforeActiveWord, EFCaptionsSegment };
565
+ //# sourceMappingURL=EFCaptions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EFCaptions.js","names":["EFCaptionsActiveWord","EFCaptionsSegment","EFCaptionsBeforeActiveWord","EFCaptionsAfterActiveWord","EFCaptions","captionsData: Caption | null"],"sources":["../../src/elements/EFCaptions.ts"],"sourcesContent":["import { Task, TaskStatus } from \"@lit/task\";\nimport { css, html, LitElement, type PropertyValueMap } from \"lit\";\nimport { customElement, property } from \"lit/decorators.js\";\nimport type { GetISOBMFFFileTranscriptionResult } from \"../../../api/src/index.js\";\nimport { EF_INTERACTIVE } from \"../EF_INTERACTIVE.js\";\nimport { CrossUpdateController } from \"./CrossUpdateController.js\";\nimport { EFAudio } from \"./EFAudio.js\";\nimport { EFSourceMixin } from \"./EFSourceMixin.js\";\nimport { EFTemporal, flushStartTimeMsCache } from \"./EFTemporal.js\";\nimport { flushSequenceDurationCache } from \"./EFTimegroup.js\";\nimport { EFVideo } from \"./EFVideo.js\";\nimport { FetchMixin } from \"./FetchMixin.js\";\n\nexport interface WordSegment {\n text: string;\n start: number;\n end: number;\n}\n\nexport interface Segment {\n start: number;\n end: number;\n text: string;\n}\n\nexport interface Caption {\n segments: Segment[];\n word_segments: WordSegment[];\n}\n\nconst stopWords = new Set([\"\", \".\", \"!\", \"?\", \",\"]);\n\n@customElement(\"ef-captions-active-word\")\nexport class EFCaptionsActiveWord extends EFTemporal(LitElement) {\n static styles = [\n css`\n :host {\n display: inline-block;\n white-space: normal;\n line-height: 1;\n }\n :host([hidden]) {\n opacity: 0;\n pointer-events: none;\n }\n `,\n ];\n\n render() {\n if (stopWords.has(this.wordText)) {\n this.hidden = true;\n return undefined;\n }\n this.hidden = false;\n\n // Set deterministic --ef-word-seed value based on word index\n const seed = (this.wordIndex * 9007) % 233; // Prime numbers for better distribution\n const seedValue = seed / 233; // Normalize to 0-1 range\n this.style.setProperty(\"--ef-word-seed\", seedValue.toString());\n\n return html`${this.wordText}`;\n }\n\n @property({ type: Number, attribute: false })\n wordStartMs = 0;\n\n @property({ type: Number, attribute: false })\n wordEndMs = 0;\n\n @property({ type: String, attribute: false })\n wordText = \"\";\n\n @property({ type: Number, attribute: false })\n wordIndex = 0;\n\n @property({ type: Boolean, reflect: true })\n hidden = false;\n\n get startTimeMs() {\n // Get parent captions element's absolute start time, then add our local offset\n const parentCaptions = this.closest(\"ef-captions\") as EFCaptions;\n const parentStartTime = parentCaptions?.startTimeMs || 0;\n return parentStartTime + (this.wordStartMs || 0);\n }\n\n get endTimeMs() {\n const parentCaptions = this.closest(\"ef-captions\") as EFCaptions;\n const parentStartTime = parentCaptions?.startTimeMs || 0;\n return parentStartTime + (this.wordEndMs || 0);\n }\n\n get durationMs(): number {\n return this.wordEndMs - this.wordStartMs;\n }\n}\n\n@customElement(\"ef-captions-segment\")\nexport class EFCaptionsSegment extends EFTemporal(LitElement) {\n static styles = [\n css`\n :host {\n display: inline-block;\n white-space: normal;\n line-height: 1;\n }\n `,\n ];\n\n render() {\n if (stopWords.has(this.segmentText)) {\n this.hidden = true;\n return undefined;\n }\n this.hidden = false;\n return html`${this.segmentText}`;\n }\n\n @property({ type: Number, attribute: false })\n segmentStartMs = 0;\n\n @property({ type: Number, attribute: false })\n segmentEndMs = 0;\n\n @property({ type: String, attribute: false })\n segmentText = \"\";\n\n @property({ type: Boolean, reflect: true })\n hidden = false;\n\n get startTimeMs() {\n // Get parent captions element's absolute start time, then add our local offset\n const parentCaptions = this.closest(\"ef-captions\") as EFCaptions;\n const parentStartTime = parentCaptions?.startTimeMs || 0;\n return parentStartTime + (this.segmentStartMs || 0);\n }\n\n get endTimeMs() {\n const parentCaptions = this.closest(\"ef-captions\") as EFCaptions;\n const parentStartTime = parentCaptions?.startTimeMs || 0;\n return parentStartTime + (this.segmentEndMs || 0);\n }\n\n get durationMs(): number {\n return this.segmentEndMs - this.segmentStartMs;\n }\n}\n\n@customElement(\"ef-captions-before-active-word\")\nexport class EFCaptionsBeforeActiveWord extends EFCaptionsSegment {\n static styles = [\n css`\n :host {\n display: inline-block;\n white-space: pre;\n line-height: 1;\n }\n :host([hidden]) {\n opacity: 0;\n pointer-events: none;\n }\n `,\n ];\n\n render() {\n if (stopWords.has(this.segmentText)) {\n this.hidden = true;\n return undefined;\n }\n this.hidden = false;\n\n // Check if there's an active word by looking for sibling active word element\n const activeWord = this.closest(\"ef-captions\")?.querySelector(\n \"ef-captions-active-word\",\n );\n const hasActiveWord = activeWord?.wordText && !activeWord.hidden;\n\n return html`${this.segmentText}${hasActiveWord ? \" \" : \"\"}`;\n }\n\n @property({ type: Boolean, reflect: true })\n hidden = false;\n\n @property({ type: String, attribute: false })\n segmentText = \"\";\n\n @property({ type: Number, attribute: false })\n segmentStartMs = 0;\n\n @property({ type: Number, attribute: false })\n segmentEndMs = 0;\n\n get startTimeMs() {\n // Get parent captions element's absolute start time, then add our local offset\n const parentCaptions = this.closest(\"ef-captions\") as EFCaptions;\n const parentStartTime = parentCaptions?.startTimeMs || 0;\n return parentStartTime + (this.segmentStartMs || 0);\n }\n\n get endTimeMs() {\n const parentCaptions = this.closest(\"ef-captions\") as EFCaptions;\n const parentStartTime = parentCaptions?.startTimeMs || 0;\n return parentStartTime + (this.segmentEndMs || 0);\n }\n\n get durationMs(): number {\n return this.segmentEndMs - this.segmentStartMs;\n }\n}\n\n@customElement(\"ef-captions-after-active-word\")\nexport class EFCaptionsAfterActiveWord extends EFCaptionsSegment {\n static styles = [\n css`\n :host {\n display: inline-block;\n white-space: pre;\n line-height: 1;\n }\n :host([hidden]) {\n opacity: 0;\n pointer-events: none;\n }\n `,\n ];\n\n render() {\n if (stopWords.has(this.segmentText)) {\n this.hidden = true;\n return undefined;\n }\n this.hidden = false;\n\n // Check if there's an active word by looking for sibling active word element\n const activeWord = this.closest(\"ef-captions\")?.querySelector(\n \"ef-captions-active-word\",\n );\n const hasActiveWord = activeWord?.wordText && !activeWord.hidden;\n\n return html`${hasActiveWord ? \" \" : \"\"}${this.segmentText}`;\n }\n\n @property({ type: Boolean, reflect: true })\n hidden = false;\n\n @property({ type: String, attribute: false })\n segmentText = \"\";\n\n @property({ type: Number, attribute: false })\n segmentStartMs = 0;\n\n @property({ type: Number, attribute: false })\n segmentEndMs = 0;\n\n get startTimeMs() {\n // Get parent captions element's absolute start time, then add our local offset\n const parentCaptions = this.closest(\"ef-captions\") as EFCaptions;\n const parentStartTime = parentCaptions?.startTimeMs || 0;\n return parentStartTime + (this.segmentStartMs || 0);\n }\n\n get endTimeMs() {\n const parentCaptions = this.closest(\"ef-captions\") as EFCaptions;\n const parentStartTime = parentCaptions?.startTimeMs || 0;\n return parentStartTime + (this.segmentEndMs || 0);\n }\n\n get durationMs(): number {\n return this.segmentEndMs - this.segmentStartMs;\n }\n}\n\n@customElement(\"ef-captions\")\nexport class EFCaptions extends EFSourceMixin(\n EFTemporal(FetchMixin(LitElement)),\n { assetType: \"caption_files\" },\n) {\n static styles = [\n css`\n :host {\n display: inline-flex;\n white-space: normal;\n line-height: 1;\n gap: 0;\n }\n ::slotted(*) {\n display: inline-block;\n margin: 0;\n padding: 0;\n }\n `,\n ];\n\n @property({ type: String, attribute: \"target\", reflect: true })\n targetSelector = \"\";\n\n set target(value: string) {\n this.targetSelector = value;\n }\n\n @property({ attribute: \"word-style\" })\n wordStyle = \"\";\n\n /**\n * URL or path to a JSON file containing custom captions data.\n * The JSON should conform to the Caption interface with 'segments' and 'word_segments' arrays.\n */\n @property({ type: String, attribute: \"captions-src\", reflect: true })\n captionsSrc = \"\";\n\n /**\n * Direct captions data object. Takes priority over captions-src and captions-script.\n * Should conform to the Caption interface with 'segments' and 'word_segments' arrays.\n */\n @property({ type: Object, attribute: false })\n captionsData: Caption | null = null;\n\n /**\n * ID of a <script> element containing JSON captions data.\n * The script's textContent should be valid JSON conforming to the Caption interface.\n */\n @property({ type: String, attribute: \"captions-script\", reflect: true })\n captionsScript = \"\";\n\n activeWordContainers = this.getElementsByTagName(\"ef-captions-active-word\");\n segmentContainers = this.getElementsByTagName(\"ef-captions-segment\");\n beforeActiveWordContainers = this.getElementsByTagName(\n \"ef-captions-before-active-word\",\n );\n afterActiveWordContainers = this.getElementsByTagName(\n \"ef-captions-after-active-word\",\n );\n\n render() {\n return html`<slot></slot>`;\n }\n\n transcriptionsPath() {\n if (!this.targetElement) {\n return null;\n }\n if (this.targetElement.assetId) {\n return `${this.apiHost}/api/v1/isobmff_files/${this.targetElement.assetId}/transcription`;\n }\n return null;\n }\n\n captionsPath() {\n if (!this.targetElement) {\n return null;\n }\n if (this.targetElement.assetId) {\n return `${this.apiHost}/api/v1/caption_files/${this.targetElement.assetId}`;\n }\n const targetSrc = this.targetElement.src;\n return `/@ef-captions/${targetSrc}`;\n }\n\n protected md5SumLoader = new Task(this, {\n autoRun: false,\n args: () => [this.target, this.fetch] as const,\n task: async ([_target, fetch], { signal }) => {\n if (!this.targetElement) {\n return null;\n }\n const md5Path = `/@ef-asset/${this.targetElement.src ?? \"\"}`;\n const response = await fetch(md5Path, { method: \"HEAD\", signal });\n return response.headers.get(\"etag\") ?? undefined;\n },\n });\n\n private transcriptionDataTask = new Task(this, {\n autoRun: EF_INTERACTIVE,\n args: () =>\n [\n this.transcriptionsPath(),\n this.fetch,\n this.hasCustomCaptionsData,\n ] as const,\n task: async ([transcriptionsPath, fetch, hasCustomData], { signal }) => {\n // Skip transcription if we have custom captions data\n if (hasCustomData || !transcriptionsPath) {\n return null;\n }\n const response = await fetch(transcriptionsPath, { signal });\n return response.json() as any as GetISOBMFFFileTranscriptionResult;\n },\n });\n\n private transcriptionFragmentPath(\n transcriptionId: string,\n fragmentIndex: number,\n ) {\n return `${this.apiHost}/api/v1/transcriptions/${transcriptionId}/fragments/${fragmentIndex}`;\n }\n\n private fragmentIndexTask = new Task(this, {\n autoRun: EF_INTERACTIVE,\n args: () =>\n [this.transcriptionDataTask.value, this.ownCurrentTimeMs] as const,\n task: async ([transcription, ownCurrentTimeMs]) => {\n if (!transcription) {\n return null;\n }\n const fragmentIndex = Math.floor(\n ownCurrentTimeMs / transcription.work_slice_ms,\n );\n return fragmentIndex;\n },\n });\n\n private customCaptionsDataTask = new Task(this, {\n autoRun: EF_INTERACTIVE,\n args: () =>\n [\n this.captionsSrc,\n this.captionsData,\n this.captionsScript,\n this.fetch,\n ] as const,\n task: async (\n [captionsSrc, captionsData, captionsScript, fetch],\n { signal },\n ) => {\n // Priority: direct data > script reference > URL source\n if (captionsData) {\n return captionsData;\n }\n\n if (captionsScript) {\n const scriptElement = document.getElementById(captionsScript);\n if (scriptElement?.textContent) {\n try {\n return JSON.parse(scriptElement.textContent) as Caption;\n } catch (error) {\n console.error(\n `Failed to parse captions from script #${captionsScript}:`,\n error,\n );\n return null;\n }\n }\n }\n\n if (captionsSrc) {\n try {\n const response = await fetch(captionsSrc, { signal });\n return (await response.json()) as Caption;\n } catch (error) {\n console.error(`Failed to load captions from ${captionsSrc}:`, error);\n return null;\n }\n }\n\n return null;\n },\n });\n\n private transcriptionFragmentDataTask = new Task(this, {\n autoRun: EF_INTERACTIVE,\n args: () =>\n [\n this.transcriptionDataTask.value,\n this.fragmentIndexTask.value,\n this.fetch,\n ] as const,\n task: async ([transcription, fragmentIndex, fetch], { signal }) => {\n if (\n transcription === null ||\n transcription === undefined ||\n fragmentIndex === null ||\n fragmentIndex === undefined\n ) {\n return null;\n }\n const fragmentPath = this.transcriptionFragmentPath(\n transcription.id,\n fragmentIndex,\n );\n const response = await fetch(fragmentPath, { signal });\n return response.json() as any as Caption;\n },\n });\n\n unifiedCaptionsDataTask = new Task(this, {\n autoRun: EF_INTERACTIVE,\n args: () =>\n [\n this.customCaptionsDataTask.value,\n this.transcriptionFragmentDataTask.value,\n ] as const,\n task: async ([_customData, _transcriptionData]) => {\n if (this.customCaptionsDataTask.status === TaskStatus.PENDING) {\n await this.customCaptionsDataTask.taskComplete;\n }\n if (this.transcriptionFragmentDataTask.status === TaskStatus.PENDING) {\n await this.transcriptionFragmentDataTask.taskComplete;\n }\n return (\n this.customCaptionsDataTask.value ||\n this.transcriptionFragmentDataTask.value\n );\n },\n });\n\n frameTask = new Task(this, {\n autoRun: EF_INTERACTIVE,\n args: () => [this.unifiedCaptionsDataTask.status, this.ownCurrentTimeMs],\n task: async () => {\n await this.unifiedCaptionsDataTask.taskComplete;\n // Trigger updateTextContainers when data is ready or time changes\n this.updateTextContainers();\n },\n });\n\n connectedCallback() {\n super.connectedCallback();\n\n // Try to get target element safely\n const target = this.targetSelector\n ? document.getElementById(this.targetSelector)\n : null;\n if (target && (target instanceof EFAudio || target instanceof EFVideo)) {\n new CrossUpdateController(target, this);\n }\n // For standalone captions with custom data, ensure proper timeline sync\n else if (this.hasCustomCaptionsData && this.rootTimegroup) {\n new CrossUpdateController(this.rootTimegroup, this);\n }\n\n // Prevent display:none from being set on caption elements\n // This maintains constant width in the parent flex container\n const observer = new MutationObserver(() => {\n if (this.style.display === \"none\") {\n // Remove the display:none and use opacity instead\n this.style.removeProperty(\"display\");\n this.style.opacity = \"0\";\n this.style.pointerEvents = \"none\";\n }\n });\n observer.observe(this, { attributes: true, attributeFilter: [\"style\"] });\n }\n\n protected updated(\n changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>,\n ): void {\n this.updateTextContainers();\n\n // Force duration recalculation when custom captions data changes\n if (\n changedProperties.has(\"captionsData\") ||\n changedProperties.has(\"captionsSrc\") ||\n changedProperties.has(\"captionsScript\")\n ) {\n this.requestUpdate(\"intrinsicDurationMs\");\n\n // Flush sequence duration cache and notify parent timegroups that child duration has changed\n flushSequenceDurationCache();\n flushStartTimeMsCache();\n\n // Notify parent timegroup to recalculate its duration\n if (this.parentTimegroup) {\n this.parentTimegroup.requestUpdate(\"durationMs\");\n this.parentTimegroup.requestUpdate(\"currentTime\");\n }\n }\n\n // Update captions when timeline position changes\n if (changedProperties.has(\"ownCurrentTimeMs\")) {\n this.updateTextContainers();\n }\n }\n\n updateTextContainers() {\n const captionsData = this.unifiedCaptionsDataTask.value as Caption;\n if (!captionsData) {\n return;\n }\n\n // Use ownCurrentTimeMs which is synchronized with the timegroup\n const currentTimeMs = this.ownCurrentTimeMs;\n const currentTimeSec = currentTimeMs / 1000;\n\n // Find the current word from word_segments\n // Use exclusive end boundary to prevent overlap at exact boundaries\n const currentWord = captionsData.word_segments.find(\n (word) => currentTimeSec >= word.start && currentTimeSec < word.end,\n );\n\n // Find the current segment\n // Use exclusive end boundary to prevent overlap at exact boundaries\n const currentSegment = captionsData.segments.find(\n (segment) =>\n currentTimeSec >= segment.start && currentTimeSec < segment.end,\n );\n\n for (const wordContainer of this.activeWordContainers) {\n if (currentWord) {\n wordContainer.wordText = currentWord.text;\n wordContainer.wordStartMs = currentWord.start * 1000;\n wordContainer.wordEndMs = currentWord.end * 1000;\n // Set word index for deterministic animation variation\n const wordIndex = captionsData.word_segments.findIndex(\n (w) =>\n w.start === currentWord.start &&\n w.end === currentWord.end &&\n w.text === currentWord.text,\n );\n wordContainer.wordIndex = wordIndex >= 0 ? wordIndex : 0;\n // Force re-render to update hidden property\n wordContainer.requestUpdate();\n } else {\n // No active word - maintain layout with invisible placeholder\n wordContainer.wordText = \"\"; // Empty when no active word\n wordContainer.wordStartMs = 0;\n wordContainer.wordEndMs = 0;\n wordContainer.requestUpdate();\n }\n }\n\n for (const segmentContainer of this.segmentContainers) {\n if (currentSegment) {\n segmentContainer.segmentText = currentSegment.text;\n segmentContainer.segmentStartMs = currentSegment.start * 1000;\n segmentContainer.segmentEndMs = currentSegment.end * 1000;\n } else {\n // No active segment - clear the container\n segmentContainer.segmentText = \"\";\n segmentContainer.segmentStartMs = 0;\n segmentContainer.segmentEndMs = 0;\n }\n segmentContainer.requestUpdate();\n }\n\n // Process context for both word and segment cases\n if (currentWord && currentSegment) {\n // Find all word segments that fall within the current segment's time range\n const segmentWords = captionsData.word_segments.filter(\n (word) =>\n word.start >= currentSegment.start && word.end <= currentSegment.end,\n );\n\n // Find the index of the current word within the segment's word segments\n const currentWordIndex = segmentWords.findIndex(\n (word) =>\n word.start === currentWord.start && word.end === currentWord.end,\n );\n\n if (currentWordIndex !== -1) {\n // Get words before the current word\n const beforeWords = segmentWords\n .slice(0, currentWordIndex)\n .map((w) => w.text.trim())\n .join(\" \");\n\n // Get words after the current word\n const afterWords = segmentWords\n .slice(currentWordIndex + 1)\n .map((w) => w.text.trim())\n .join(\" \");\n\n // Update before containers - should be visible at the same time as active word\n for (const container of this.beforeActiveWordContainers) {\n container.segmentText = beforeWords;\n container.segmentStartMs = currentWord.start * 1000;\n container.segmentEndMs = currentWord.end * 1000;\n container.requestUpdate();\n }\n\n // Update after containers - should be visible at the same time as active word\n for (const container of this.afterActiveWordContainers) {\n container.segmentText = afterWords;\n container.segmentStartMs = currentWord.start * 1000;\n container.segmentEndMs = currentWord.end * 1000;\n container.requestUpdate();\n }\n }\n } else if (currentSegment) {\n // No active word but we have an active segment\n const segmentWords = captionsData.word_segments.filter(\n (word) =>\n word.start >= currentSegment.start && word.end <= currentSegment.end,\n );\n\n // Check if we're before the first word or after the last word\n const firstWord = segmentWords[0];\n const isBeforeFirstWord = firstWord && currentTimeSec < firstWord.start;\n\n if (isBeforeFirstWord) {\n // Before first word starts - show all words in \"after\" container (they're all upcoming)\n const allWords = segmentWords.map((w) => w.text.trim()).join(\" \");\n\n for (const container of this.beforeActiveWordContainers) {\n container.segmentText = \"\"; // Nothing before yet\n container.segmentStartMs = currentSegment.start * 1000;\n container.segmentEndMs = currentSegment.end * 1000;\n container.requestUpdate();\n }\n\n for (const container of this.afterActiveWordContainers) {\n container.segmentText = allWords; // All words are upcoming\n container.segmentStartMs = currentSegment.start * 1000;\n container.segmentEndMs = currentSegment.end * 1000;\n container.requestUpdate();\n }\n } else {\n // After last word ends - show all completed words in \"before\" container\n const allCompletedWords = segmentWords\n .map((w) => w.text.trim())\n .join(\" \");\n\n for (const container of this.beforeActiveWordContainers) {\n container.segmentText = allCompletedWords;\n container.segmentStartMs = currentSegment.start * 1000;\n container.segmentEndMs = currentSegment.end * 1000;\n container.requestUpdate();\n }\n\n for (const container of this.afterActiveWordContainers) {\n container.segmentText = \"\";\n container.segmentStartMs = currentSegment.start * 1000;\n container.segmentEndMs = currentSegment.end * 1000;\n container.requestUpdate();\n }\n }\n } else {\n // No active segment or word - clear all context containers\n for (const container of this.beforeActiveWordContainers) {\n container.segmentText = \"\";\n container.segmentStartMs = 0;\n container.segmentEndMs = 0;\n container.requestUpdate();\n }\n\n for (const container of this.afterActiveWordContainers) {\n container.segmentText = \"\";\n container.segmentStartMs = 0;\n container.segmentEndMs = 0;\n container.requestUpdate();\n }\n }\n }\n\n get targetElement() {\n const target = document.getElementById(this.targetSelector ?? \"\");\n if (target instanceof EFAudio || target instanceof EFVideo) {\n return target;\n }\n // When using custom captions data, a target is not required\n if (this.hasCustomCaptionsData) {\n return null;\n }\n return null;\n }\n\n get hasCustomCaptionsData(): boolean {\n return !!(this.captionsData || this.captionsSrc || this.captionsScript);\n }\n\n // Follow the exact EFMedia pattern for safe duration integration\n get intrinsicDurationMs(): number | undefined {\n // Direct access to custom captions data - avoiding complex task dependencies\n // Priority: direct data > script reference > external file\n let captionsData: Caption | null = null;\n\n if (this.captionsData) {\n captionsData = this.captionsData;\n } else if (this.captionsScript) {\n const scriptElement = document.getElementById(this.captionsScript);\n if (scriptElement?.textContent) {\n try {\n captionsData = JSON.parse(scriptElement.textContent) as Caption;\n } catch {\n // Invalid JSON, fall through to return undefined\n }\n }\n } else if (this.customCaptionsDataTask.value) {\n captionsData = this.customCaptionsDataTask.value as Caption;\n }\n\n if (!captionsData) {\n return undefined;\n }\n\n if (\n captionsData.segments.length === 0 &&\n captionsData.word_segments.length === 0\n ) {\n return 0;\n }\n\n // Find the maximum end time from both segments and word_segments\n const maxSegmentEnd =\n captionsData.segments.length > 0\n ? Math.max(...captionsData.segments.map((s) => s.end))\n : 0;\n const maxWordEnd =\n captionsData.word_segments.length > 0\n ? Math.max(...captionsData.word_segments.map((w) => w.end))\n : 0;\n\n return Math.max(maxSegmentEnd, maxWordEnd) * 1000; // Convert to milliseconds\n }\n\n // Follow the exact EFMedia pattern for safe duration integration\n get hasOwnDuration(): boolean {\n // Simple check - if we have any form of custom captions data, we have our own duration\n return !!(\n this.captionsData ||\n this.captionsScript ||\n this.customCaptionsDataTask.value\n );\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"ef-captions\": EFCaptions;\n \"ef-captions-active-word\": EFCaptionsActiveWord;\n \"ef-captions-segment\": EFCaptionsSegment;\n \"ef-captions-before-active-word\": EFCaptionsBeforeActiveWord;\n \"ef-captions-after-active-word\": EFCaptionsAfterActiveWord;\n }\n}\n"],"mappings":"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"}
@@ -1,23 +1,34 @@
1
- import { Task } from '@lit/task';
2
- import { LitElement } from 'lit';
3
- declare const EFImage_base: (new (...args: any[]) => import('./EFTemporal.js').TemporalMixinInterface) & (new (...args: any[]) => import('./EFSourceMixin.js').EFSourceMixinInterface) & (new (...args: any[]) => import('./FetchMixin.js').FetchMixinInterface) & typeof LitElement;
4
- export declare class EFImage extends EFImage_base {
5
- #private;
6
- static styles: import('lit').CSSResult[];
7
- imageRef: import('lit-html/directives/ref.js').Ref<HTMLImageElement>;
8
- canvasRef: import('lit-html/directives/ref.js').Ref<HTMLCanvasElement>;
9
- set assetId(value: string | null);
10
- get assetId(): string | null;
11
- render(): import('lit-html').TemplateResult<1>;
12
- private isDirectUrl;
13
- assetPath(): string;
14
- get hasOwnDuration(): boolean;
15
- fetchImage: Task<readonly [string, typeof fetch], void>;
16
- frameTask: Task<readonly [import('@lit/task').TaskStatus], void>;
1
+ import { TemporalMixinInterface } from "./EFTemporal.js";
2
+ import { EFSourceMixinInterface } from "./EFSourceMixin.js";
3
+ import { FetchMixinInterface } from "./FetchMixin.js";
4
+ import * as _lit_task0 from "@lit/task";
5
+ import { Task } from "@lit/task";
6
+ import * as lit0 from "lit";
7
+ import { LitElement } from "lit";
8
+ import * as lit_html0 from "lit-html";
9
+ import * as lit_html_directives_ref_js0 from "lit-html/directives/ref.js";
10
+
11
+ //#region src/elements/EFImage.d.ts
12
+ declare const EFImage_base: (new (...args: any[]) => TemporalMixinInterface) & (new (...args: any[]) => EFSourceMixinInterface) & (new (...args: any[]) => FetchMixinInterface) & typeof LitElement;
13
+ declare class EFImage extends EFImage_base {
14
+ #private;
15
+ static styles: lit0.CSSResult[];
16
+ imageRef: lit_html_directives_ref_js0.Ref<HTMLImageElement>;
17
+ canvasRef: lit_html_directives_ref_js0.Ref<HTMLCanvasElement>;
18
+ set assetId(value: string | null);
19
+ get assetId(): string | null;
20
+ render(): lit_html0.TemplateResult<1>;
21
+ private isDirectUrl;
22
+ assetPath(): string;
23
+ get hasOwnDuration(): boolean;
24
+ fetchImage: Task<readonly [string, typeof fetch], void>;
25
+ frameTask: Task<readonly [_lit_task0.TaskStatus], void>;
17
26
  }
18
27
  declare global {
19
- interface HTMLElementTagNameMap {
20
- "ef-image": EFImage;
21
- }
28
+ interface HTMLElementTagNameMap {
29
+ "ef-image": EFImage;
30
+ }
22
31
  }
23
- export {};
32
+ //#endregion
33
+ export { EFImage };
34
+ //# sourceMappingURL=EFImage.d.ts.map
@@ -7,7 +7,9 @@ import { Task } from "@lit/task";
7
7
  import { LitElement, css, html } from "lit";
8
8
  import { customElement, property } from "lit/decorators.js";
9
9
  import { createRef, ref } from "lit/directives/ref.js";
10
- var EFImage = class EFImage$1 extends EFTemporal(EFSourceMixin(FetchMixin(LitElement), { assetType: "image_files" })) {
10
+
11
+ //#region src/elements/EFImage.ts
12
+ let EFImage = class EFImage$1 extends EFTemporal(EFSourceMixin(FetchMixin(LitElement), { assetType: "image_files" })) {
11
13
  constructor(..._args) {
12
14
  super(..._args);
13
15
  this.imageRef = createRef();
@@ -85,4 +87,7 @@ __decorate([property({
85
87
  reflect: true
86
88
  })], EFImage.prototype, "assetId", null);
87
89
  EFImage = __decorate([customElement("ef-image")], EFImage);
90
+
91
+ //#endregion
88
92
  export { EFImage };
93
+ //# sourceMappingURL=EFImage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EFImage.js","names":["EFImage","#assetId"],"sources":["../../src/elements/EFImage.ts"],"sourcesContent":["import { Task } from \"@lit/task\";\nimport { css, html, LitElement } from \"lit\";\nimport { customElement, property } from \"lit/decorators.js\";\nimport { createRef, ref } from \"lit/directives/ref.js\";\nimport { EF_INTERACTIVE } from \"../EF_INTERACTIVE.js\";\nimport { EFSourceMixin } from \"./EFSourceMixin.js\";\nimport { EFTemporal } from \"./EFTemporal.js\";\nimport { FetchMixin } from \"./FetchMixin.js\";\n\n@customElement(\"ef-image\")\nexport class EFImage extends EFTemporal(\n EFSourceMixin(FetchMixin(LitElement), {\n assetType: \"image_files\",\n }),\n) {\n static styles = [\n css`\n :host {\n display: block;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n canvas, img {\n position: static;\n all: initial;\n width: 100%;\n height: 100%;\n }\n `,\n ];\n\n imageRef = createRef<HTMLImageElement>();\n canvasRef = createRef<HTMLCanvasElement>();\n\n #assetId: string | null = null;\n @property({ type: String, attribute: \"asset-id\", reflect: true })\n set assetId(value: string | null) {\n this.#assetId = value;\n }\n\n get assetId() {\n return this.#assetId ?? this.getAttribute(\"asset-id\");\n }\n\n render() {\n const assetPath = this.assetPath();\n const isDirectUrl = this.isDirectUrl(assetPath);\n return isDirectUrl\n ? html`<img ${ref(this.imageRef)} src=${assetPath} />`\n : html`<canvas ${ref(this.canvasRef)}></canvas>`;\n }\n\n private isDirectUrl(src: string): boolean {\n return src.startsWith(\"http://\") || src.startsWith(\"https://\");\n }\n\n assetPath() {\n if (this.assetId) {\n return `${this.apiHost}/api/v1/image_files/${this.assetId}`;\n }\n if (this.isDirectUrl(this.src)) {\n return this.src;\n }\n return `/@ef-image/${this.src}`;\n }\n\n get hasOwnDuration() {\n return this.hasExplicitDuration;\n }\n\n fetchImage = new Task(this, {\n autoRun: EF_INTERACTIVE,\n args: () => [this.assetPath(), this.fetch] as const,\n task: async ([assetPath, fetch], { signal }) => {\n // For direct URLs, skip task - src is set directly in render\n if (this.isDirectUrl(assetPath)) {\n return;\n }\n\n // For asset-id and local files, use canvas as before\n const response = await fetch(assetPath, { signal });\n const image = new Image();\n image.src = URL.createObjectURL(await response.blob());\n\n await new Promise((resolve, reject) => {\n image.onload = resolve;\n image.onerror = reject;\n });\n\n if (!this.canvasRef.value) throw new Error(\"Canvas not ready\");\n const ctx = this.canvasRef.value.getContext(\"2d\");\n if (!ctx) throw new Error(\"Canvas 2d context not ready\");\n this.canvasRef.value.width = image.width;\n this.canvasRef.value.height = image.height;\n ctx.drawImage(image, 0, 0);\n },\n });\n\n frameTask = new Task(this, {\n autoRun: EF_INTERACTIVE,\n args: () => [this.fetchImage.status] as const,\n task: async () => {\n await this.fetchImage.taskComplete;\n },\n });\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"ef-image\": EFImage;\n }\n}\n"],"mappings":";;;;;;;;;;;AAUO,oBAAMA,kBAAgB,WAC3B,cAAc,WAAW,WAAW,EAAE,EACpC,WAAW,eACZ,CAAC,CACH,CAAC;;;kBAkBW,WAA6B;mBAC5B,WAA8B;oBAsC7B,IAAI,KAAK,MAAM;GAC1B,SAAS;GACT,YAAY,CAAC,KAAK,WAAW,EAAE,KAAK,MAAM;GAC1C,MAAM,OAAO,CAAC,WAAW,QAAQ,EAAE,aAAa;AAE9C,QAAI,KAAK,YAAY,UAAU,CAC7B;IAIF,MAAM,WAAW,MAAM,MAAM,WAAW,EAAE,QAAQ,CAAC;IACnD,MAAM,QAAQ,IAAI,OAAO;AACzB,UAAM,MAAM,IAAI,gBAAgB,MAAM,SAAS,MAAM,CAAC;AAEtD,UAAM,IAAI,SAAS,SAAS,WAAW;AACrC,WAAM,SAAS;AACf,WAAM,UAAU;MAChB;AAEF,QAAI,CAAC,KAAK,UAAU,MAAO,OAAM,IAAI,MAAM,mBAAmB;IAC9D,MAAM,MAAM,KAAK,UAAU,MAAM,WAAW,KAAK;AACjD,QAAI,CAAC,IAAK,OAAM,IAAI,MAAM,8BAA8B;AACxD,SAAK,UAAU,MAAM,QAAQ,MAAM;AACnC,SAAK,UAAU,MAAM,SAAS,MAAM;AACpC,QAAI,UAAU,OAAO,GAAG,EAAE;;GAE7B,CAAC;mBAEU,IAAI,KAAK,MAAM;GACzB,SAAS;GACT,YAAY,CAAC,KAAK,WAAW,OAAO;GACpC,MAAM,YAAY;AAChB,UAAM,KAAK,WAAW;;GAEzB,CAAC;;;gBA1Fc,CACd,GAAG;;;;;;;;;;;;;MAcJ;;CAKD,WAA0B;CAC1B,IACI,QAAQ,OAAsB;AAChC,QAAKC,UAAW;;CAGlB,IAAI,UAAU;AACZ,SAAO,MAAKA,WAAY,KAAK,aAAa,WAAW;;CAGvD,SAAS;EACP,MAAM,YAAY,KAAK,WAAW;AAElC,SADoB,KAAK,YAAY,UAAU,GAE3C,IAAI,QAAQ,IAAI,KAAK,SAAS,CAAC,OAAO,UAAU,OAChD,IAAI,WAAW,IAAI,KAAK,UAAU,CAAC;;CAGzC,AAAQ,YAAY,KAAsB;AACxC,SAAO,IAAI,WAAW,UAAU,IAAI,IAAI,WAAW,WAAW;;CAGhE,YAAY;AACV,MAAI,KAAK,QACP,QAAO,GAAG,KAAK,QAAQ,sBAAsB,KAAK;AAEpD,MAAI,KAAK,YAAY,KAAK,IAAI,CAC5B,QAAO,KAAK;AAEd,SAAO,cAAc,KAAK;;CAG5B,IAAI,iBAAiB;AACnB,SAAO,KAAK;;;YAhCb,SAAS;CAAE,MAAM;CAAQ,WAAW;CAAY,SAAS;CAAM,CAAC;sBA3BlE,cAAc,WAAW"}
@@ -1,4 +1,6 @@
1
1
  import { AssetMediaEngine } from "./AssetMediaEngine.js";
2
+
3
+ //#region src/elements/EFMedia/AssetIdMediaEngine.ts
2
4
  var AssetIdMediaEngine = class AssetIdMediaEngine extends AssetMediaEngine {
3
5
  static async fetchByAssetId(host, _urlGenerator, assetId, apiHost) {
4
6
  const url = `${apiHost}/api/v1/isobmff_files/${assetId}/index`;
@@ -47,4 +49,7 @@ var AssetIdMediaEngine = class AssetIdMediaEngine extends AssetMediaEngine {
47
49
  return globalTimestamps.map((globalMs) => (globalMs - segmentStartMs) / 1e3);
48
50
  }
49
51
  };
52
+
53
+ //#endregion
50
54
  export { AssetIdMediaEngine };
55
+ //# sourceMappingURL=AssetIdMediaEngine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AssetIdMediaEngine.js","names":["assetId: string","apiHost: string","paths: InitSegmentPaths"],"sources":["../../../src/elements/EFMedia/AssetIdMediaEngine.ts"],"sourcesContent":["import type { TrackFragmentIndex } from \"@editframe/assets\";\nimport type {\n InitSegmentPaths,\n MediaEngine,\n VideoRendition,\n} from \"../../transcoding/types\";\nimport type { UrlGenerator } from \"../../transcoding/utils/UrlGenerator\";\nimport type { EFMedia } from \"../EFMedia\";\nimport { AssetMediaEngine } from \"./AssetMediaEngine\";\n\nexport class AssetIdMediaEngine\n extends AssetMediaEngine\n implements MediaEngine\n{\n static async fetchByAssetId(\n host: EFMedia,\n _urlGenerator: UrlGenerator,\n assetId: string,\n apiHost: string,\n ) {\n const url = `${apiHost}/api/v1/isobmff_files/${assetId}/index`;\n const response = await host.fetch(url);\n const data = (await response.json()) as Record<number, TrackFragmentIndex>;\n return new AssetIdMediaEngine(host, assetId, data, apiHost);\n }\n\n constructor(\n host: EFMedia,\n public assetId: string,\n data: Record<number, TrackFragmentIndex>,\n private apiHost: string,\n ) {\n // Pass assetId as src to parent constructor for compatibility\n super(host, assetId);\n // Initialize data after parent constructor\n this.data = data;\n\n // Calculate duration from the data\n const longestFragment = Object.values(this.data).reduce(\n (max, fragment) => Math.max(max, fragment.duration / fragment.timescale),\n 0,\n );\n this.durationMs = longestFragment * 1000;\n }\n\n // Override URL-building methods to use API endpoints instead of file paths\n get initSegmentPaths() {\n const paths: InitSegmentPaths = {};\n\n if (this.audioTrackIndex !== undefined) {\n paths.audio = {\n path: `${this.apiHost}/api/v1/isobmff_tracks/${this.assetId}/${this.audioTrackIndex.track}`,\n pos: this.audioTrackIndex.initSegment.offset,\n size: this.audioTrackIndex.initSegment.size,\n };\n }\n\n if (this.videoTrackIndex !== undefined) {\n paths.video = {\n path: `${this.apiHost}/api/v1/isobmff_tracks/${this.assetId}/${this.videoTrackIndex.track}`,\n pos: this.videoTrackIndex.initSegment.offset,\n size: this.videoTrackIndex.initSegment.size,\n };\n }\n\n return paths;\n }\n\n get templates() {\n return {\n initSegment: `${this.apiHost}/api/v1/isobmff_tracks/${this.assetId}/{trackId}`,\n mediaSegment: `${this.apiHost}/api/v1/isobmff_tracks/${this.assetId}/{trackId}`,\n };\n }\n\n buildInitSegmentUrl(trackId: number) {\n return `${this.apiHost}/api/v1/isobmff_tracks/${this.assetId}/${trackId}`;\n }\n\n buildMediaSegmentUrl(trackId: number, _segmentId: number) {\n return `${this.apiHost}/api/v1/isobmff_tracks/${this.assetId}/${trackId}`;\n }\n\n convertToSegmentRelativeTimestamps(\n globalTimestamps: number[],\n segmentId: number,\n rendition: VideoRendition,\n ): number[] {\n if (!rendition.trackId) {\n throw new Error(\n \"[convertToSegmentRelativeTimestamps] Track ID is required for asset metadata\",\n );\n }\n // For AssetMediaEngine, we need to calculate the actual segment start time\n // using the precise segment boundaries from the track fragment index\n const trackData = this.data[rendition.trackId];\n if (!trackData) {\n throw new Error(\"Track not found\");\n }\n const segment = trackData.segments?.[segmentId];\n if (!segment) {\n throw new Error(\"Segment not found\");\n }\n const segmentStartMs = (segment.cts / trackData.timescale) * 1000;\n\n return globalTimestamps.map(\n (globalMs) => (globalMs - segmentStartMs) / 1000,\n );\n }\n}\n"],"mappings":";;;AAUA,IAAa,qBAAb,MAAa,2BACH,iBAEV;CACE,aAAa,eACX,MACA,eACA,SACA,SACA;EACA,MAAM,MAAM,GAAG,QAAQ,wBAAwB,QAAQ;AAGvD,SAAO,IAAI,mBAAmB,MAAM,SADtB,OADG,MAAM,KAAK,MAAM,IAAI,EACT,MAAM,EACgB,QAAQ;;CAG7D,YACE,MACA,AAAOA,SACP,MACA,AAAQC,SACR;AAEA,QAAM,MAAM,QAAQ;EALb;EAEC;AAKR,OAAK,OAAO;AAOZ,OAAK,aAJmB,OAAO,OAAO,KAAK,KAAK,CAAC,QAC9C,KAAK,aAAa,KAAK,IAAI,KAAK,SAAS,WAAW,SAAS,UAAU,EACxE,EACD,GACmC;;CAItC,IAAI,mBAAmB;EACrB,MAAMC,QAA0B,EAAE;AAElC,MAAI,KAAK,oBAAoB,OAC3B,OAAM,QAAQ;GACZ,MAAM,GAAG,KAAK,QAAQ,yBAAyB,KAAK,QAAQ,GAAG,KAAK,gBAAgB;GACpF,KAAK,KAAK,gBAAgB,YAAY;GACtC,MAAM,KAAK,gBAAgB,YAAY;GACxC;AAGH,MAAI,KAAK,oBAAoB,OAC3B,OAAM,QAAQ;GACZ,MAAM,GAAG,KAAK,QAAQ,yBAAyB,KAAK,QAAQ,GAAG,KAAK,gBAAgB;GACpF,KAAK,KAAK,gBAAgB,YAAY;GACtC,MAAM,KAAK,gBAAgB,YAAY;GACxC;AAGH,SAAO;;CAGT,IAAI,YAAY;AACd,SAAO;GACL,aAAa,GAAG,KAAK,QAAQ,yBAAyB,KAAK,QAAQ;GACnE,cAAc,GAAG,KAAK,QAAQ,yBAAyB,KAAK,QAAQ;GACrE;;CAGH,oBAAoB,SAAiB;AACnC,SAAO,GAAG,KAAK,QAAQ,yBAAyB,KAAK,QAAQ,GAAG;;CAGlE,qBAAqB,SAAiB,YAAoB;AACxD,SAAO,GAAG,KAAK,QAAQ,yBAAyB,KAAK,QAAQ,GAAG;;CAGlE,mCACE,kBACA,WACA,WACU;AACV,MAAI,CAAC,UAAU,QACb,OAAM,IAAI,MACR,+EACD;EAIH,MAAM,YAAY,KAAK,KAAK,UAAU;AACtC,MAAI,CAAC,UACH,OAAM,IAAI,MAAM,kBAAkB;EAEpC,MAAM,UAAU,UAAU,WAAW;AACrC,MAAI,CAAC,QACH,OAAM,IAAI,MAAM,oBAAoB;EAEtC,MAAM,iBAAkB,QAAQ,MAAM,UAAU,YAAa;AAE7D,SAAO,iBAAiB,KACrB,cAAc,WAAW,kBAAkB,IAC7C"}
@@ -1,6 +1,8 @@
1
1
  import { withSpan } from "../../otel/tracingHelpers.js";
2
2
  import { BaseMediaEngine } from "./BaseMediaEngine.js";
3
3
  import { convertToScaledTime, roundToMilliseconds } from "./shared/PrecisionUtils.js";
4
+
5
+ //#region src/elements/EFMedia/AssetMediaEngine.ts
4
6
  var AssetMediaEngine = class AssetMediaEngine extends BaseMediaEngine {
5
7
  constructor(host, src) {
6
8
  super(host);
@@ -97,6 +99,9 @@ var AssetMediaEngine = class AssetMediaEngine extends BaseMediaEngine {
97
99
  return this.fetchMediaWithHeaders(url, headers, signal);
98
100
  });
99
101
  }
102
+ /**
103
+ * Calculate audio segments for variable-duration segments using track fragment index
104
+ */
100
105
  calculateAudioSegmentRange(fromMs, toMs, rendition, _durationMs) {
101
106
  if (fromMs >= toMs || !rendition.trackId) {
102
107
  console.warn(`calculateAudioSegmentRange: invalid fromMs ${fromMs} toMs ${toMs} rendition ${JSON.stringify(rendition)}`);
@@ -159,6 +164,10 @@ var AssetMediaEngine = class AssetMediaEngine extends BaseMediaEngine {
159
164
  return nearestSegmentIndex;
160
165
  }
161
166
  getScrubVideoRendition() {}
167
+ /**
168
+ * Get preferred buffer configuration for this media engine
169
+ * AssetMediaEngine uses lower buffering since segments are already optimized
170
+ */
162
171
  getBufferConfig() {
163
172
  return {
164
173
  videoBufferDurationMs: 2e3,
@@ -179,4 +188,7 @@ var AssetMediaEngine = class AssetMediaEngine extends BaseMediaEngine {
179
188
  }
180
189
  }
181
190
  };
191
+
192
+ //#endregion
182
193
  export { AssetMediaEngine };
194
+ //# sourceMappingURL=AssetMediaEngine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AssetMediaEngine.js","names":["paths: InitSegmentPaths","segmentRanges: SegmentTimeRange[]","distance: number"],"sources":["../../../src/elements/EFMedia/AssetMediaEngine.ts"],"sourcesContent":["import type { TrackFragmentIndex } from \"@editframe/assets\";\n\nimport { withSpan } from \"../../otel/tracingHelpers.js\";\nimport type {\n AudioRendition,\n InitSegmentPaths,\n MediaEngine,\n SegmentTimeRange,\n VideoRendition,\n} from \"../../transcoding/types\";\nimport type { UrlGenerator } from \"../../transcoding/utils/UrlGenerator\";\nimport type { EFMedia } from \"../EFMedia\";\nimport { BaseMediaEngine } from \"./BaseMediaEngine\";\nimport type { MediaRendition } from \"./shared/MediaTaskUtils\";\nimport {\n convertToScaledTime,\n roundToMilliseconds,\n} from \"./shared/PrecisionUtils\";\n\nexport class AssetMediaEngine extends BaseMediaEngine implements MediaEngine {\n public src: string;\n protected data: Record<number, TrackFragmentIndex> = {};\n durationMs = 0;\n\n constructor(host: EFMedia, src: string) {\n super(host);\n this.src = src;\n }\n\n static async fetch(host: EFMedia, urlGenerator: UrlGenerator, src: string) {\n const engine = new AssetMediaEngine(host, src);\n const url = urlGenerator.generateTrackFragmentIndexUrl(src);\n const data = await engine.fetchManifest(url);\n engine.data = data as Record<number, TrackFragmentIndex>;\n\n // Calculate duration from the data\n const longestFragment = Object.values(engine.data).reduce(\n (max, fragment) => Math.max(max, fragment.duration / fragment.timescale),\n 0,\n );\n engine.durationMs = longestFragment * 1000;\n\n if (src.startsWith(\"/\")) {\n engine.src = src.slice(1);\n }\n return engine;\n }\n\n get audioTrackIndex() {\n return Object.values(this.data).find((track) => track.type === \"audio\");\n }\n\n get videoTrackIndex() {\n return Object.values(this.data).find((track) => track.type === \"video\");\n }\n\n get videoRendition() {\n const videoTrack = this.videoTrackIndex;\n\n if (!videoTrack || videoTrack.track === undefined) {\n return undefined;\n }\n\n return {\n trackId: videoTrack.track,\n src: this.src,\n startTimeOffsetMs: videoTrack.startTimeOffsetMs,\n };\n }\n\n get audioRendition() {\n const audioTrack = this.audioTrackIndex;\n\n if (!audioTrack || audioTrack.track === undefined) {\n return undefined;\n }\n\n return {\n trackId: audioTrack.track,\n src: this.src,\n };\n }\n\n get initSegmentPaths() {\n const paths: InitSegmentPaths = {};\n\n if (this.audioTrackIndex !== undefined) {\n paths.audio = {\n path: `@ef-track/${this.audioTrackIndex.track}.m4s`,\n pos: this.audioTrackIndex.initSegment.offset,\n size: this.audioTrackIndex.initSegment.size,\n };\n }\n\n if (this.videoTrackIndex !== undefined) {\n paths.video = {\n path: `/@ef-track/${this.videoTrackIndex.track}.m4s`,\n pos: this.videoTrackIndex.initSegment.offset,\n size: this.videoTrackIndex.initSegment.size,\n };\n }\n\n return paths;\n }\n\n get templates() {\n return {\n initSegment: \"/@ef-track/{src}?trackId={trackId}\",\n mediaSegment: \"/@ef-track/{src}?trackId={trackId}\",\n };\n }\n\n buildInitSegmentUrl(trackId: number) {\n return `/@ef-track/${this.src}?trackId=${trackId}`;\n }\n\n buildMediaSegmentUrl(trackId: number, segmentId: number) {\n return `/@ef-track/${this.src}?trackId=${trackId}&segmentId=${segmentId}`;\n }\n\n async fetchInitSegment(\n rendition: { trackId: number | undefined; src: string },\n signal: AbortSignal,\n ) {\n return withSpan(\n \"assetEngine.fetchInitSegment\",\n {\n trackId: rendition.trackId || -1,\n src: rendition.src,\n },\n undefined,\n async (span) => {\n if (!rendition.trackId) {\n throw new Error(\n \"[fetchInitSegment] Track ID is required for asset metadata\",\n );\n }\n const url = this.buildInitSegmentUrl(rendition.trackId);\n const initSegment = this.data[rendition.trackId]?.initSegment;\n if (!initSegment) {\n throw new Error(\"Init segment not found\");\n }\n\n span.setAttribute(\"offset\", initSegment.offset);\n span.setAttribute(\"size\", initSegment.size);\n\n // Use unified fetch method with Range headers\n const headers = {\n Range: `bytes=${initSegment.offset}-${initSegment.offset + initSegment.size - 1}`,\n };\n\n return this.fetchMediaWithHeaders(url, headers, signal);\n },\n );\n }\n\n async fetchMediaSegment(\n segmentId: number,\n rendition: { trackId: number | undefined; src: string },\n signal?: AbortSignal,\n ) {\n return withSpan(\n \"assetEngine.fetchMediaSegment\",\n {\n segmentId,\n trackId: rendition.trackId || -1,\n src: rendition.src,\n },\n undefined,\n async (span) => {\n if (!rendition.trackId) {\n throw new Error(\n \"[fetchMediaSegment] Track ID is required for asset metadata\",\n );\n }\n if (segmentId === undefined) {\n throw new Error(\"Segment ID is not available\");\n }\n const url = this.buildMediaSegmentUrl(rendition.trackId, segmentId);\n const mediaSegment = this.data[rendition.trackId]?.segments[segmentId];\n if (!mediaSegment) {\n throw new Error(\"Media segment not found\");\n }\n\n span.setAttribute(\"offset\", mediaSegment.offset);\n span.setAttribute(\"size\", mediaSegment.size);\n\n // Use unified fetch method with Range headers\n const headers = {\n Range: `bytes=${mediaSegment.offset}-${mediaSegment.offset + mediaSegment.size - 1}`,\n };\n\n return this.fetchMediaWithHeaders(url, headers, signal);\n },\n );\n }\n\n /**\n * Calculate audio segments for variable-duration segments using track fragment index\n */\n calculateAudioSegmentRange(\n fromMs: number,\n toMs: number,\n rendition: AudioRendition,\n _durationMs: number,\n ): SegmentTimeRange[] {\n if (fromMs >= toMs || !rendition.trackId) {\n console.warn(\n `calculateAudioSegmentRange: invalid fromMs ${fromMs} toMs ${toMs} rendition ${JSON.stringify(\n rendition,\n )}`,\n );\n return [];\n }\n\n const track = this.data[rendition.trackId];\n if (!track) {\n console.warn(\n `calculateAudioSegmentRange: track not found for rendition ${JSON.stringify(\n rendition,\n )}`,\n );\n return [];\n }\n\n const { timescale, segments } = track;\n const segmentRanges: SegmentTimeRange[] = [];\n\n for (let i = 0; i < segments.length; i++) {\n // biome-ignore lint/style/noNonNullAssertion: we know the segment is not null\n const segment = segments[i]!;\n const segmentStartTime = segment.cts;\n const segmentEndTime = segment.cts + segment.duration;\n\n // Convert to milliseconds\n const segmentStartMs = (segmentStartTime / timescale) * 1000;\n const segmentEndMs = (segmentEndTime / timescale) * 1000;\n\n // Check if segment overlaps with requested time range\n if (segmentStartMs < toMs && segmentEndMs > fromMs) {\n segmentRanges.push({\n segmentId: i, // AssetMediaEngine uses 0-based segment IDs\n startMs: segmentStartMs,\n endMs: segmentEndMs,\n });\n }\n }\n if (segmentRanges.length === 0) {\n console.warn(\n `calculateAudioSegmentRange: no segments found for fromMs ${fromMs} toMs ${toMs} rendition ${JSON.stringify(\n {\n rendition,\n track,\n },\n )}`,\n );\n }\n\n return segmentRanges;\n }\n\n computeSegmentId(seekTimeMs: number, rendition: MediaRendition) {\n if (!rendition.trackId) {\n console.warn(\n `computeSegmentId: trackId not found for rendition ${JSON.stringify(\n rendition,\n )}`,\n );\n throw new Error(\n \"[computeSegmentId] Track ID is required for asset metadata\",\n );\n }\n const track = this.data[rendition.trackId];\n if (!track) {\n throw new Error(\"Track not found\");\n }\n const { timescale, segments } = track;\n\n // Apply startTimeOffsetMs to map user timeline to media timeline for segment selection\n const startTimeOffsetMs =\n (\"startTimeOffsetMs\" in rendition && rendition.startTimeOffsetMs) || 0;\n\n const offsetSeekTimeMs = roundToMilliseconds(\n seekTimeMs + startTimeOffsetMs,\n );\n // Convert to timescale units using consistent precision\n const scaledSeekTime = convertToScaledTime(offsetSeekTimeMs, timescale);\n\n // Find the segment that contains the actual seek time\n for (let i = segments.length - 1; i >= 0; i--) {\n // biome-ignore lint/style/noNonNullAssertion: we know the segment is not null\n const segment = segments[i]!;\n const segmentEndTime = segment.cts + segment.duration;\n\n // Check if the seek time falls within this segment\n if (segment.cts <= scaledSeekTime && scaledSeekTime < segmentEndTime) {\n return i;\n }\n }\n\n // Handle gaps: if no exact segment contains the time, find the nearest one\n // This handles cases where seek time falls between segments (like 8041.667ms)\n let nearestSegmentIndex = 0;\n let nearestDistance = Number.MAX_SAFE_INTEGER;\n\n for (let i = 0; i < segments.length; i++) {\n // biome-ignore lint/style/noNonNullAssertion: we know the segment is not null\n const segment = segments[i]!;\n const segmentStartTime = segment.cts;\n const segmentEndTime = segment.cts + segment.duration;\n\n let distance: number;\n if (scaledSeekTime < segmentStartTime) {\n // Time is before this segment\n distance = segmentStartTime - scaledSeekTime;\n } else if (scaledSeekTime >= segmentEndTime) {\n // Time is after this segment\n distance = scaledSeekTime - segmentEndTime;\n } else {\n // Time is within this segment (should have been caught above, but just in case)\n return i;\n }\n\n if (distance < nearestDistance) {\n nearestDistance = distance;\n nearestSegmentIndex = i;\n }\n }\n\n return nearestSegmentIndex;\n }\n\n getScrubVideoRendition(): VideoRendition | undefined {\n // AssetMediaEngine does not have a dedicated scrub track\n return undefined;\n }\n\n /**\n * Get preferred buffer configuration for this media engine\n * AssetMediaEngine uses lower buffering since segments are already optimized\n */\n getBufferConfig() {\n return {\n // Buffer just 1 segment ahead (~2 seconds) for assets\n videoBufferDurationMs: 2000,\n audioBufferDurationMs: 2000,\n maxVideoBufferFetches: 1,\n maxAudioBufferFetches: 1,\n };\n }\n\n // AssetMediaEngine inherits the default extractThumbnails from BaseMediaEngine\n // which provides a clear warning that this engine type is not supported\n\n convertToSegmentRelativeTimestamps(\n globalTimestamps: number[],\n segmentId: number,\n rendition: VideoRendition,\n ): number[] {\n {\n // Asset: MediaBunny expects segment-relative timestamps in seconds\n // This is because Asset segments are independent timeline fragments\n\n if (!rendition.trackId) {\n throw new Error(\"Track ID is required for asset metadata\");\n }\n // For AssetMediaEngine, we need to calculate the actual segment start time\n // using the precise segment boundaries from the track fragment index\n const trackData = this.data[rendition.trackId];\n if (!trackData) {\n throw new Error(\"Track not found\");\n }\n const segment = trackData.segments?.[segmentId];\n if (!segment) {\n throw new Error(\"Segment not found\");\n }\n const segmentStartMs = (segment.cts / trackData.timescale) * 1000;\n\n return globalTimestamps.map(\n (globalMs) => (globalMs - segmentStartMs) / 1000,\n );\n }\n }\n}\n"],"mappings":";;;;;AAmBA,IAAa,mBAAb,MAAa,yBAAyB,gBAAuC;CAK3E,YAAY,MAAe,KAAa;AACtC,QAAM,KAAK;cAJwC,EAAE;oBAC1C;AAIX,OAAK,MAAM;;CAGb,aAAa,MAAM,MAAe,cAA4B,KAAa;EACzE,MAAM,SAAS,IAAI,iBAAiB,MAAM,IAAI;EAC9C,MAAM,MAAM,aAAa,8BAA8B,IAAI;AAE3D,SAAO,OADM,MAAM,OAAO,cAAc,IAAI;AAQ5C,SAAO,aAJiB,OAAO,OAAO,OAAO,KAAK,CAAC,QAChD,KAAK,aAAa,KAAK,IAAI,KAAK,SAAS,WAAW,SAAS,UAAU,EACxE,EACD,GACqC;AAEtC,MAAI,IAAI,WAAW,IAAI,CACrB,QAAO,MAAM,IAAI,MAAM,EAAE;AAE3B,SAAO;;CAGT,IAAI,kBAAkB;AACpB,SAAO,OAAO,OAAO,KAAK,KAAK,CAAC,MAAM,UAAU,MAAM,SAAS,QAAQ;;CAGzE,IAAI,kBAAkB;AACpB,SAAO,OAAO,OAAO,KAAK,KAAK,CAAC,MAAM,UAAU,MAAM,SAAS,QAAQ;;CAGzE,IAAI,iBAAiB;EACnB,MAAM,aAAa,KAAK;AAExB,MAAI,CAAC,cAAc,WAAW,UAAU,OACtC;AAGF,SAAO;GACL,SAAS,WAAW;GACpB,KAAK,KAAK;GACV,mBAAmB,WAAW;GAC/B;;CAGH,IAAI,iBAAiB;EACnB,MAAM,aAAa,KAAK;AAExB,MAAI,CAAC,cAAc,WAAW,UAAU,OACtC;AAGF,SAAO;GACL,SAAS,WAAW;GACpB,KAAK,KAAK;GACX;;CAGH,IAAI,mBAAmB;EACrB,MAAMA,QAA0B,EAAE;AAElC,MAAI,KAAK,oBAAoB,OAC3B,OAAM,QAAQ;GACZ,MAAM,aAAa,KAAK,gBAAgB,MAAM;GAC9C,KAAK,KAAK,gBAAgB,YAAY;GACtC,MAAM,KAAK,gBAAgB,YAAY;GACxC;AAGH,MAAI,KAAK,oBAAoB,OAC3B,OAAM,QAAQ;GACZ,MAAM,cAAc,KAAK,gBAAgB,MAAM;GAC/C,KAAK,KAAK,gBAAgB,YAAY;GACtC,MAAM,KAAK,gBAAgB,YAAY;GACxC;AAGH,SAAO;;CAGT,IAAI,YAAY;AACd,SAAO;GACL,aAAa;GACb,cAAc;GACf;;CAGH,oBAAoB,SAAiB;AACnC,SAAO,cAAc,KAAK,IAAI,WAAW;;CAG3C,qBAAqB,SAAiB,WAAmB;AACvD,SAAO,cAAc,KAAK,IAAI,WAAW,QAAQ,aAAa;;CAGhE,MAAM,iBACJ,WACA,QACA;AACA,SAAO,SACL,gCACA;GACE,SAAS,UAAU,WAAW;GAC9B,KAAK,UAAU;GAChB,EACD,QACA,OAAO,SAAS;AACd,OAAI,CAAC,UAAU,QACb,OAAM,IAAI,MACR,6DACD;GAEH,MAAM,MAAM,KAAK,oBAAoB,UAAU,QAAQ;GACvD,MAAM,cAAc,KAAK,KAAK,UAAU,UAAU;AAClD,OAAI,CAAC,YACH,OAAM,IAAI,MAAM,yBAAyB;AAG3C,QAAK,aAAa,UAAU,YAAY,OAAO;AAC/C,QAAK,aAAa,QAAQ,YAAY,KAAK;GAG3C,MAAM,UAAU,EACd,OAAO,SAAS,YAAY,OAAO,GAAG,YAAY,SAAS,YAAY,OAAO,KAC/E;AAED,UAAO,KAAK,sBAAsB,KAAK,SAAS,OAAO;IAE1D;;CAGH,MAAM,kBACJ,WACA,WACA,QACA;AACA,SAAO,SACL,iCACA;GACE;GACA,SAAS,UAAU,WAAW;GAC9B,KAAK,UAAU;GAChB,EACD,QACA,OAAO,SAAS;AACd,OAAI,CAAC,UAAU,QACb,OAAM,IAAI,MACR,8DACD;AAEH,OAAI,cAAc,OAChB,OAAM,IAAI,MAAM,8BAA8B;GAEhD,MAAM,MAAM,KAAK,qBAAqB,UAAU,SAAS,UAAU;GACnE,MAAM,eAAe,KAAK,KAAK,UAAU,UAAU,SAAS;AAC5D,OAAI,CAAC,aACH,OAAM,IAAI,MAAM,0BAA0B;AAG5C,QAAK,aAAa,UAAU,aAAa,OAAO;AAChD,QAAK,aAAa,QAAQ,aAAa,KAAK;GAG5C,MAAM,UAAU,EACd,OAAO,SAAS,aAAa,OAAO,GAAG,aAAa,SAAS,aAAa,OAAO,KAClF;AAED,UAAO,KAAK,sBAAsB,KAAK,SAAS,OAAO;IAE1D;;;;;CAMH,2BACE,QACA,MACA,WACA,aACoB;AACpB,MAAI,UAAU,QAAQ,CAAC,UAAU,SAAS;AACxC,WAAQ,KACN,8CAA8C,OAAO,QAAQ,KAAK,aAAa,KAAK,UAClF,UACD,GACF;AACD,UAAO,EAAE;;EAGX,MAAM,QAAQ,KAAK,KAAK,UAAU;AAClC,MAAI,CAAC,OAAO;AACV,WAAQ,KACN,6DAA6D,KAAK,UAChE,UACD,GACF;AACD,UAAO,EAAE;;EAGX,MAAM,EAAE,WAAW,aAAa;EAChC,MAAMC,gBAAoC,EAAE;AAE5C,OAAK,IAAI,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;GAExC,MAAM,UAAU,SAAS;GACzB,MAAM,mBAAmB,QAAQ;GACjC,MAAM,iBAAiB,QAAQ,MAAM,QAAQ;GAG7C,MAAM,iBAAkB,mBAAmB,YAAa;GACxD,MAAM,eAAgB,iBAAiB,YAAa;AAGpD,OAAI,iBAAiB,QAAQ,eAAe,OAC1C,eAAc,KAAK;IACjB,WAAW;IACX,SAAS;IACT,OAAO;IACR,CAAC;;AAGN,MAAI,cAAc,WAAW,EAC3B,SAAQ,KACN,4DAA4D,OAAO,QAAQ,KAAK,aAAa,KAAK,UAChG;GACE;GACA;GACD,CACF,GACF;AAGH,SAAO;;CAGT,iBAAiB,YAAoB,WAA2B;AAC9D,MAAI,CAAC,UAAU,SAAS;AACtB,WAAQ,KACN,qDAAqD,KAAK,UACxD,UACD,GACF;AACD,SAAM,IAAI,MACR,6DACD;;EAEH,MAAM,QAAQ,KAAK,KAAK,UAAU;AAClC,MAAI,CAAC,MACH,OAAM,IAAI,MAAM,kBAAkB;EAEpC,MAAM,EAAE,WAAW,aAAa;EAUhC,MAAM,iBAAiB,oBAJE,oBACvB,cAHC,uBAAuB,aAAa,UAAU,qBAAsB,GAItE,EAE4D,UAAU;AAGvE,OAAK,IAAI,IAAI,SAAS,SAAS,GAAG,KAAK,GAAG,KAAK;GAE7C,MAAM,UAAU,SAAS;GACzB,MAAM,iBAAiB,QAAQ,MAAM,QAAQ;AAG7C,OAAI,QAAQ,OAAO,kBAAkB,iBAAiB,eACpD,QAAO;;EAMX,IAAI,sBAAsB;EAC1B,IAAI,kBAAkB,OAAO;AAE7B,OAAK,IAAI,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;GAExC,MAAM,UAAU,SAAS;GACzB,MAAM,mBAAmB,QAAQ;GACjC,MAAM,iBAAiB,QAAQ,MAAM,QAAQ;GAE7C,IAAIC;AACJ,OAAI,iBAAiB,iBAEnB,YAAW,mBAAmB;YACrB,kBAAkB,eAE3B,YAAW,iBAAiB;OAG5B,QAAO;AAGT,OAAI,WAAW,iBAAiB;AAC9B,sBAAkB;AAClB,0BAAsB;;;AAI1B,SAAO;;CAGT,yBAAqD;;;;;CASrD,kBAAkB;AAChB,SAAO;GAEL,uBAAuB;GACvB,uBAAuB;GACvB,uBAAuB;GACvB,uBAAuB;GACxB;;CAMH,mCACE,kBACA,WACA,WACU;EACV;AAIE,OAAI,CAAC,UAAU,QACb,OAAM,IAAI,MAAM,0CAA0C;GAI5D,MAAM,YAAY,KAAK,KAAK,UAAU;AACtC,OAAI,CAAC,UACH,OAAM,IAAI,MAAM,kBAAkB;GAEpC,MAAM,UAAU,UAAU,WAAW;AACrC,OAAI,CAAC,QACH,OAAM,IAAI,MAAM,oBAAoB;GAEtC,MAAM,iBAAkB,QAAQ,MAAM,UAAU,YAAa;AAE7D,UAAO,iBAAiB,KACrB,cAAc,WAAW,kBAAkB,IAC7C"}