@editframe/elements 0.16.8-beta.0 → 0.18.3-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -0
- package/dist/DecoderResetFrequency.test.d.ts +1 -0
- package/dist/DecoderResetRecovery.test.d.ts +1 -0
- package/dist/DelayedLoadingState.d.ts +48 -0
- package/dist/DelayedLoadingState.integration.test.d.ts +1 -0
- package/dist/DelayedLoadingState.js +113 -0
- package/dist/DelayedLoadingState.test.d.ts +1 -0
- package/dist/EF_FRAMEGEN.d.ts +10 -1
- package/dist/EF_FRAMEGEN.js +199 -179
- package/dist/EF_INTERACTIVE.js +2 -6
- package/dist/EF_RENDERING.js +1 -3
- package/dist/LoadingDebounce.test.d.ts +1 -0
- package/dist/LoadingIndicator.browsertest.d.ts +0 -0
- package/dist/ManualScrubTest.test.d.ts +1 -0
- package/dist/ScrubResolvedFlashing.test.d.ts +1 -0
- package/dist/ScrubTrackManager.d.ts +96 -0
- package/dist/ScrubTrackManager.test.d.ts +1 -0
- package/dist/VideoSeekFlashing.browsertest.d.ts +0 -0
- package/dist/VideoStuckDiagnostic.test.d.ts +1 -0
- package/dist/elements/CrossUpdateController.js +13 -15
- package/dist/elements/EFAudio.browsertest.d.ts +0 -0
- package/dist/elements/EFAudio.d.ts +22 -3
- package/dist/elements/EFAudio.js +60 -43
- package/dist/elements/EFCaptions.js +337 -373
- package/dist/elements/EFImage.d.ts +1 -0
- package/dist/elements/EFImage.js +73 -91
- package/dist/elements/EFMedia/AssetIdMediaEngine.d.ts +18 -0
- package/dist/elements/EFMedia/AssetIdMediaEngine.js +41 -0
- package/dist/elements/EFMedia/AssetIdMediaEngine.test.d.ts +1 -0
- package/dist/elements/EFMedia/AssetMediaEngine.d.ts +47 -0
- package/dist/elements/EFMedia/AssetMediaEngine.js +116 -0
- package/dist/elements/EFMedia/BaseMediaEngine.d.ts +55 -0
- package/dist/elements/EFMedia/BaseMediaEngine.js +96 -0
- package/dist/elements/EFMedia/BaseMediaEngine.test.d.ts +1 -0
- package/dist/elements/EFMedia/BufferedSeekingInput.browsertest.d.ts +1 -0
- package/dist/elements/EFMedia/BufferedSeekingInput.d.ts +43 -0
- package/dist/elements/EFMedia/BufferedSeekingInput.js +159 -0
- package/dist/elements/EFMedia/JitMediaEngine.browsertest.d.ts +0 -0
- package/dist/elements/EFMedia/JitMediaEngine.d.ts +31 -0
- package/dist/elements/EFMedia/JitMediaEngine.js +62 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioBufferTask.browsertest.d.ts +9 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioBufferTask.d.ts +16 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioBufferTask.js +48 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioFrequencyAnalysisTask.d.ts +3 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioFrequencyAnalysisTask.js +138 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioInitSegmentFetchTask.browsertest.d.ts +9 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioInitSegmentFetchTask.d.ts +4 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioInitSegmentFetchTask.js +16 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioInputTask.browsertest.d.ts +9 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioInputTask.d.ts +3 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioInputTask.js +22 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioSeekTask.d.ts +7 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioSeekTask.js +24 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioSegmentFetchTask.d.ts +4 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioSegmentFetchTask.js +18 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioSegmentIdTask.d.ts +4 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioSegmentIdTask.js +16 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.d.ts +3 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.js +104 -0
- package/dist/elements/EFMedia/services/AudioElementFactory.browsertest.d.ts +1 -0
- package/dist/elements/EFMedia/services/AudioElementFactory.d.ts +22 -0
- package/dist/elements/EFMedia/services/AudioElementFactory.js +72 -0
- package/dist/elements/EFMedia/services/MediaSourceService.browsertest.d.ts +1 -0
- package/dist/elements/EFMedia/services/MediaSourceService.d.ts +47 -0
- package/dist/elements/EFMedia/services/MediaSourceService.js +73 -0
- package/dist/elements/EFMedia/shared/AudioSpanUtils.d.ts +7 -0
- package/dist/elements/EFMedia/shared/AudioSpanUtils.js +54 -0
- package/dist/elements/EFMedia/shared/BufferUtils.d.ts +70 -0
- package/dist/elements/EFMedia/shared/BufferUtils.js +89 -0
- package/dist/elements/EFMedia/shared/MediaTaskUtils.d.ts +23 -0
- package/dist/elements/EFMedia/shared/RenditionHelpers.browsertest.d.ts +1 -0
- package/dist/elements/EFMedia/shared/RenditionHelpers.d.ts +19 -0
- package/dist/elements/EFMedia/tasks/makeMediaEngineTask.browsertest.d.ts +1 -0
- package/dist/elements/EFMedia/tasks/makeMediaEngineTask.d.ts +18 -0
- package/dist/elements/EFMedia/tasks/makeMediaEngineTask.js +60 -0
- package/dist/elements/EFMedia/tasks/makeMediaEngineTask.test.d.ts +1 -0
- package/dist/elements/EFMedia/videoTasks/makeVideoBufferTask.browsertest.d.ts +9 -0
- package/dist/elements/EFMedia/videoTasks/makeVideoBufferTask.d.ts +16 -0
- package/dist/elements/EFMedia/videoTasks/makeVideoBufferTask.js +46 -0
- package/dist/elements/EFMedia/videoTasks/makeVideoInitSegmentFetchTask.browsertest.d.ts +9 -0
- package/dist/elements/EFMedia/videoTasks/makeVideoInitSegmentFetchTask.d.ts +4 -0
- package/dist/elements/EFMedia/videoTasks/makeVideoInitSegmentFetchTask.js +16 -0
- package/dist/elements/EFMedia/videoTasks/makeVideoInputTask.browsertest.d.ts +9 -0
- package/dist/elements/EFMedia/videoTasks/makeVideoInputTask.d.ts +3 -0
- package/dist/elements/EFMedia/videoTasks/makeVideoInputTask.js +27 -0
- package/dist/elements/EFMedia/videoTasks/makeVideoSeekTask.d.ts +7 -0
- package/dist/elements/EFMedia/videoTasks/makeVideoSeekTask.js +25 -0
- package/dist/elements/EFMedia/videoTasks/makeVideoSegmentFetchTask.browsertest.d.ts +9 -0
- package/dist/elements/EFMedia/videoTasks/makeVideoSegmentFetchTask.d.ts +4 -0
- package/dist/elements/EFMedia/videoTasks/makeVideoSegmentFetchTask.js +18 -0
- package/dist/elements/EFMedia/videoTasks/makeVideoSegmentIdTask.browsertest.d.ts +9 -0
- package/dist/elements/EFMedia/videoTasks/makeVideoSegmentIdTask.d.ts +4 -0
- package/dist/elements/EFMedia/videoTasks/makeVideoSegmentIdTask.js +16 -0
- package/dist/elements/EFMedia.browsertest.d.ts +1 -0
- package/dist/elements/EFMedia.d.ts +95 -66
- package/dist/elements/EFMedia.js +204 -683
- package/dist/elements/EFSourceMixin.js +31 -48
- package/dist/elements/EFTemporal.d.ts +2 -1
- package/dist/elements/EFTemporal.js +266 -360
- package/dist/elements/EFTimegroup.d.ts +14 -1
- package/dist/elements/EFTimegroup.js +337 -323
- package/dist/elements/EFVideo.browsertest.d.ts +0 -0
- package/dist/elements/EFVideo.d.ts +123 -4
- package/dist/elements/EFVideo.js +308 -111
- package/dist/elements/EFWaveform.js +375 -411
- package/dist/elements/FetchMixin.js +14 -24
- package/dist/elements/MediaController.d.ts +30 -0
- package/dist/elements/SampleBuffer.d.ts +14 -0
- package/dist/elements/SampleBuffer.js +52 -0
- package/dist/elements/TargetController.js +130 -156
- package/dist/elements/TimegroupController.js +17 -19
- package/dist/elements/durationConverter.js +15 -4
- package/dist/elements/parseTimeToMs.js +4 -10
- package/dist/elements/printTaskStatus.d.ts +2 -0
- package/dist/elements/updateAnimations.js +39 -59
- package/dist/getRenderInfo.d.ts +2 -2
- package/dist/getRenderInfo.js +59 -67
- package/dist/gui/ContextMixin.js +150 -288
- package/dist/gui/EFConfiguration.js +27 -43
- package/dist/gui/EFFilmstrip.d.ts +3 -3
- package/dist/gui/EFFilmstrip.js +440 -620
- package/dist/gui/EFFitScale.d.ts +2 -2
- package/dist/gui/EFFitScale.js +112 -135
- package/dist/gui/EFFocusOverlay.js +45 -61
- package/dist/gui/EFPreview.js +30 -49
- package/dist/gui/EFScrubber.js +78 -99
- package/dist/gui/EFTimeDisplay.js +49 -70
- package/dist/gui/EFToggleLoop.js +17 -34
- package/dist/gui/EFTogglePlay.js +37 -58
- package/dist/gui/EFWorkbench.js +66 -88
- package/dist/gui/TWMixin.js +2 -48
- package/dist/gui/TWMixin2.js +31 -0
- package/dist/gui/efContext.js +2 -6
- package/dist/gui/fetchContext.js +1 -3
- package/dist/gui/focusContext.js +1 -3
- package/dist/gui/focusedElementContext.js +2 -6
- package/dist/gui/playingContext.js +1 -4
- package/dist/gui/services/ElementConnectionManager.browsertest.d.ts +1 -0
- package/dist/gui/services/ElementConnectionManager.d.ts +59 -0
- package/dist/gui/services/ElementConnectionManager.js +128 -0
- package/dist/gui/services/PlaybackController.browsertest.d.ts +1 -0
- package/dist/gui/services/PlaybackController.d.ts +103 -0
- package/dist/gui/services/PlaybackController.js +290 -0
- package/dist/index.js +5 -30
- package/dist/msToTimeCode.js +11 -13
- package/dist/services/MediaSourceManager.d.ts +62 -0
- package/dist/services/MediaSourceManager.js +211 -0
- package/dist/style.css +2 -1
- package/dist/transcoding/cache/CacheManager.d.ts +73 -0
- package/dist/transcoding/cache/RequestDeduplicator.d.ts +29 -0
- package/dist/transcoding/cache/RequestDeduplicator.js +53 -0
- package/dist/transcoding/cache/RequestDeduplicator.test.d.ts +1 -0
- package/dist/transcoding/types/index.d.ts +242 -0
- package/dist/transcoding/utils/MediaUtils.d.ts +9 -0
- package/dist/transcoding/utils/UrlGenerator.d.ts +26 -0
- package/dist/transcoding/utils/UrlGenerator.js +45 -0
- package/dist/transcoding/utils/constants.d.ts +27 -0
- package/dist/utils/LRUCache.d.ts +34 -0
- package/dist/utils/LRUCache.js +115 -0
- package/package.json +4 -3
- package/src/elements/EFAudio.browsertest.ts +709 -0
- package/src/elements/EFAudio.ts +59 -15
- package/src/elements/EFCaptions.browsertest.ts +0 -1
- package/src/elements/EFImage.browsertest.ts +42 -1
- package/src/elements/EFImage.ts +23 -3
- package/src/elements/EFMedia/AssetIdMediaEngine.test.ts +222 -0
- package/src/elements/EFMedia/AssetIdMediaEngine.ts +70 -0
- package/src/elements/EFMedia/AssetMediaEngine.ts +210 -0
- package/src/elements/EFMedia/BaseMediaEngine.test.ts +164 -0
- package/src/elements/EFMedia/BaseMediaEngine.ts +170 -0
- package/src/elements/EFMedia/BufferedSeekingInput.browsertest.ts +400 -0
- package/src/elements/EFMedia/BufferedSeekingInput.ts +267 -0
- package/src/elements/EFMedia/JitMediaEngine.browsertest.ts +165 -0
- package/src/elements/EFMedia/JitMediaEngine.ts +110 -0
- package/src/elements/EFMedia/audioTasks/makeAudioBufferTask.browsertest.ts +554 -0
- package/src/elements/EFMedia/audioTasks/makeAudioBufferTask.ts +81 -0
- package/src/elements/EFMedia/audioTasks/makeAudioFrequencyAnalysisTask.ts +241 -0
- package/src/elements/EFMedia/audioTasks/makeAudioInitSegmentFetchTask.browsertest.ts +59 -0
- package/src/elements/EFMedia/audioTasks/makeAudioInitSegmentFetchTask.ts +23 -0
- package/src/elements/EFMedia/audioTasks/makeAudioInputTask.browsertest.ts +55 -0
- package/src/elements/EFMedia/audioTasks/makeAudioInputTask.ts +35 -0
- package/src/elements/EFMedia/audioTasks/makeAudioSeekTask.ts +42 -0
- package/src/elements/EFMedia/audioTasks/makeAudioSegmentFetchTask.ts +34 -0
- package/src/elements/EFMedia/audioTasks/makeAudioSegmentIdTask.ts +23 -0
- package/src/elements/EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.ts +174 -0
- package/src/elements/EFMedia/services/AudioElementFactory.browsertest.ts +325 -0
- package/src/elements/EFMedia/services/AudioElementFactory.ts +119 -0
- package/src/elements/EFMedia/services/MediaSourceService.browsertest.ts +257 -0
- package/src/elements/EFMedia/services/MediaSourceService.ts +102 -0
- package/src/elements/EFMedia/shared/AudioSpanUtils.ts +128 -0
- package/src/elements/EFMedia/shared/BufferUtils.ts +310 -0
- package/src/elements/EFMedia/shared/MediaTaskUtils.ts +44 -0
- package/src/elements/EFMedia/shared/RenditionHelpers.browsertest.ts +247 -0
- package/src/elements/EFMedia/shared/RenditionHelpers.ts +79 -0
- package/src/elements/EFMedia/tasks/makeMediaEngineTask.browsertest.ts +128 -0
- package/src/elements/EFMedia/tasks/makeMediaEngineTask.test.ts +233 -0
- package/src/elements/EFMedia/tasks/makeMediaEngineTask.ts +89 -0
- package/src/elements/EFMedia/videoTasks/makeVideoBufferTask.browsertest.ts +555 -0
- package/src/elements/EFMedia/videoTasks/makeVideoBufferTask.ts +79 -0
- package/src/elements/EFMedia/videoTasks/makeVideoInitSegmentFetchTask.browsertest.ts +59 -0
- package/src/elements/EFMedia/videoTasks/makeVideoInitSegmentFetchTask.ts +23 -0
- package/src/elements/EFMedia/videoTasks/makeVideoInputTask.browsertest.ts +55 -0
- package/src/elements/EFMedia/videoTasks/makeVideoInputTask.ts +45 -0
- package/src/elements/EFMedia/videoTasks/makeVideoSeekTask.ts +44 -0
- package/src/elements/EFMedia/videoTasks/makeVideoSegmentFetchTask.browsertest.ts +57 -0
- package/src/elements/EFMedia/videoTasks/makeVideoSegmentFetchTask.ts +32 -0
- package/src/elements/EFMedia/videoTasks/makeVideoSegmentIdTask.browsertest.ts +56 -0
- package/src/elements/EFMedia/videoTasks/makeVideoSegmentIdTask.ts +23 -0
- package/src/elements/EFMedia.browsertest.ts +696 -271
- package/src/elements/EFMedia.ts +218 -776
- package/src/elements/EFTemporal.browsertest.ts +0 -1
- package/src/elements/EFTemporal.ts +13 -3
- package/src/elements/EFTimegroup.browsertest.ts +6 -3
- package/src/elements/EFTimegroup.ts +221 -27
- package/src/elements/EFVideo.browsertest.ts +758 -0
- package/src/elements/EFVideo.ts +418 -68
- package/src/elements/EFWaveform.ts +5 -5
- package/src/elements/MediaController.ts +98 -0
- package/src/elements/SampleBuffer.ts +97 -0
- package/src/elements/printTaskStatus.ts +16 -0
- package/src/elements/updateAnimations.ts +6 -0
- package/src/gui/ContextMixin.ts +23 -104
- package/src/gui/TWMixin.ts +10 -3
- package/src/gui/services/ElementConnectionManager.browsertest.ts +263 -0
- package/src/gui/services/ElementConnectionManager.ts +224 -0
- package/src/gui/services/PlaybackController.browsertest.ts +437 -0
- package/src/gui/services/PlaybackController.ts +521 -0
- package/src/services/MediaSourceManager.ts +333 -0
- package/src/transcoding/cache/CacheManager.ts +208 -0
- package/src/transcoding/cache/RequestDeduplicator.test.ts +170 -0
- package/src/transcoding/cache/RequestDeduplicator.ts +65 -0
- package/src/transcoding/types/index.ts +265 -0
- package/src/transcoding/utils/MediaUtils.ts +63 -0
- package/src/transcoding/utils/UrlGenerator.ts +68 -0
- package/src/transcoding/utils/constants.ts +36 -0
- package/src/utils/LRUCache.ts +153 -0
- package/test/EFVideo.framegen.browsertest.ts +127 -0
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- package/test/__cache__/GET__api_v1_transcode_manifest_json_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__3be92a0437de726b431ed5af2369158a/data.bin +1 -0
- package/test/__cache__/GET__api_v1_transcode_manifest_json_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__3be92a0437de726b431ed5af2369158a/metadata.json +19 -0
- package/test/createJitTestClips.ts +425 -0
- package/test/recordReplayProxyPlugin.js +302 -0
- package/test/useAssetMSW.ts +49 -0
- package/test/useMSW.ts +44 -0
- package/types.json +1 -1
- package/dist/gui/TWMixin.css.js +0 -4
- /package/dist/elements/{TargetController.test.d.ts → TargetController.browsertest.d.ts} +0 -0
- /package/src/elements/{TargetController.test.ts → TargetController.browsertest.ts} +0 -0
package/src/elements/EFVideo.ts
CHANGED
|
@@ -1,13 +1,45 @@
|
|
|
1
1
|
import { Task } from "@lit/task";
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
2
|
+
import debug from "debug";
|
|
3
|
+
import { css, html, type PropertyValueMap } from "lit";
|
|
4
|
+
import { customElement, property, state } from "lit/decorators.js";
|
|
4
5
|
import { createRef, ref } from "lit/directives/ref.js";
|
|
5
6
|
|
|
7
|
+
import { DelayedLoadingState } from "../DelayedLoadingState.js";
|
|
6
8
|
import { TWMixin } from "../gui/TWMixin.js";
|
|
9
|
+
import type { CacheStats, ScrubTrackManager } from "../ScrubTrackManager.js";
|
|
10
|
+
import { makeVideoBufferTask } from "./EFMedia/videoTasks/makeVideoBufferTask.ts";
|
|
11
|
+
import { makeVideoInitSegmentFetchTask } from "./EFMedia/videoTasks/makeVideoInitSegmentFetchTask.ts";
|
|
12
|
+
import { makeVideoInputTask } from "./EFMedia/videoTasks/makeVideoInputTask.ts";
|
|
13
|
+
import { makeVideoSeekTask } from "./EFMedia/videoTasks/makeVideoSeekTask.ts";
|
|
14
|
+
import { makeVideoSegmentFetchTask } from "./EFMedia/videoTasks/makeVideoSegmentFetchTask.ts";
|
|
15
|
+
import { makeVideoSegmentIdTask } from "./EFMedia/videoTasks/makeVideoSegmentIdTask.ts";
|
|
7
16
|
import { EFMedia } from "./EFMedia.js";
|
|
8
17
|
|
|
18
|
+
// EF_FRAMEGEN is a global instance created in EF_FRAMEGEN.ts
|
|
19
|
+
declare global {
|
|
20
|
+
var EF_FRAMEGEN: import("../EF_FRAMEGEN.js").EFFramegen;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const log = debug("ef:elements:EFVideo");
|
|
24
|
+
|
|
25
|
+
interface LoadingState {
|
|
26
|
+
isLoading: boolean;
|
|
27
|
+
operation: "scrub-segment" | "video-segment" | "seeking" | "decoding" | null;
|
|
28
|
+
message: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
9
31
|
@customElement("ef-video")
|
|
10
32
|
export class EFVideo extends TWMixin(EFMedia) {
|
|
33
|
+
static get observedAttributes() {
|
|
34
|
+
const parentAttributes = EFMedia.observedAttributes || [];
|
|
35
|
+
return [
|
|
36
|
+
...parentAttributes,
|
|
37
|
+
"video-buffer-duration",
|
|
38
|
+
"max-video-buffer-fetches",
|
|
39
|
+
"enable-video-buffering",
|
|
40
|
+
];
|
|
41
|
+
}
|
|
42
|
+
|
|
11
43
|
static styles = [
|
|
12
44
|
/**
|
|
13
45
|
*
|
|
@@ -15,6 +47,7 @@ export class EFVideo extends TWMixin(EFMedia) {
|
|
|
15
47
|
css`
|
|
16
48
|
:host {
|
|
17
49
|
display: block;
|
|
50
|
+
position: relative;
|
|
18
51
|
}
|
|
19
52
|
canvas {
|
|
20
53
|
all: inherit;
|
|
@@ -29,12 +62,129 @@ export class EFVideo extends TWMixin(EFMedia) {
|
|
|
29
62
|
outline: none;
|
|
30
63
|
box-shadow: none;
|
|
31
64
|
}
|
|
65
|
+
.loading-overlay {
|
|
66
|
+
position: absolute;
|
|
67
|
+
top: 0;
|
|
68
|
+
left: 0;
|
|
69
|
+
right: 0;
|
|
70
|
+
bottom: 0;
|
|
71
|
+
background: rgba(0, 0, 0, 0.6);
|
|
72
|
+
display: flex;
|
|
73
|
+
align-items: center;
|
|
74
|
+
justify-content: center;
|
|
75
|
+
z-index: 10;
|
|
76
|
+
backdrop-filter: blur(2px);
|
|
77
|
+
}
|
|
78
|
+
.loading-content {
|
|
79
|
+
background: rgba(0, 0, 0, 0.8);
|
|
80
|
+
border-radius: 8px;
|
|
81
|
+
padding: 16px 24px;
|
|
82
|
+
display: flex;
|
|
83
|
+
align-items: center;
|
|
84
|
+
gap: 12px;
|
|
85
|
+
color: white;
|
|
86
|
+
font-size: 14px;
|
|
87
|
+
font-weight: 500;
|
|
88
|
+
}
|
|
89
|
+
.loading-spinner {
|
|
90
|
+
width: 20px;
|
|
91
|
+
height: 20px;
|
|
92
|
+
border: 2px solid rgba(255, 255, 255, 0.2);
|
|
93
|
+
border-left: 2px solid #fff;
|
|
94
|
+
border-radius: 50%;
|
|
95
|
+
animation: spin 1s linear infinite;
|
|
96
|
+
}
|
|
97
|
+
@keyframes spin {
|
|
98
|
+
0% { transform: rotate(0deg); }
|
|
99
|
+
100% { transform: rotate(360deg); }
|
|
100
|
+
}
|
|
101
|
+
.loading-message {
|
|
102
|
+
font-size: 12px;
|
|
103
|
+
opacity: 0.8;
|
|
104
|
+
}
|
|
32
105
|
`,
|
|
33
106
|
];
|
|
34
107
|
canvasRef = createRef<HTMLCanvasElement>();
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Duration in milliseconds for video buffering ahead of current time
|
|
111
|
+
* @domAttribute "video-buffer-duration"
|
|
112
|
+
*/
|
|
113
|
+
@property({ type: Number, attribute: "video-buffer-duration" })
|
|
114
|
+
videoBufferDurationMs = 60000; // 60 seconds
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Maximum number of concurrent video segment fetches for buffering
|
|
118
|
+
* @domAttribute "max-video-buffer-fetches"
|
|
119
|
+
*/
|
|
120
|
+
@property({ type: Number, attribute: "max-video-buffer-fetches" })
|
|
121
|
+
maxVideoBufferFetches = 2;
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Enable/disable video buffering system
|
|
125
|
+
* @domAttribute "enable-video-buffering"
|
|
126
|
+
*/
|
|
127
|
+
@property({ type: Boolean, attribute: "enable-video-buffering" })
|
|
128
|
+
enableVideoBuffering = true;
|
|
129
|
+
|
|
130
|
+
// Video-specific tasks
|
|
131
|
+
videoSegmentIdTask = makeVideoSegmentIdTask(this);
|
|
132
|
+
videoInitSegmentFetchTask = makeVideoInitSegmentFetchTask(this);
|
|
133
|
+
videoSegmentFetchTask = makeVideoSegmentFetchTask(this);
|
|
134
|
+
videoInputTask = makeVideoInputTask(this);
|
|
135
|
+
videoSeekTask = makeVideoSeekTask(this);
|
|
136
|
+
videoBufferTask = makeVideoBufferTask(this);
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Scrub track manager for fast timeline navigation
|
|
140
|
+
*/
|
|
141
|
+
scrubTrackManager?: ScrubTrackManager;
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Delayed loading state manager for user feedback
|
|
145
|
+
*/
|
|
146
|
+
private delayedLoadingState: DelayedLoadingState;
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Loading state for user feedback
|
|
150
|
+
*/
|
|
151
|
+
@state()
|
|
152
|
+
loadingState = {
|
|
153
|
+
isLoading: false,
|
|
154
|
+
operation: null as LoadingState["operation"],
|
|
155
|
+
message: "",
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
constructor() {
|
|
159
|
+
super();
|
|
160
|
+
|
|
161
|
+
// Initialize delayed loading state with callback to update UI
|
|
162
|
+
this.delayedLoadingState = new DelayedLoadingState(
|
|
163
|
+
250,
|
|
164
|
+
(isLoading, message) => {
|
|
165
|
+
this.setLoadingState(isLoading, null, message);
|
|
166
|
+
},
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
|
|
35
170
|
render() {
|
|
36
171
|
return html`
|
|
37
172
|
<canvas ${ref(this.canvasRef)}></canvas>
|
|
173
|
+
${
|
|
174
|
+
this.loadingState.isLoading
|
|
175
|
+
? html`
|
|
176
|
+
<div class="loading-overlay">
|
|
177
|
+
<div class="loading-content">
|
|
178
|
+
<div class="loading-spinner"></div>
|
|
179
|
+
<div>
|
|
180
|
+
<div>Loading Video...</div>
|
|
181
|
+
<div class="loading-message">${this.loadingState.message}</div>
|
|
182
|
+
</div>
|
|
183
|
+
</div>
|
|
184
|
+
</div>
|
|
185
|
+
`
|
|
186
|
+
: ""
|
|
187
|
+
}
|
|
38
188
|
`;
|
|
39
189
|
}
|
|
40
190
|
|
|
@@ -42,89 +192,289 @@ export class EFVideo extends TWMixin(EFMedia) {
|
|
|
42
192
|
return this.canvasRef.value;
|
|
43
193
|
}
|
|
44
194
|
|
|
45
|
-
// The underlying video decoder MUST NOT be used concurrently.
|
|
46
|
-
// If frames are fed in out of order, the decoder may crash.
|
|
47
|
-
#decoderLock = false;
|
|
48
|
-
|
|
49
195
|
frameTask = new Task(this, {
|
|
50
|
-
args: () =>
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
this.paintTask.status,
|
|
58
|
-
] as const,
|
|
59
|
-
task: async () => {
|
|
60
|
-
await this.trackFragmentIndexLoader.taskComplete;
|
|
61
|
-
await this.initSegmentsLoader.taskComplete;
|
|
62
|
-
await this.seekTask.taskComplete;
|
|
63
|
-
await this.fetchSeekTask.taskComplete;
|
|
64
|
-
await this.videoAssetTask.taskComplete;
|
|
196
|
+
args: () => [this.desiredSeekTimeMs] as const,
|
|
197
|
+
onError: (error) => {
|
|
198
|
+
console.error("frameTask error", error);
|
|
199
|
+
},
|
|
200
|
+
onComplete: () => {},
|
|
201
|
+
task: async ([_desiredSeekTimeMs], { signal }) => {
|
|
202
|
+
await this.videoSeekTask.taskComplete;
|
|
65
203
|
await this.paintTask.taskComplete;
|
|
204
|
+
if (signal.aborted) {
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
66
207
|
},
|
|
67
208
|
});
|
|
68
209
|
|
|
210
|
+
protected updated(
|
|
211
|
+
changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>,
|
|
212
|
+
): void {
|
|
213
|
+
super.updated(changedProperties);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Start a delayed loading operation for testing
|
|
218
|
+
*/
|
|
219
|
+
startDelayedLoading(
|
|
220
|
+
operationId: string,
|
|
221
|
+
message: string,
|
|
222
|
+
options: { background?: boolean } = {},
|
|
223
|
+
): void {
|
|
224
|
+
this.delayedLoadingState.startLoading(operationId, message, options);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Clear a delayed loading operation for testing
|
|
229
|
+
*/
|
|
230
|
+
clearDelayedLoading(operationId: string): void {
|
|
231
|
+
this.delayedLoadingState.clearLoading(operationId);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Set loading state for user feedback
|
|
236
|
+
*/
|
|
237
|
+
private setLoadingState(
|
|
238
|
+
isLoading: boolean,
|
|
239
|
+
operation: LoadingState["operation"] = null,
|
|
240
|
+
message = "",
|
|
241
|
+
): void {
|
|
242
|
+
this.loadingState = {
|
|
243
|
+
isLoading,
|
|
244
|
+
operation,
|
|
245
|
+
message,
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
|
|
69
249
|
paintTask = new Task(this, {
|
|
70
|
-
args: () => [this.
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
if (
|
|
82
|
-
|
|
250
|
+
args: () => [this.desiredSeekTimeMs] as const,
|
|
251
|
+
onError: (error) => {
|
|
252
|
+
console.error("paintTask error", error);
|
|
253
|
+
},
|
|
254
|
+
onComplete: () => {},
|
|
255
|
+
task: async ([_seekToMs], { signal }) => {
|
|
256
|
+
await this.videoSeekTask.taskComplete;
|
|
257
|
+
// Check if we're in production rendering mode vs preview mode
|
|
258
|
+
const isProductionRendering = this.isInProductionRenderingMode();
|
|
259
|
+
|
|
260
|
+
const sample = this.videoSeekTask.value;
|
|
261
|
+
if (sample) {
|
|
262
|
+
const videoFrame = sample.toVideoFrame();
|
|
263
|
+
this.displayFrame(videoFrame, _seekToMs);
|
|
264
|
+
videoFrame.close();
|
|
83
265
|
}
|
|
84
|
-
try {
|
|
85
|
-
this.#decoderLock = true;
|
|
86
|
-
const frame = await videoAsset.seekToTime(seekToMs / 1000);
|
|
87
266
|
|
|
88
|
-
|
|
89
|
-
|
|
267
|
+
// EF_FRAMEGEN-aware rendering mode detection
|
|
268
|
+
if (!isProductionRendering) {
|
|
269
|
+
// Preview mode: skip rendering during initialization to prevent artifacts
|
|
270
|
+
if (
|
|
271
|
+
!this.rootTimegroup ||
|
|
272
|
+
(this.rootTimegroup.currentTimeMs === 0 &&
|
|
273
|
+
this.desiredSeekTimeMs === 0)
|
|
274
|
+
) {
|
|
275
|
+
return; // Skip initialization frame in preview mode
|
|
90
276
|
}
|
|
91
|
-
|
|
92
|
-
|
|
277
|
+
// Preview mode: proceed with rendering
|
|
278
|
+
} else {
|
|
279
|
+
// Production rendering mode: only render when EF_FRAMEGEN has explicitly started frame rendering
|
|
280
|
+
// This prevents initialization frames before the actual render sequence begins
|
|
281
|
+
if (!this.rootTimegroup) {
|
|
93
282
|
return;
|
|
94
283
|
}
|
|
95
284
|
|
|
96
|
-
if (
|
|
97
|
-
|
|
98
|
-
this.canvasElement.width !== frame.codedWidth ||
|
|
99
|
-
this.canvasElement.height !== frame.codedHeight
|
|
100
|
-
) {
|
|
101
|
-
this.canvasElement.width = frame.codedWidth;
|
|
102
|
-
this.canvasElement.height = frame.codedHeight;
|
|
103
|
-
}
|
|
285
|
+
if (!this.isFrameRenderingActive()) {
|
|
286
|
+
return; // Wait for EF_FRAMEGEN to start frame sequence
|
|
104
287
|
}
|
|
105
288
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
frame,
|
|
112
|
-
0,
|
|
113
|
-
0,
|
|
114
|
-
this.canvasElement.width,
|
|
115
|
-
this.canvasElement.height,
|
|
116
|
-
);
|
|
117
|
-
|
|
118
|
-
return seekToMs;
|
|
119
|
-
} catch (error) {
|
|
120
|
-
console.trace("Unexpected error while seeking video", error);
|
|
121
|
-
// As a practical matter, we should probably just re-create the VideoAsset if decoding fails.
|
|
122
|
-
// The decoder is probably in an invalid state anyway.
|
|
123
|
-
} finally {
|
|
124
|
-
this.#decoderLock = false;
|
|
289
|
+
// Production mode: EF_FRAMEGEN has started frame sequence, proceed with rendering
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
if (signal.aborted) {
|
|
293
|
+
return;
|
|
125
294
|
}
|
|
126
295
|
},
|
|
127
296
|
});
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Display a video frame on the canvas
|
|
300
|
+
*/
|
|
301
|
+
private displayFrame(frame: VideoFrame, seekToMs: number): number {
|
|
302
|
+
log("trace: displayFrame start", { seekToMs, frameFormat: frame.format });
|
|
303
|
+
if (!this.canvasElement) {
|
|
304
|
+
log("trace: displayFrame aborted - no canvas element");
|
|
305
|
+
throw new Error(
|
|
306
|
+
`Frame display failed: Canvas element is not available at time ${seekToMs}ms. The video component may not be properly initialized.`,
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
const ctx = this.canvasElement.getContext("2d");
|
|
311
|
+
if (!ctx) {
|
|
312
|
+
log("trace: displayFrame aborted - no canvas context");
|
|
313
|
+
throw new Error(
|
|
314
|
+
`Frame display failed: Unable to get 2D canvas context at time ${seekToMs}ms. This may indicate a browser compatibility issue or canvas corruption.`,
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
if (frame?.codedWidth && frame?.codedHeight) {
|
|
319
|
+
if (
|
|
320
|
+
this.canvasElement.width !== frame.codedWidth ||
|
|
321
|
+
this.canvasElement.height !== frame.codedHeight
|
|
322
|
+
) {
|
|
323
|
+
log("trace: updating canvas dimensions", {
|
|
324
|
+
width: frame.codedWidth,
|
|
325
|
+
height: frame.codedHeight,
|
|
326
|
+
});
|
|
327
|
+
this.canvasElement.width = frame.codedWidth;
|
|
328
|
+
this.canvasElement.height = frame.codedHeight;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
if (frame.format === null) {
|
|
333
|
+
log("trace: displayFrame aborted - null frame format");
|
|
334
|
+
throw new Error(
|
|
335
|
+
`Frame display failed: Video frame has null format at time ${seekToMs}ms. This indicates corrupted or incompatible video data.`,
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
log("trace: drawing frame to canvas", frame.timestamp / 1000);
|
|
340
|
+
ctx.drawImage(
|
|
341
|
+
frame,
|
|
342
|
+
0,
|
|
343
|
+
0,
|
|
344
|
+
this.canvasElement.width,
|
|
345
|
+
this.canvasElement.height,
|
|
346
|
+
);
|
|
347
|
+
log("trace: frame drawn to canvas", { seekToMs });
|
|
348
|
+
|
|
349
|
+
return seekToMs;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Check if we're in production rendering mode (EF_FRAMEGEN active) vs preview mode
|
|
354
|
+
*/
|
|
355
|
+
private isInProductionRenderingMode(): boolean {
|
|
356
|
+
// Check if EF_RENDERING function exists and returns true (production rendering)
|
|
357
|
+
if (typeof window.EF_RENDERING === "function") {
|
|
358
|
+
return window.EF_RENDERING();
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// Check if workbench is in rendering mode
|
|
362
|
+
const workbench = document.querySelector("ef-workbench") as any;
|
|
363
|
+
if (workbench?.rendering) {
|
|
364
|
+
return true;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// Check if EF_FRAMEGEN exists and has render options (indicates active rendering)
|
|
368
|
+
if (window.EF_FRAMEGEN?.renderOptions) {
|
|
369
|
+
return true;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// Default to preview mode
|
|
373
|
+
return false;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Check if EF_FRAMEGEN has explicitly started frame rendering (not just initialization)
|
|
378
|
+
*/
|
|
379
|
+
private isFrameRenderingActive(): boolean {
|
|
380
|
+
if (!window.EF_FRAMEGEN?.renderOptions) {
|
|
381
|
+
return false;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// In production mode, only render when EF_FRAMEGEN has actually begun frame sequence
|
|
385
|
+
// Check if we're past the initialization phase by looking for explicit frame control
|
|
386
|
+
const renderOptions = window.EF_FRAMEGEN.renderOptions;
|
|
387
|
+
const renderStartTime = renderOptions.encoderOptions.fromMs;
|
|
388
|
+
const currentTime = this.rootTimegroup?.currentTimeMs || 0;
|
|
389
|
+
|
|
390
|
+
// We're in active frame rendering if:
|
|
391
|
+
// 1. currentTime >= renderStartTime (includes the starting frame)
|
|
392
|
+
return currentTime >= renderStartTime;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* Get scrub track performance statistics
|
|
397
|
+
*/
|
|
398
|
+
getScrubTrackStats(): CacheStats | null {
|
|
399
|
+
return this.scrubTrackManager?.getCacheStats() || null;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// Getter properties for backward compatibility with tests
|
|
403
|
+
/**
|
|
404
|
+
* Effective mode - always returns "asset" for EFVideo
|
|
405
|
+
*/
|
|
406
|
+
get effectiveMode(): string {
|
|
407
|
+
return "asset";
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* Legacy getter for asset index loader (maps to mediaEngine task)
|
|
412
|
+
*/
|
|
413
|
+
get assetIndexLoader() {
|
|
414
|
+
return this.mediaEngineTask;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* Legacy getter for fragment index task (maps to videoSegmentIdTask)
|
|
419
|
+
*/
|
|
420
|
+
get fragmentIndexTask() {
|
|
421
|
+
return this.videoSegmentIdTask;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* Legacy getter for seek task (maps to videoSeekTask)
|
|
426
|
+
*/
|
|
427
|
+
get seekTask() {
|
|
428
|
+
return this.videoSeekTask;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* Legacy getter for media segments task (maps to videoSegmentFetchTask)
|
|
433
|
+
*/
|
|
434
|
+
get mediaSegmentsTask() {
|
|
435
|
+
return this.videoSegmentFetchTask;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* Legacy getter for asset segment keys task (maps to videoSegmentIdTask)
|
|
440
|
+
*/
|
|
441
|
+
get assetSegmentKeysTask() {
|
|
442
|
+
return this.videoSegmentIdTask;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
/**
|
|
446
|
+
* Legacy getter for asset init segments task (maps to videoInitSegmentFetchTask)
|
|
447
|
+
*/
|
|
448
|
+
get assetInitSegmentsTask() {
|
|
449
|
+
return this.videoInitSegmentFetchTask;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
/**
|
|
453
|
+
* Legacy getter for asset segment loader (maps to videoSegmentFetchTask)
|
|
454
|
+
*/
|
|
455
|
+
get assetSegmentLoader() {
|
|
456
|
+
return this.videoSegmentFetchTask;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* Legacy getter for video asset task (maps to videoBufferTask)
|
|
461
|
+
*/
|
|
462
|
+
get videoAssetTask() {
|
|
463
|
+
return this.videoBufferTask;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* Clean up resources when component is disconnected
|
|
468
|
+
*/
|
|
469
|
+
disconnectedCallback(): void {
|
|
470
|
+
super.disconnectedCallback();
|
|
471
|
+
|
|
472
|
+
// Clean up scrub track manager
|
|
473
|
+
this.scrubTrackManager?.cleanup();
|
|
474
|
+
|
|
475
|
+
// Clean up delayed loading state
|
|
476
|
+
this.delayedLoadingState.clearAllLoading();
|
|
477
|
+
}
|
|
128
478
|
}
|
|
129
479
|
|
|
130
480
|
declare global {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { CSSStyleObserver } from "@bramus/style-observer";
|
|
2
2
|
import { Task } from "@lit/task";
|
|
3
|
-
import { LitElement, type PropertyValueMap
|
|
3
|
+
import { css, html, LitElement, type PropertyValueMap } from "lit";
|
|
4
4
|
import { customElement, property, state } from "lit/decorators.js";
|
|
5
|
-
import { type Ref,
|
|
5
|
+
import { createRef, type Ref, ref } from "lit/directives/ref.js";
|
|
6
6
|
import { EF_INTERACTIVE } from "../EF_INTERACTIVE.js";
|
|
7
7
|
import { EF_RENDERING } from "../EF_RENDERING.js";
|
|
8
8
|
import { TWMixin } from "../gui/TWMixin.js";
|
|
@@ -16,8 +16,8 @@ import { TargetController } from "./TargetController.ts";
|
|
|
16
16
|
export class EFWaveform extends EFTemporal(TWMixin(LitElement)) {
|
|
17
17
|
static styles = css`
|
|
18
18
|
:host {
|
|
19
|
-
display: block;
|
|
20
19
|
all: inherit;
|
|
20
|
+
display: block;
|
|
21
21
|
position: relative;
|
|
22
22
|
}
|
|
23
23
|
|
|
@@ -38,7 +38,7 @@ export class EFWaveform extends EFTemporal(TWMixin(LitElement)) {
|
|
|
38
38
|
private mutationObserver?: MutationObserver;
|
|
39
39
|
|
|
40
40
|
render() {
|
|
41
|
-
return html`<canvas ${ref(this.canvasRef)}></canvas>`;
|
|
41
|
+
return html`<canvas ${ref(this.canvasRef)}></canvas><div class="text-5xl inline-block bg-red-500">`;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
@property({
|
|
@@ -78,7 +78,7 @@ export class EFWaveform extends EFTemporal(TWMixin(LitElement)) {
|
|
|
78
78
|
if (this.targetElement) {
|
|
79
79
|
new CrossUpdateController(this.targetElement, this);
|
|
80
80
|
}
|
|
81
|
-
} catch (
|
|
81
|
+
} catch (_error) {
|
|
82
82
|
// TODO: determine if this is a critical error, or if we should just ignore it
|
|
83
83
|
// currenty evidence suggests everything still works
|
|
84
84
|
// no target element, no cross update controller
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import type { ReactiveController, ReactiveControllerHost } from "lit";
|
|
2
|
+
|
|
3
|
+
export class MediaController implements ReactiveController {
|
|
4
|
+
#src: string | null = null;
|
|
5
|
+
#assetId: string | null = null;
|
|
6
|
+
|
|
7
|
+
constructor(
|
|
8
|
+
private host: ReactiveControllerHost & {
|
|
9
|
+
src: string;
|
|
10
|
+
assetId: string | null;
|
|
11
|
+
mode: "asset" | "jit-transcode" | "auto";
|
|
12
|
+
},
|
|
13
|
+
) {
|
|
14
|
+
this.host.addController(this);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
get mode() {
|
|
18
|
+
const actualMode = this.host.mode;
|
|
19
|
+
if (actualMode === "asset" || actualMode === "jit-transcode") {
|
|
20
|
+
return actualMode;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (this.host.assetId) {
|
|
24
|
+
return "asset";
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (!this.host.src) {
|
|
28
|
+
return "asset";
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return "asset";
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
get src() {
|
|
35
|
+
return this.#src;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
set src(value: string | null) {
|
|
39
|
+
if (this.#src !== value) {
|
|
40
|
+
this.trackUpdate("src", this.#src, value);
|
|
41
|
+
this.#src = value;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
get assetId() {
|
|
46
|
+
return this.#assetId;
|
|
47
|
+
}
|
|
48
|
+
set assetId(value: string | null) {
|
|
49
|
+
if (this.#assetId !== value) {
|
|
50
|
+
this.trackUpdate("assetId", this.#assetId, value);
|
|
51
|
+
this.#assetId = value;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
changes: Map<string, { oldValue: any; newValue: any }> | null = null;
|
|
56
|
+
updatePending = false;
|
|
57
|
+
|
|
58
|
+
trackUpdate(key: string, oldValue: any, newValue: any) {
|
|
59
|
+
this.changes ??= new Map<string, { oldValue: any; newValue: any }>();
|
|
60
|
+
this.changes.set(key, { oldValue, newValue });
|
|
61
|
+
if (!this.updatePending) {
|
|
62
|
+
this.updatePending = true;
|
|
63
|
+
queueMicrotask(() => {
|
|
64
|
+
this.endUpdate();
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
endUpdate() {
|
|
70
|
+
try {
|
|
71
|
+
if (this.changes) {
|
|
72
|
+
this.handleUpdate(this.changes);
|
|
73
|
+
}
|
|
74
|
+
} finally {
|
|
75
|
+
this.changes = null;
|
|
76
|
+
this.updatePending = false;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
handleUpdate(changes: Map<string, { oldValue: any; newValue: any }>) {
|
|
81
|
+
if (changes.has("src") || changes.has("assetId") || changes.has("mode")) {
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
hostUpdated(): void {
|
|
86
|
+
this.src = this.host.src;
|
|
87
|
+
this.assetId = this.host.assetId;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
hostConnected() {
|
|
91
|
+
this.src = this.host.src;
|
|
92
|
+
this.assetId = this.host.assetId;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
hostDisconnected() {}
|
|
96
|
+
|
|
97
|
+
updated() {}
|
|
98
|
+
}
|