@editframe/elements 0.17.6-beta.0 → 0.18.7-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/EF_FRAMEGEN.js +1 -1
- package/dist/elements/EFAudio.d.ts +21 -2
- package/dist/elements/EFAudio.js +41 -11
- package/dist/elements/EFImage.d.ts +1 -0
- package/dist/elements/EFImage.js +11 -3
- package/dist/elements/EFMedia/AssetIdMediaEngine.d.ts +18 -0
- package/dist/elements/EFMedia/AssetIdMediaEngine.js +41 -0
- package/dist/elements/EFMedia/AssetMediaEngine.browsertest.d.ts +0 -0
- package/dist/elements/EFMedia/AssetMediaEngine.d.ts +45 -0
- package/dist/elements/EFMedia/AssetMediaEngine.js +135 -0
- package/dist/elements/EFMedia/BaseMediaEngine.d.ts +55 -0
- package/dist/elements/EFMedia/BaseMediaEngine.js +115 -0
- package/dist/elements/EFMedia/BufferedSeekingInput.d.ts +43 -0
- package/dist/elements/EFMedia/BufferedSeekingInput.js +179 -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 +81 -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 +141 -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 +30 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioSeekTask.chunkboundary.regression.browsertest.d.ts +0 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioSeekTask.d.ts +7 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioSeekTask.js +32 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioSegmentFetchTask.d.ts +4 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioSegmentFetchTask.js +28 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioSegmentIdTask.d.ts +4 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioSegmentIdTask.js +17 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.d.ts +3 -0
- package/dist/elements/EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.js +107 -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/PrecisionUtils.d.ts +28 -0
- package/dist/elements/EFMedia/shared/PrecisionUtils.js +29 -0
- package/dist/elements/EFMedia/shared/RenditionHelpers.d.ts +19 -0
- package/dist/elements/EFMedia/tasks/makeMediaEngineTask.d.ts +18 -0
- package/dist/elements/EFMedia/tasks/makeMediaEngineTask.js +60 -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 +34 -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 +28 -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 +17 -0
- package/dist/elements/EFMedia.browsertest.d.ts +1 -0
- package/dist/elements/EFMedia.d.ts +63 -111
- package/dist/elements/EFMedia.js +117 -1113
- package/dist/elements/EFTemporal.d.ts +1 -1
- package/dist/elements/EFTemporal.js +1 -1
- package/dist/elements/EFTimegroup.d.ts +11 -0
- package/dist/elements/EFTimegroup.js +83 -13
- package/dist/elements/EFVideo.d.ts +54 -32
- package/dist/elements/EFVideo.js +100 -207
- package/dist/elements/EFWaveform.js +2 -2
- package/dist/elements/SampleBuffer.d.ts +14 -0
- package/dist/elements/SampleBuffer.js +52 -0
- package/dist/getRenderInfo.js +2 -1
- package/dist/gui/ContextMixin.js +3 -2
- package/dist/gui/EFFilmstrip.d.ts +3 -3
- package/dist/gui/EFFilmstrip.js +1 -1
- package/dist/gui/EFFitScale.d.ts +2 -2
- package/dist/gui/TWMixin.js +1 -1
- package/dist/style.css +1 -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 +3 -3
- package/src/elements/EFAudio.browsertest.ts +189 -49
- package/src/elements/EFAudio.ts +59 -13
- package/src/elements/EFImage.browsertest.ts +42 -0
- 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.browsertest.ts +100 -0
- package/src/elements/EFMedia/AssetMediaEngine.ts +255 -0
- package/src/elements/EFMedia/BaseMediaEngine.test.ts +164 -0
- package/src/elements/EFMedia/BaseMediaEngine.ts +219 -0
- package/src/elements/EFMedia/BufferedSeekingInput.browsertest.ts +481 -0
- package/src/elements/EFMedia/BufferedSeekingInput.ts +324 -0
- package/src/elements/EFMedia/JitMediaEngine.browsertest.ts +165 -0
- package/src/elements/EFMedia/JitMediaEngine.ts +166 -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 +250 -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 +43 -0
- package/src/elements/EFMedia/audioTasks/makeAudioSeekTask.chunkboundary.regression.browsertest.ts +199 -0
- package/src/elements/EFMedia/audioTasks/makeAudioSeekTask.ts +64 -0
- package/src/elements/EFMedia/audioTasks/makeAudioSegmentFetchTask.ts +45 -0
- package/src/elements/EFMedia/audioTasks/makeAudioSegmentIdTask.ts +24 -0
- package/src/elements/EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.ts +183 -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/PrecisionUtils.ts +46 -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 +68 -0
- package/src/elements/EFMedia/videoTasks/makeVideoSegmentFetchTask.browsertest.ts +57 -0
- package/src/elements/EFMedia/videoTasks/makeVideoSegmentFetchTask.ts +43 -0
- package/src/elements/EFMedia/videoTasks/makeVideoSegmentIdTask.browsertest.ts +56 -0
- package/src/elements/EFMedia/videoTasks/makeVideoSegmentIdTask.ts +24 -0
- package/src/elements/EFMedia.browsertest.ts +706 -273
- package/src/elements/EFMedia.ts +136 -1769
- package/src/elements/EFTemporal.ts +3 -4
- package/src/elements/EFTimegroup.browsertest.ts +6 -3
- package/src/elements/EFTimegroup.ts +147 -21
- package/src/elements/EFVideo.browsertest.ts +980 -169
- package/src/elements/EFVideo.ts +113 -458
- package/src/elements/EFWaveform.ts +1 -1
- package/src/elements/MediaController.ts +2 -12
- package/src/elements/SampleBuffer.ts +95 -0
- package/src/gui/ContextMixin.ts +3 -6
- 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 +269 -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 +39 -30
- 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_1_mp4_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4_bytes_0__9ed2d25c675aa6bb6ff5b3ae23887c71/data.bin +0 -0
- package/test/__cache__/GET__api_v1_transcode_audio_1_mp4_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4_bytes_0__9ed2d25c675aa6bb6ff5b3ae23887c71/metadata.json +22 -0
- 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_2_mp4_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4_bytes_0__d5a3309a2bf756dd6e304807eb402f56/data.bin +0 -0
- package/test/__cache__/GET__api_v1_transcode_audio_2_mp4_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4_bytes_0__d5a3309a2bf756dd6e304807eb402f56/metadata.json +22 -0
- 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_3_mp4_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4_bytes_0__773254bb671e3466fca8677139fb239e/data.bin +0 -0
- package/test/__cache__/GET__api_v1_transcode_audio_3_mp4_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4_bytes_0__773254bb671e3466fca8677139fb239e/metadata.json +22 -0
- 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_4_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__a6fb05a22b18d850f7f2950bbcdbdeed/data.bin +0 -0
- package/test/__cache__/GET__api_v1_transcode_high_4_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__a6fb05a22b18d850f7f2950bbcdbdeed/metadata.json +21 -0
- package/test/__cache__/GET__api_v1_transcode_high_5_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__a50058c7c3602e90879fe3428ed891f4/data.bin +0 -0
- package/test/__cache__/GET__api_v1_transcode_high_5_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__a50058c7c3602e90879fe3428ed891f4/metadata.json +21 -0
- 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 +320 -188
- package/test/recordReplayProxyPlugin.js +352 -0
- package/test/useAssetMSW.ts +1 -1
- package/test/useMSW.ts +35 -22
- package/types.json +1 -1
- package/dist/JitTranscodingClient.d.ts +0 -167
- package/dist/JitTranscodingClient.js +0 -373
- package/dist/ScrubTrackManager.d.ts +0 -96
- package/dist/ScrubTrackManager.js +0 -216
- package/dist/elements/printTaskStatus.js +0 -11
- package/src/elements/__screenshots__/EFMedia.browsertest.ts/EFMedia-JIT-audio-playback-audioBufferTask-should-work-in-JIT-mode-without-URL-errors-1.png +0 -0
- package/test/EFVideo.frame-tasks.browsertest.ts +0 -524
- /package/dist/{DecoderResetFrequency.test.d.ts → elements/EFMedia/AssetIdMediaEngine.test.d.ts} +0 -0
- /package/dist/{DecoderResetRecovery.test.d.ts → elements/EFMedia/BaseMediaEngine.test.d.ts} +0 -0
- /package/dist/{JitTranscodingClient.browsertest.d.ts → elements/EFMedia/BufferedSeekingInput.browsertest.d.ts} +0 -0
- /package/dist/{JitTranscodingClient.test.d.ts → elements/EFMedia/shared/RenditionHelpers.browsertest.d.ts} +0 -0
- /package/dist/{ScrubTrackIntegration.test.d.ts → elements/EFMedia/tasks/makeMediaEngineTask.browsertest.d.ts} +0 -0
- /package/dist/{SegmentSwitchLoading.test.d.ts → elements/EFMedia/tasks/makeMediaEngineTask.test.d.ts} +0 -0
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { consume, createContext } from "@lit/context";
|
|
2
|
+
import { Task } from "@lit/task";
|
|
2
3
|
import type { LitElement, PropertyValueMap, ReactiveController } from "lit";
|
|
3
4
|
import { property, state } from "lit/decorators.js";
|
|
4
|
-
import type { EFTimegroup } from "./EFTimegroup.js";
|
|
5
|
-
|
|
6
|
-
import { Task } from "@lit/task";
|
|
7
5
|
import { EF_INTERACTIVE } from "../EF_INTERACTIVE.js";
|
|
8
6
|
import { durationConverter } from "./durationConverter.js";
|
|
7
|
+
import type { EFTimegroup } from "./EFTimegroup.js";
|
|
9
8
|
|
|
10
9
|
export const timegroupContext = createContext<EFTimegroup>(
|
|
11
10
|
Symbol("timeGroupContext"),
|
|
@@ -549,7 +548,7 @@ export const EFTemporal = <T extends Constructor<LitElement>>(
|
|
|
549
548
|
}
|
|
550
549
|
const previous = siblingTemorals?.[(ownIndex ?? 0) - 1];
|
|
551
550
|
if (!previous) {
|
|
552
|
-
console.
|
|
551
|
+
console.error("Previous temporal element not found", {
|
|
553
552
|
ownIndex,
|
|
554
553
|
siblingTemorals,
|
|
555
554
|
});
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
|
-
LitElement,
|
|
3
|
-
type TemplateResult,
|
|
4
2
|
html,
|
|
3
|
+
LitElement,
|
|
5
4
|
render as litRender,
|
|
5
|
+
type TemplateResult,
|
|
6
6
|
} from "lit";
|
|
7
7
|
import { assert, beforeEach, describe, test } from "vitest";
|
|
8
8
|
import { EFTimegroup } from "./EFTimegroup.js";
|
|
@@ -353,7 +353,7 @@ describe("setting currentTime", () => {
|
|
|
353
353
|
document.body.appendChild(timegroup);
|
|
354
354
|
assert.isNull(localStorage.getItem(timegroup.storageKey));
|
|
355
355
|
timegroup.currentTime = 5_000;
|
|
356
|
-
assert.equal(localStorage.getItem(timegroup.storageKey), "
|
|
356
|
+
assert.equal(localStorage.getItem(timegroup.storageKey), "10"); // Clamped to duration
|
|
357
357
|
timegroup.remove();
|
|
358
358
|
});
|
|
359
359
|
|
|
@@ -392,6 +392,9 @@ describe("setting currentTime", () => {
|
|
|
392
392
|
assert.equal(a.ownCurrentTimeMs, 2_500);
|
|
393
393
|
assert.equal(b.ownCurrentTimeMs, 0);
|
|
394
394
|
|
|
395
|
+
// Wait for frame update to complete before next assignment
|
|
396
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
397
|
+
|
|
395
398
|
root.currentTimeMs = 7_500;
|
|
396
399
|
|
|
397
400
|
assert.equal(a.ownCurrentTimeMs, 5_000);
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
import { provide } from "@lit/context";
|
|
2
2
|
import { Task, TaskStatus } from "@lit/task";
|
|
3
3
|
import debug from "debug";
|
|
4
|
-
import { LitElement, type PropertyValueMap
|
|
4
|
+
import { css, html, LitElement, type PropertyValueMap } from "lit";
|
|
5
5
|
import { customElement, property } from "lit/decorators.js";
|
|
6
6
|
|
|
7
7
|
import { EF_INTERACTIVE } from "../EF_INTERACTIVE.js";
|
|
8
8
|
import { isContextMixin } from "../gui/ContextMixin.js";
|
|
9
|
+
import { durationConverter } from "./durationConverter.js";
|
|
9
10
|
import { deepGetMediaElements } from "./EFMedia.js";
|
|
10
11
|
import {
|
|
11
|
-
EFTemporal,
|
|
12
12
|
deepGetElementsWithFrameTasks,
|
|
13
|
+
EFTemporal,
|
|
13
14
|
flushStartTimeMsCache,
|
|
14
15
|
shallowGetTemporalElements,
|
|
15
16
|
timegroupContext,
|
|
16
17
|
} from "./EFTemporal.js";
|
|
17
18
|
import { TimegroupController } from "./TimegroupController.js";
|
|
18
|
-
import { durationConverter } from "./durationConverter.js";
|
|
19
19
|
import { updateAnimations } from "./updateAnimations.ts";
|
|
20
20
|
|
|
21
21
|
const log = debug("ef:elements:EFTimegroup");
|
|
@@ -52,6 +52,10 @@ export class EFTimegroup extends EFTemporal(LitElement) {
|
|
|
52
52
|
|
|
53
53
|
#currentTime = 0;
|
|
54
54
|
|
|
55
|
+
// Frame update locking mechanism (only for root timegroups)
|
|
56
|
+
private isFrameUpdateInProgress = false;
|
|
57
|
+
private queuedTimeUpdate: number | null = null;
|
|
58
|
+
|
|
55
59
|
@property({
|
|
56
60
|
type: String,
|
|
57
61
|
attribute: "mode",
|
|
@@ -72,27 +76,84 @@ export class EFTimegroup extends EFTemporal(LitElement) {
|
|
|
72
76
|
|
|
73
77
|
@property({ type: Number, attribute: "currenttime" })
|
|
74
78
|
set currentTime(time: number) {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
83
|
-
|
|
79
|
+
const newTime = Math.max(0, Math.min(time, this.durationMs / 1000));
|
|
80
|
+
|
|
81
|
+
// Only apply locking mechanism for root timegroups to prevent cascade overload
|
|
82
|
+
if (this.isRootTimegroup && this.isFrameUpdateInProgress) {
|
|
83
|
+
// Queue the latest time update - only keep the most recent
|
|
84
|
+
this.queuedTimeUpdate = newTime;
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (this.isRootTimegroup) {
|
|
89
|
+
this.#executeTimeUpdate(newTime);
|
|
90
|
+
} else {
|
|
91
|
+
// Non-root timegroups update immediately (no cascade risk)
|
|
92
|
+
this.#currentTime = newTime;
|
|
93
|
+
this.#saveTimeToLocalStorage(newTime);
|
|
84
94
|
}
|
|
85
95
|
}
|
|
96
|
+
|
|
86
97
|
get currentTime() {
|
|
87
98
|
return this.#currentTime;
|
|
88
99
|
}
|
|
100
|
+
|
|
89
101
|
get currentTimeMs() {
|
|
90
102
|
return this.currentTime * 1000;
|
|
91
103
|
}
|
|
104
|
+
|
|
92
105
|
set currentTimeMs(ms: number) {
|
|
93
106
|
this.currentTime = ms / 1000;
|
|
94
107
|
}
|
|
95
108
|
|
|
109
|
+
/**
|
|
110
|
+
* Determines if this is a root timegroup (no parent timegroups)
|
|
111
|
+
*/
|
|
112
|
+
get isRootTimegroup(): boolean {
|
|
113
|
+
return this.closest("ef-timegroup") === this;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Executes time update with frame locking for root timegroups
|
|
118
|
+
*/
|
|
119
|
+
async #executeTimeUpdate(time: number) {
|
|
120
|
+
this.isFrameUpdateInProgress = true;
|
|
121
|
+
this.#currentTime = time;
|
|
122
|
+
|
|
123
|
+
try {
|
|
124
|
+
// Save to localStorage
|
|
125
|
+
this.#saveTimeToLocalStorage(time);
|
|
126
|
+
|
|
127
|
+
// Wait for any pending frame tasks to complete before allowing next update
|
|
128
|
+
await this.waitForFrameTasks();
|
|
129
|
+
} catch (error) {
|
|
130
|
+
console.error("⚠️ [TIME_UPDATE_ERROR] Error during frame update:", error);
|
|
131
|
+
} finally {
|
|
132
|
+
this.isFrameUpdateInProgress = false;
|
|
133
|
+
|
|
134
|
+
// Process queued update if any (ensures latest scrub position is processed)
|
|
135
|
+
if (this.queuedTimeUpdate !== null && this.queuedTimeUpdate !== time) {
|
|
136
|
+
const nextTime = this.queuedTimeUpdate;
|
|
137
|
+
this.queuedTimeUpdate = null;
|
|
138
|
+
// Schedule on next tick to avoid recursive call stack
|
|
139
|
+
setTimeout(() => this.#executeTimeUpdate(nextTime), 0);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Saves time to localStorage (extracted for reuse)
|
|
146
|
+
*/
|
|
147
|
+
#saveTimeToLocalStorage(time: number) {
|
|
148
|
+
try {
|
|
149
|
+
if (this.id && this.isConnected) {
|
|
150
|
+
localStorage.setItem(this.storageKey, time.toString());
|
|
151
|
+
}
|
|
152
|
+
} catch (error) {
|
|
153
|
+
log("Failed to save time to localStorage", error);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
96
157
|
render() {
|
|
97
158
|
return html`<slot></slot> `;
|
|
98
159
|
}
|
|
@@ -236,9 +297,7 @@ export class EFTimegroup extends EFTemporal(LitElement) {
|
|
|
236
297
|
const mediaElements = deepGetMediaElements(this);
|
|
237
298
|
// Then, we must await the fragmentIndexTask to ensure all media elements have their
|
|
238
299
|
// fragment index loaded, which is where their duration is parsed from.
|
|
239
|
-
await Promise.all(
|
|
240
|
-
mediaElements.map((m) => m.fragmentIndexTask.taskComplete),
|
|
241
|
-
);
|
|
300
|
+
await Promise.all(mediaElements.map((m) => m.mediaEngineTask.taskComplete));
|
|
242
301
|
|
|
243
302
|
// After waiting for durations, we must force some updates to cascade and ensure all temporal elements
|
|
244
303
|
// have correct durations and start times. It is not ideal that we have to do this inside here,
|
|
@@ -338,16 +397,40 @@ export class EFTimegroup extends EFTemporal(LitElement) {
|
|
|
338
397
|
) {
|
|
339
398
|
await this.waitForMediaDurations();
|
|
340
399
|
|
|
400
|
+
// Create AbortController for audio fetch operations
|
|
401
|
+
const abortController = new AbortController();
|
|
402
|
+
|
|
341
403
|
await Promise.all(
|
|
342
404
|
deepGetMediaElements(this).map(async (mediaElement) => {
|
|
405
|
+
// Skip muted elements entirely - no audio fetching or processing needed
|
|
406
|
+
if (mediaElement.mute) {
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
|
|
343
410
|
const mediaStartsBeforeEnd = mediaElement.startTimeMs <= toMs;
|
|
344
411
|
const mediaEndsAfterStart = mediaElement.endTimeMs >= fromMs;
|
|
345
412
|
const mediaOverlaps = mediaStartsBeforeEnd && mediaEndsAfterStart;
|
|
346
|
-
if (!mediaOverlaps
|
|
413
|
+
if (!mediaOverlaps) {
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
// Convert from root timegroup timeline to media element's local timeline
|
|
418
|
+
const mediaLocalFromMs = Math.max(0, fromMs - mediaElement.startTimeMs);
|
|
419
|
+
const mediaLocalToMs = Math.min(
|
|
420
|
+
mediaElement.endTimeMs - mediaElement.startTimeMs,
|
|
421
|
+
toMs - mediaElement.startTimeMs,
|
|
422
|
+
);
|
|
423
|
+
|
|
424
|
+
// Skip if no valid local time range
|
|
425
|
+
if (mediaLocalFromMs >= mediaLocalToMs) {
|
|
347
426
|
return;
|
|
348
427
|
}
|
|
349
428
|
|
|
350
|
-
const audio = await mediaElement.fetchAudioSpanningTime(
|
|
429
|
+
const audio = await mediaElement.fetchAudioSpanningTime(
|
|
430
|
+
mediaLocalFromMs, // ✅ Now using media element's local timeline
|
|
431
|
+
mediaLocalToMs, // ✅ Now using media element's local timeline
|
|
432
|
+
abortController.signal,
|
|
433
|
+
);
|
|
351
434
|
if (!audio) {
|
|
352
435
|
throw new Error("Failed to fetch audio");
|
|
353
436
|
}
|
|
@@ -358,16 +441,25 @@ export class EFTimegroup extends EFTemporal(LitElement) {
|
|
|
358
441
|
);
|
|
359
442
|
bufferSource.connect(audioContext.destination);
|
|
360
443
|
|
|
444
|
+
// Calculate timing for placing this audio in the output context
|
|
361
445
|
const ctxStartMs = Math.max(0, mediaElement.startTimeMs - fromMs);
|
|
362
446
|
const ctxEndMs = mediaElement.endTimeMs - fromMs;
|
|
363
447
|
const ctxDurationMs = ctxEndMs - ctxStartMs;
|
|
364
448
|
|
|
365
|
-
|
|
366
|
-
|
|
449
|
+
// Calculate offset within the fetched audio buffer
|
|
450
|
+
// Since we now use local timeline coordinates, audio.startMs is relative to media start
|
|
451
|
+
const requestedOffsetInMedia = mediaLocalFromMs; // Already in local timeline
|
|
452
|
+
const actualOffsetInBuffer = requestedOffsetInMedia - audio.startMs; // Both in local timeline
|
|
453
|
+
|
|
454
|
+
// Ensure offset is never negative (this would cause audio scheduling errors)
|
|
455
|
+
const safeOffset = Math.max(0, actualOffsetInBuffer);
|
|
456
|
+
|
|
457
|
+
if (safeOffset !== actualOffsetInBuffer) {
|
|
458
|
+
}
|
|
367
459
|
|
|
368
460
|
bufferSource.start(
|
|
369
461
|
ctxStartMs / 1000,
|
|
370
|
-
|
|
462
|
+
safeOffset / 1000,
|
|
371
463
|
ctxDurationMs / 1000,
|
|
372
464
|
);
|
|
373
465
|
}),
|
|
@@ -375,8 +467,14 @@ export class EFTimegroup extends EFTemporal(LitElement) {
|
|
|
375
467
|
}
|
|
376
468
|
|
|
377
469
|
async renderAudio(fromMs: number, toMs: number) {
|
|
470
|
+
// Here we determine the number of samples we need to render rather than the duration.
|
|
471
|
+
// We cannot tolerate having more or fewer samples than fit exactlly into AAC frames.
|
|
378
472
|
const durationMs = toMs - fromMs;
|
|
379
|
-
const
|
|
473
|
+
const duration = durationMs / 1000;
|
|
474
|
+
const exactSamples = 48000 * duration;
|
|
475
|
+
const aacFrames = exactSamples / 1024;
|
|
476
|
+
const alignedFrames = Math.round(aacFrames);
|
|
477
|
+
const contextSize = alignedFrames * 1024; // AAC-aligned sample count
|
|
380
478
|
|
|
381
479
|
// Debug logging for audio duration calculations
|
|
382
480
|
if (contextSize <= 0) {
|
|
@@ -400,6 +498,34 @@ export class EFTimegroup extends EFTemporal(LitElement) {
|
|
|
400
498
|
return renderedBuffer;
|
|
401
499
|
}
|
|
402
500
|
|
|
501
|
+
/**
|
|
502
|
+
* TEMPORARY TEST METHOD: Renders audio and immediately plays it back
|
|
503
|
+
* Usage: timegroup.testPlayAudio(0, 5000) // Play first 5 seconds
|
|
504
|
+
*/
|
|
505
|
+
async testPlayAudio(fromMs: number, toMs: number) {
|
|
506
|
+
// Render the audio using the existing renderAudio method
|
|
507
|
+
const renderedBuffer = await this.renderAudio(fromMs, toMs);
|
|
508
|
+
|
|
509
|
+
// Create a regular AudioContext for playback
|
|
510
|
+
const playbackContext = new AudioContext();
|
|
511
|
+
|
|
512
|
+
// Create a buffer source and connect it
|
|
513
|
+
const bufferSource = playbackContext.createBufferSource();
|
|
514
|
+
bufferSource.buffer = renderedBuffer;
|
|
515
|
+
bufferSource.connect(playbackContext.destination);
|
|
516
|
+
|
|
517
|
+
// Start playback immediately
|
|
518
|
+
bufferSource.start(0);
|
|
519
|
+
|
|
520
|
+
// Return a promise that resolves when playback ends
|
|
521
|
+
return new Promise<void>((resolve) => {
|
|
522
|
+
bufferSource.onended = () => {
|
|
523
|
+
playbackContext.close();
|
|
524
|
+
resolve();
|
|
525
|
+
};
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
|
|
403
529
|
async loadMd5Sums() {
|
|
404
530
|
const efElements = this.efElements;
|
|
405
531
|
const loaderTasks: Promise<any>[] = [];
|