@editframe/elements 0.37.3-beta → 0.38.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 +17 -14
- package/dist/EF_FRAMEGEN.js.map +1 -1
- package/dist/EF_RENDERING.js.map +1 -1
- package/dist/canvas/EFCanvas.d.ts +9 -2
- package/dist/canvas/EFCanvas.js +14 -4
- package/dist/canvas/EFCanvas.js.map +1 -1
- package/dist/canvas/EFCanvasItem.d.ts +4 -4
- package/dist/canvas/overlays/SelectionOverlay.d.ts +10 -2
- package/dist/canvas/overlays/SelectionOverlay.js +5 -12
- package/dist/canvas/overlays/SelectionOverlay.js.map +1 -1
- package/dist/canvas/overlays/overlayState.js.map +1 -1
- package/dist/canvas/selection/SelectionController.js.map +1 -1
- package/dist/elements/EFAudio.d.ts +1 -11
- package/dist/elements/EFAudio.js +2 -10
- package/dist/elements/EFAudio.js.map +1 -1
- package/dist/elements/EFCaptions.d.ts +5 -9
- package/dist/elements/EFCaptions.js +34 -11
- package/dist/elements/EFCaptions.js.map +1 -1
- package/dist/elements/EFImage.d.ts +10 -8
- package/dist/elements/EFImage.js +117 -32
- package/dist/elements/EFImage.js.map +1 -1
- package/dist/elements/EFMedia/AssetMediaEngine.js +2 -2
- package/dist/elements/EFMedia/AssetMediaEngine.js.map +1 -1
- package/dist/elements/EFMedia/BaseMediaEngine.js +15 -92
- package/dist/elements/EFMedia/BaseMediaEngine.js.map +1 -1
- package/dist/elements/EFMedia/BufferedSeekingInput.js +10 -11
- package/dist/elements/EFMedia/BufferedSeekingInput.js.map +1 -1
- package/dist/elements/EFMedia/{AssetIdMediaEngine.js → FileMediaEngine.js} +44 -24
- package/dist/elements/EFMedia/FileMediaEngine.js.map +1 -0
- package/dist/elements/EFMedia/JitMediaEngine.js +14 -13
- package/dist/elements/EFMedia/JitMediaEngine.js.map +1 -1
- package/dist/elements/EFMedia/shared/AudioSpanUtils.js +3 -3
- package/dist/elements/EFMedia/shared/AudioSpanUtils.js.map +1 -1
- package/dist/elements/EFMedia/shared/ThumbnailExtractor.js +12 -7
- package/dist/elements/EFMedia/shared/ThumbnailExtractor.js.map +1 -1
- package/dist/elements/EFMedia/shared/timeoutUtils.js +44 -0
- package/dist/elements/EFMedia/shared/timeoutUtils.js.map +1 -0
- package/dist/elements/EFMedia/videoTasks/MainVideoInputCache.js +1 -1
- package/dist/elements/EFMedia/videoTasks/MainVideoInputCache.js.map +1 -1
- package/dist/elements/EFMedia/videoTasks/ScrubInputCache.js +4 -4
- package/dist/elements/EFMedia/videoTasks/ScrubInputCache.js.map +1 -1
- package/dist/elements/EFMedia.d.ts +14 -8
- package/dist/elements/EFMedia.js +52 -19
- package/dist/elements/EFMedia.js.map +1 -1
- package/dist/elements/EFPanZoom.d.ts +2 -2
- package/dist/elements/EFPanZoom.js +1 -1
- package/dist/elements/EFPanZoom.js.map +1 -1
- package/dist/elements/EFSourceMixin.js +16 -8
- package/dist/elements/EFSourceMixin.js.map +1 -1
- package/dist/elements/EFSurface.d.ts +7 -10
- package/dist/elements/EFSurface.js +4 -43
- package/dist/elements/EFSurface.js.map +1 -1
- package/dist/elements/EFTemporal.d.ts +33 -8
- package/dist/elements/EFTemporal.js +92 -40
- package/dist/elements/EFTemporal.js.map +1 -1
- package/dist/elements/EFText.d.ts +3 -0
- package/dist/elements/EFText.js +54 -21
- package/dist/elements/EFText.js.map +1 -1
- package/dist/elements/EFTextSegment.js +8 -4
- package/dist/elements/EFTextSegment.js.map +1 -1
- package/dist/elements/EFTimegroup.d.ts +26 -43
- package/dist/elements/EFTimegroup.js +295 -314
- package/dist/elements/EFTimegroup.js.map +1 -1
- package/dist/elements/EFVideo.d.ts +44 -42
- package/dist/elements/EFVideo.js +259 -172
- package/dist/elements/EFVideo.js.map +1 -1
- package/dist/elements/EFWaveform.d.ts +3 -8
- package/dist/elements/EFWaveform.js +18 -13
- package/dist/elements/EFWaveform.js.map +1 -1
- package/dist/elements/ElementPositionInfo.js.map +1 -1
- package/dist/elements/FetchMixin.js.map +1 -1
- package/dist/elements/TargetController.d.ts +0 -3
- package/dist/elements/TargetController.js +12 -35
- package/dist/elements/TargetController.js.map +1 -1
- package/dist/elements/TimegroupController.js.map +1 -1
- package/dist/elements/cloneFactoryRegistry.d.ts +14 -0
- package/dist/elements/cloneFactoryRegistry.js +15 -0
- package/dist/elements/cloneFactoryRegistry.js.map +1 -0
- package/dist/elements/renderTemporalAudio.js +8 -6
- package/dist/elements/renderTemporalAudio.js.map +1 -1
- package/dist/elements/setupTemporalHierarchy.js +62 -0
- package/dist/elements/setupTemporalHierarchy.js.map +1 -0
- package/dist/elements/updateAnimations.js +62 -87
- package/dist/elements/updateAnimations.js.map +1 -1
- package/dist/getRenderInfo.d.ts +3 -2
- package/dist/getRenderInfo.js +20 -4
- package/dist/getRenderInfo.js.map +1 -1
- package/dist/gui/ContextMixin.js +68 -12
- package/dist/gui/ContextMixin.js.map +1 -1
- package/dist/gui/Controllable.js +1 -1
- package/dist/gui/Controllable.js.map +1 -1
- package/dist/gui/EFActiveRootTemporal.d.ts +4 -4
- package/dist/gui/EFActiveRootTemporal.js.map +1 -1
- package/dist/gui/EFControls.d.ts +2 -2
- package/dist/gui/EFControls.js +2 -2
- package/dist/gui/EFControls.js.map +1 -1
- package/dist/gui/EFDial.d.ts +4 -4
- package/dist/gui/EFDial.js +12 -9
- package/dist/gui/EFDial.js.map +1 -1
- package/dist/gui/EFFilmstrip.d.ts +2 -0
- package/dist/gui/EFFilmstrip.js +18 -10
- package/dist/gui/EFFilmstrip.js.map +1 -1
- package/dist/gui/EFFitScale.d.ts +28 -4
- package/dist/gui/EFFitScale.js +88 -26
- package/dist/gui/EFFitScale.js.map +1 -1
- package/dist/gui/EFFocusOverlay.d.ts +4 -4
- package/dist/gui/EFFocusOverlay.js +3 -3
- package/dist/gui/EFFocusOverlay.js.map +1 -1
- package/dist/gui/EFOverlayItem.d.ts +4 -4
- package/dist/gui/EFOverlayLayer.d.ts +4 -4
- package/dist/gui/EFPause.d.ts +4 -4
- package/dist/gui/EFPause.js +1 -1
- package/dist/gui/EFPlay.d.ts +4 -4
- package/dist/gui/EFPlay.js +1 -1
- package/dist/gui/EFPreview.js +1 -1
- package/dist/gui/EFResizableBox.d.ts +4 -4
- package/dist/gui/EFResizableBox.js +5 -5
- package/dist/gui/EFResizableBox.js.map +1 -1
- package/dist/gui/EFScrubber.d.ts +4 -4
- package/dist/gui/EFScrubber.js +8 -13
- package/dist/gui/EFScrubber.js.map +1 -1
- package/dist/gui/EFTimeDisplay.d.ts +8 -4
- package/dist/gui/EFTimeDisplay.js +25 -7
- package/dist/gui/EFTimeDisplay.js.map +1 -1
- package/dist/gui/EFTimelineRuler.d.ts +4 -4
- package/dist/gui/EFTimelineRuler.js +3 -3
- package/dist/gui/EFTimelineRuler.js.map +1 -1
- package/dist/gui/EFToggleLoop.d.ts +4 -4
- package/dist/gui/EFToggleLoop.js +1 -1
- package/dist/gui/EFTogglePlay.d.ts +4 -4
- package/dist/gui/EFTogglePlay.js +1 -1
- package/dist/gui/EFTransformHandles.d.ts +4 -4
- package/dist/gui/EFTransformHandles.js +6 -6
- package/dist/gui/EFTransformHandles.js.map +1 -1
- package/dist/gui/EFWorkbench.d.ts +40 -36
- package/dist/gui/EFWorkbench.js +436 -822
- package/dist/gui/EFWorkbench.js.map +1 -1
- package/dist/gui/FitScaleHelpers.js.map +1 -1
- package/dist/gui/PlaybackController.d.ts +3 -8
- package/dist/gui/PlaybackController.js +59 -56
- package/dist/gui/PlaybackController.js.map +1 -1
- package/dist/gui/TWMixin.js +1 -1
- package/dist/gui/TWMixin.js.map +1 -1
- package/dist/gui/TargetOrContextMixin.js +43 -6
- package/dist/gui/TargetOrContextMixin.js.map +1 -1
- package/dist/gui/ef-theme.css +136 -0
- package/dist/gui/hierarchy/EFHierarchy.d.ts +2 -2
- package/dist/gui/hierarchy/EFHierarchy.js +14 -24
- package/dist/gui/hierarchy/EFHierarchy.js.map +1 -1
- package/dist/gui/hierarchy/EFHierarchyItem.d.ts +3 -3
- package/dist/gui/hierarchy/EFHierarchyItem.js +22 -10
- package/dist/gui/hierarchy/EFHierarchyItem.js.map +1 -1
- package/dist/gui/icons.js.map +1 -1
- package/dist/gui/previewSettingsContext.d.ts +18 -0
- package/dist/gui/previewSettingsContext.js.map +1 -1
- package/dist/gui/theme.js +34 -0
- package/dist/gui/theme.js.map +1 -0
- package/dist/gui/timeline/EFTimeline.d.ts +2 -2
- package/dist/gui/timeline/EFTimeline.js +70 -52
- package/dist/gui/timeline/EFTimeline.js.map +1 -1
- package/dist/gui/timeline/EFTimelineRow.d.ts +3 -1
- package/dist/gui/timeline/EFTimelineRow.js +55 -32
- package/dist/gui/timeline/EFTimelineRow.js.map +1 -1
- package/dist/gui/timeline/TrimHandles.d.ts +23 -9
- package/dist/gui/timeline/TrimHandles.js +224 -51
- package/dist/gui/timeline/TrimHandles.js.map +1 -1
- package/dist/gui/timeline/flattenHierarchy.js.map +1 -1
- package/dist/gui/timeline/timelineEditingContext.d.ts +34 -0
- package/dist/gui/timeline/timelineEditingContext.js +24 -0
- package/dist/gui/timeline/timelineEditingContext.js.map +1 -0
- package/dist/gui/timeline/timelineStateContext.js.map +1 -1
- package/dist/gui/timeline/tracks/AudioTrack.js +1 -1
- package/dist/gui/timeline/tracks/AudioTrack.js.map +1 -1
- package/dist/gui/timeline/tracks/CaptionsTrack.d.ts +2 -3
- package/dist/gui/timeline/tracks/CaptionsTrack.js +17 -75
- package/dist/gui/timeline/tracks/CaptionsTrack.js.map +1 -1
- package/dist/gui/timeline/tracks/EFThumbnailStrip.d.ts +52 -0
- package/dist/gui/timeline/tracks/EFThumbnailStrip.js +596 -0
- package/dist/gui/timeline/tracks/EFThumbnailStrip.js.map +1 -0
- package/dist/gui/timeline/tracks/HTMLTrack.js.map +1 -1
- package/dist/gui/timeline/tracks/ImageTrack.js.map +1 -1
- package/dist/gui/timeline/tracks/TextTrack.d.ts +3 -2
- package/dist/gui/timeline/tracks/TextTrack.js +17 -43
- package/dist/gui/timeline/tracks/TextTrack.js.map +1 -1
- package/dist/gui/timeline/tracks/TimegroupTrack.d.ts +3 -4
- package/dist/gui/timeline/tracks/TimegroupTrack.js +33 -23
- package/dist/gui/timeline/tracks/TimegroupTrack.js.map +1 -1
- package/dist/gui/timeline/tracks/TrackItem.d.ts +7 -9
- package/dist/gui/timeline/tracks/TrackItem.js +18 -17
- package/dist/gui/timeline/tracks/TrackItem.js.map +1 -1
- package/dist/gui/timeline/tracks/VideoTrack.d.ts +3 -3
- package/dist/gui/timeline/tracks/VideoTrack.js +11 -14
- package/dist/gui/timeline/tracks/VideoTrack.js.map +1 -1
- package/dist/gui/timeline/tracks/WaveformTrack.js.map +1 -1
- package/dist/gui/timeline/tracks/renderTrackChildren.js.map +1 -1
- package/dist/gui/timeline/tracks/waveformUtils.js +1 -1
- package/dist/gui/timeline/tracks/waveformUtils.js.map +1 -1
- package/dist/gui/tree/EFTree.d.ts +4 -4
- package/dist/gui/tree/EFTree.js +8 -14
- package/dist/gui/tree/EFTree.js.map +1 -1
- package/dist/gui/tree/EFTreeItem.d.ts +4 -4
- package/dist/gui/tree/EFTreeItem.js +3 -3
- package/dist/gui/tree/EFTreeItem.js.map +1 -1
- package/dist/gui/tree/treeContext.js.map +1 -1
- package/dist/index.d.ts +10 -8
- package/dist/index.js +6 -5
- package/dist/index.js.map +1 -1
- package/dist/node.d.ts +2 -2
- package/dist/node.js +2 -2
- package/dist/preview/AdaptiveResolutionTracker.js +3 -3
- package/dist/preview/AdaptiveResolutionTracker.js.map +1 -1
- package/dist/preview/FrameController.d.ts +2 -17
- package/dist/preview/FrameController.js +40 -63
- package/dist/preview/FrameController.js.map +1 -1
- package/dist/preview/QualityUpgradeScheduler.d.ts +76 -0
- package/dist/preview/QualityUpgradeScheduler.js +158 -0
- package/dist/preview/QualityUpgradeScheduler.js.map +1 -0
- package/dist/preview/RenderContext.d.ts +119 -1
- package/dist/preview/RenderContext.js +21 -3
- package/dist/preview/RenderContext.js.map +1 -1
- package/dist/preview/RenderProfiler.js.map +1 -1
- package/dist/preview/RenderStats.js +85 -0
- package/dist/preview/RenderStats.js.map +1 -0
- package/dist/preview/encoding/canvasEncoder.js +2 -52
- package/dist/preview/encoding/canvasEncoder.js.map +1 -1
- package/dist/preview/encoding/mainThreadEncoder.js.map +1 -1
- package/dist/preview/encoding/workerEncoder.js.map +1 -1
- package/dist/preview/logger.js.map +1 -1
- package/dist/preview/previewSettings.d.ts +34 -0
- package/dist/preview/previewSettings.js +29 -17
- package/dist/preview/previewSettings.js.map +1 -1
- package/dist/preview/previewTypes.js +4 -4
- package/dist/preview/previewTypes.js.map +1 -1
- package/dist/preview/renderElementToCanvas.d.ts +44 -0
- package/dist/preview/renderElementToCanvas.js +72 -0
- package/dist/preview/renderElementToCanvas.js.map +1 -0
- package/dist/preview/renderTimegroupToCanvas.js +267 -145
- package/dist/preview/renderTimegroupToCanvas.js.map +1 -1
- package/dist/preview/renderTimegroupToCanvas.types.d.ts +30 -0
- package/dist/preview/renderTimegroupToVideo.js +85 -105
- package/dist/preview/renderTimegroupToVideo.js.map +1 -1
- package/dist/preview/{renderTimegroupToVideo.d.ts → renderTimegroupToVideo.types.d.ts} +9 -9
- package/dist/preview/renderVideoToVideo.js +286 -0
- package/dist/preview/renderVideoToVideo.js.map +1 -0
- package/dist/preview/renderers.js.map +1 -1
- package/dist/preview/rendering/ScaleConfig.js +74 -0
- package/dist/preview/rendering/ScaleConfig.js.map +1 -0
- package/dist/preview/rendering/inlineImages.js +1 -44
- package/dist/preview/rendering/inlineImages.js.map +1 -1
- package/dist/preview/rendering/loadImage.js +22 -0
- package/dist/preview/rendering/loadImage.js.map +1 -0
- package/dist/preview/rendering/renderToImageNative.js +3 -3
- package/dist/preview/rendering/renderToImageNative.js.map +1 -1
- package/dist/preview/rendering/serializeTimelineDirect.js +224 -68
- package/dist/preview/rendering/serializeTimelineDirect.js.map +1 -1
- package/dist/preview/statsTrackingStrategy.js +1 -101
- package/dist/preview/statsTrackingStrategy.js.map +1 -1
- package/dist/preview/workers/WorkerPool.js +0 -1
- package/dist/preview/workers/WorkerPool.js.map +1 -1
- package/dist/preview/workers/encoderWorkerInline.js +21 -54
- package/dist/preview/workers/encoderWorkerInline.js.map +1 -1
- package/dist/render/EFRenderAPI.d.ts +2 -1
- package/dist/render/EFRenderAPI.js +12 -36
- package/dist/render/EFRenderAPI.js.map +1 -1
- package/dist/render/getRenderData.js +4 -4
- package/dist/render/getRenderData.js.map +1 -1
- package/dist/style.css +114 -163
- package/dist/transcoding/cache/RequestDeduplicator.js +1 -0
- package/dist/transcoding/cache/RequestDeduplicator.js.map +1 -1
- package/dist/transcoding/types/index.d.ts +1 -1
- package/dist/transcoding/utils/UrlGenerator.js +10 -3
- package/dist/transcoding/utils/UrlGenerator.js.map +1 -1
- package/dist/utils/LRUCache.js +1 -0
- package/dist/utils/LRUCache.js.map +1 -1
- package/dist/utils/frameTime.js +23 -1
- package/dist/utils/frameTime.js.map +1 -1
- package/package.json +21 -8
- package/scripts/build-css.js +8 -1
- package/test/setup.ts +0 -1
- package/test/useAssetMSW.ts +50 -0
- package/test/visualRegressionUtils.ts +23 -9
- package/dist/_virtual/rolldown_runtime.js +0 -27
- package/dist/elements/EFMedia/AssetIdMediaEngine.js.map +0 -1
- package/dist/elements/EFThumbnailStrip.d.ts +0 -167
- package/dist/elements/EFThumbnailStrip.js +0 -731
- package/dist/elements/EFThumbnailStrip.js.map +0 -1
- package/dist/elements/SessionThumbnailCache.js +0 -154
- package/dist/elements/SessionThumbnailCache.js.map +0 -1
- package/dist/node_modules/react/cjs/react-jsx-runtime.development.js +0 -688
- package/dist/node_modules/react/cjs/react-jsx-runtime.development.js.map +0 -1
- package/dist/node_modules/react/cjs/react.development.js +0 -1521
- package/dist/node_modules/react/cjs/react.development.js.map +0 -1
- package/dist/node_modules/react/index.js +0 -13
- package/dist/node_modules/react/index.js.map +0 -1
- package/dist/node_modules/react/jsx-runtime.js +0 -13
- package/dist/node_modules/react/jsx-runtime.js.map +0 -1
- package/dist/preview/encoding/types.d.ts +0 -1
- package/dist/preview/renderTimegroupPreview.js +0 -686
- package/dist/preview/renderTimegroupPreview.js.map +0 -1
- package/dist/preview/renderTimegroupToCanvas.d.ts +0 -42
- package/dist/preview/rendering/renderToImage.d.ts +0 -2
- package/dist/preview/rendering/renderToImage.js +0 -95
- package/dist/preview/rendering/renderToImage.js.map +0 -1
- package/dist/preview/rendering/renderToImageForeignObject.js +0 -163
- package/dist/preview/rendering/renderToImageForeignObject.js.map +0 -1
- package/dist/preview/rendering/renderToImageNative.d.ts +0 -1
- package/dist/preview/rendering/svgSerializer.js +0 -43
- package/dist/preview/rendering/svgSerializer.js.map +0 -1
- package/dist/preview/rendering/types.d.ts +0 -2
- package/dist/preview/thumbnailCacheSettings.js +0 -52
- package/dist/preview/thumbnailCacheSettings.js.map +0 -1
- package/dist/sandbox/PlaybackControls.d.ts +0 -1
- package/dist/sandbox/PlaybackControls.js +0 -10
- package/dist/sandbox/PlaybackControls.js.map +0 -1
- package/dist/sandbox/ScenarioRunner.d.ts +0 -1
- package/dist/sandbox/ScenarioRunner.js +0 -1
- package/dist/sandbox/defineSandbox.d.ts +0 -1
- package/dist/sandbox/index.d.ts +0 -3
- package/dist/sandbox/index.js +0 -2
- package/test/EFVideo.framegen.browsertest.ts +0 -80
- package/test/thumbnail-performance-test.html +0 -116
|
@@ -1,22 +1,21 @@
|
|
|
1
1
|
import { quantizeToFrameTimeS } from "../utils/frameTime.js";
|
|
2
|
+
import { getCloneFactory } from "./cloneFactoryRegistry.js";
|
|
2
3
|
import { EF_RENDERING } from "../EF_RENDERING.js";
|
|
3
|
-
import { evaluateAnimationVisibilityState, updateAnimations } from "./updateAnimations.js";
|
|
4
|
-
import { parseTimeToMs } from "./parseTimeToMs.js";
|
|
5
|
-
import { __decorate } from "../_virtual/_@oxc-project_runtime@0.95.0/helpers/decorate.js";
|
|
6
|
-
import { EFTemporal, deepGetElementsWithFrameTasks, flushStartTimeMsCache, registerIsTimegroupCalculatingDuration, resetTemporalCache, shallowGetTemporalElements, timegroupContext } from "./EFTemporal.js";
|
|
7
4
|
import { efContext } from "../gui/efContext.js";
|
|
8
|
-
import { isContextMixin } from "../gui/ContextMixin.js";
|
|
9
5
|
import { TWMixin } from "../gui/TWMixin2.js";
|
|
10
6
|
import { isTracingEnabled, withSpan } from "../otel/tracingHelpers.js";
|
|
11
7
|
import { FrameController, PRIORITY_DEFAULT } from "../preview/FrameController.js";
|
|
8
|
+
import { QualityUpgradeScheduler } from "../preview/QualityUpgradeScheduler.js";
|
|
9
|
+
import { updateAnimations } from "./updateAnimations.js";
|
|
10
|
+
import { parseTimeToMs } from "./parseTimeToMs.js";
|
|
11
|
+
import { __decorate } from "../_virtual/_@oxc-project_runtime@0.95.0/helpers/decorate.js";
|
|
12
|
+
import { EFTemporal, flushStartTimeMsCache, registerIsTimegroupCalculatingDuration, resetTemporalCache, shallowGetTemporalElements, timegroupContext } from "./EFTemporal.js";
|
|
12
13
|
import { renderTemporalAudio } from "./renderTemporalAudio.js";
|
|
13
14
|
import { EFTargetable } from "./TargetController.js";
|
|
14
15
|
import { deepGetMediaElements } from "./EFMedia.js";
|
|
15
16
|
import { TimegroupController } from "./TimegroupController.js";
|
|
16
17
|
import { getContainerInfoFromElement } from "./ContainerInfo.js";
|
|
17
18
|
import { getPositionInfoFromElement } from "./ElementPositionInfo.js";
|
|
18
|
-
import { captureFromClone, captureTimegroupAtTime } from "../preview/renderTimegroupToCanvas.js";
|
|
19
|
-
import { renderTimegroupToVideo } from "../preview/renderTimegroupToVideo.js";
|
|
20
19
|
import "../canvas/EFCanvas.js";
|
|
21
20
|
import "../gui/hierarchy/EFHierarchy.js";
|
|
22
21
|
import "../gui/EFFilmstrip.js";
|
|
@@ -29,10 +28,9 @@ import { LitElement, css, html } from "lit";
|
|
|
29
28
|
import { customElement, property } from "lit/decorators.js";
|
|
30
29
|
|
|
31
30
|
//#region src/elements/EFTimegroup.ts
|
|
32
|
-
var _EFTimegroup;
|
|
33
31
|
const log = debug("ef:elements:EFTimegroup");
|
|
34
|
-
const INITIALIZER_ERROR_THRESHOLD_MS =
|
|
35
|
-
const INITIALIZER_WARN_THRESHOLD_MS =
|
|
32
|
+
const INITIALIZER_ERROR_THRESHOLD_MS = 2e3;
|
|
33
|
+
const INITIALIZER_WARN_THRESHOLD_MS = 100;
|
|
36
34
|
let durationCache = /* @__PURE__ */ new WeakMap();
|
|
37
35
|
const flushDurationCache = () => {
|
|
38
36
|
durationCache = /* @__PURE__ */ new WeakMap();
|
|
@@ -176,34 +174,14 @@ function evaluateSeekTarget(requestedTime, durationMs, fps) {
|
|
|
176
174
|
return Math.max(0, Math.min(quantizedTime, durationMs / 1e3));
|
|
177
175
|
}
|
|
178
176
|
let EFTimegroup = class EFTimegroup$1 extends EFTargetable(EFTemporal(TWMixin(LitElement))) {
|
|
179
|
-
static {
|
|
180
|
-
_EFTimegroup = this;
|
|
181
|
-
}
|
|
182
177
|
constructor(..._args) {
|
|
183
178
|
super(..._args);
|
|
184
179
|
this._timeGroupContext = this;
|
|
185
180
|
this.efContext = this;
|
|
186
|
-
this.mode = "contain";
|
|
187
|
-
this.overlapMs = 0;
|
|
188
181
|
this.fps = 30;
|
|
189
182
|
this.autoInit = false;
|
|
190
183
|
this.workbench = false;
|
|
191
184
|
this.fit = "none";
|
|
192
|
-
this.frameTask = (() => {
|
|
193
|
-
const self = this;
|
|
194
|
-
const taskObj = {
|
|
195
|
-
run: () => {
|
|
196
|
-
self.#frameTaskAbortController?.abort();
|
|
197
|
-
self.#frameTaskAbortController = new AbortController();
|
|
198
|
-
const signal = self.#frameTaskAbortController.signal;
|
|
199
|
-
self.#frameTaskPromise = self.#runFrameTask(signal);
|
|
200
|
-
taskObj.taskComplete = self.#frameTaskPromise;
|
|
201
|
-
return self.#frameTaskPromise;
|
|
202
|
-
},
|
|
203
|
-
taskComplete: Promise.resolve()
|
|
204
|
-
};
|
|
205
|
-
return taskObj;
|
|
206
|
-
})();
|
|
207
185
|
this.seekTask = (() => {
|
|
208
186
|
const self = this;
|
|
209
187
|
const taskObj = {
|
|
@@ -251,25 +229,95 @@ let EFTimegroup = class EFTimegroup$1 extends EFTargetable(EFTemporal(TWMixin(Li
|
|
|
251
229
|
}
|
|
252
230
|
`;
|
|
253
231
|
}
|
|
232
|
+
#trackedChildren = /* @__PURE__ */ new Set();
|
|
233
|
+
shouldAutoReady() {
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
236
|
+
#childReadyStateHandler = () => {
|
|
237
|
+
this.#recomputeAggregateReadyState();
|
|
238
|
+
};
|
|
239
|
+
#childContentChangeHandler = (e) => {
|
|
240
|
+
const detail = e.detail;
|
|
241
|
+
this.emitContentChange(detail?.reason ?? "content");
|
|
242
|
+
};
|
|
243
|
+
#recomputeAggregateReadyState() {
|
|
244
|
+
const children = shallowGetTemporalElements(this);
|
|
245
|
+
if (children.length === 0) {
|
|
246
|
+
this.setContentReadyState("ready");
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
let hasLoading = false;
|
|
250
|
+
let hasError = false;
|
|
251
|
+
let hasIdle = false;
|
|
252
|
+
for (const child of children) {
|
|
253
|
+
const state$1 = child.contentReadyState;
|
|
254
|
+
if (state$1 === "loading") hasLoading = true;
|
|
255
|
+
else if (state$1 === "error") hasError = true;
|
|
256
|
+
else if (state$1 === "idle") hasIdle = true;
|
|
257
|
+
}
|
|
258
|
+
if (hasError) this.setContentReadyState("error");
|
|
259
|
+
else if (hasLoading) this.setContentReadyState("loading");
|
|
260
|
+
else if (hasIdle) this.setContentReadyState("loading");
|
|
261
|
+
else this.setContentReadyState("ready");
|
|
262
|
+
}
|
|
263
|
+
#syncChildListeners() {
|
|
264
|
+
const currentChildren = new Set(shallowGetTemporalElements(this));
|
|
265
|
+
for (const child of this.#trackedChildren) if (!currentChildren.has(child)) {
|
|
266
|
+
child.removeEventListener("readystatechange", this.#childReadyStateHandler);
|
|
267
|
+
child.removeEventListener("contentchange", this.#childContentChangeHandler);
|
|
268
|
+
}
|
|
269
|
+
for (const child of currentChildren) if (!this.#trackedChildren.has(child)) {
|
|
270
|
+
child.addEventListener("readystatechange", this.#childReadyStateHandler);
|
|
271
|
+
child.addEventListener("contentchange", this.#childContentChangeHandler);
|
|
272
|
+
}
|
|
273
|
+
this.#trackedChildren = currentChildren;
|
|
274
|
+
this.#recomputeAggregateReadyState();
|
|
275
|
+
}
|
|
276
|
+
/** @public */
|
|
277
|
+
#mode = "contain";
|
|
278
|
+
get mode() {
|
|
279
|
+
return this.#mode;
|
|
280
|
+
}
|
|
281
|
+
set mode(value) {
|
|
282
|
+
if (this.#mode === value) return;
|
|
283
|
+
const old = this.#mode;
|
|
284
|
+
this.#mode = value;
|
|
285
|
+
this.requestUpdate("mode", old);
|
|
286
|
+
if (this.getAttribute("mode") !== value) this.setAttribute("mode", value);
|
|
287
|
+
}
|
|
288
|
+
/** @public */
|
|
289
|
+
#overlapMs = 0;
|
|
290
|
+
get overlapMs() {
|
|
291
|
+
return this.#overlapMs;
|
|
292
|
+
}
|
|
293
|
+
set overlapMs(value) {
|
|
294
|
+
if (this.#overlapMs === value) return;
|
|
295
|
+
const old = this.#overlapMs;
|
|
296
|
+
this.#overlapMs = value;
|
|
297
|
+
this.requestUpdate("overlapMs", old);
|
|
298
|
+
const attrVal = value > 0 ? `${value}ms` : null;
|
|
299
|
+
if (attrVal && this.getAttribute("overlap") !== attrVal) this.setAttribute("overlap", attrVal);
|
|
300
|
+
else if (!attrVal && this.hasAttribute("overlap")) this.removeAttribute("overlap");
|
|
301
|
+
}
|
|
254
302
|
#initializer;
|
|
255
303
|
/**
|
|
256
304
|
* Initializer function for setting up JavaScript behavior on this timegroup.
|
|
257
305
|
* This function is called ONCE per instance - on the prime timeline when first connected,
|
|
258
306
|
* and on each render clone when created.
|
|
259
|
-
*
|
|
307
|
+
*
|
|
260
308
|
* Use this to register frame callbacks, set up event listeners, or initialize state.
|
|
261
309
|
* The same initializer code runs on both prime and clones, eliminating duplication.
|
|
262
|
-
*
|
|
310
|
+
*
|
|
263
311
|
* CONSTRAINTS:
|
|
264
312
|
* - MUST be synchronous (no async/await, no Promise return)
|
|
265
313
|
* - MUST complete in <100ms (error thrown) or <10ms (warning logged)
|
|
266
314
|
* - Should only register callbacks and set up behavior, not do expensive work
|
|
267
|
-
*
|
|
315
|
+
*
|
|
268
316
|
* TIMING:
|
|
269
317
|
* - If set before element connects to DOM: runs automatically after connectedCallback
|
|
270
318
|
* - If set after element is connected: runs immediately
|
|
271
319
|
* - Clones automatically copy and run the initializer when created
|
|
272
|
-
*
|
|
320
|
+
*
|
|
273
321
|
* @example
|
|
274
322
|
* ```javascript
|
|
275
323
|
* const tg = document.querySelector('ef-timegroup');
|
|
@@ -287,29 +335,12 @@ let EFTimegroup = class EFTimegroup$1 extends EFTargetable(EFTemporal(TWMixin(Li
|
|
|
287
335
|
}
|
|
288
336
|
set initializer(fn) {
|
|
289
337
|
this.#initializer = fn;
|
|
290
|
-
if (fn && this.isConnected && !this.#initializerHasRun) this.#initializerComplete = this.updateComplete.then(() => {
|
|
291
|
-
this.#runInitializer();
|
|
292
|
-
});
|
|
293
338
|
}
|
|
294
339
|
/**
|
|
295
340
|
* Track if initializer has run on this instance to prevent double execution.
|
|
296
341
|
* @internal
|
|
297
342
|
*/
|
|
298
343
|
#initializerHasRun = false;
|
|
299
|
-
/**
|
|
300
|
-
* Promise that resolves when initializer completes.
|
|
301
|
-
* Used by createRenderClone to ensure frame tasks are registered before rendering.
|
|
302
|
-
* @internal
|
|
303
|
-
*/
|
|
304
|
-
#initializerComplete;
|
|
305
|
-
/**
|
|
306
|
-
* Public accessor for initializer completion promise.
|
|
307
|
-
* Allows createRenderClone to wait for initializer before rendering.
|
|
308
|
-
* @internal
|
|
309
|
-
*/
|
|
310
|
-
get initializerComplete() {
|
|
311
|
-
return this.#initializerComplete;
|
|
312
|
-
}
|
|
313
344
|
attributeChangedCallback(name, old, value) {
|
|
314
345
|
if (name === "mode" && value) this.mode = value;
|
|
315
346
|
if (name === "overlap" && value) this.overlapMs = parseTimeToMs(value);
|
|
@@ -352,6 +383,18 @@ let EFTimegroup = class EFTimegroup$1 extends EFTargetable(EFTemporal(TWMixin(Li
|
|
|
352
383
|
return this.#frameController;
|
|
353
384
|
}
|
|
354
385
|
/**
|
|
386
|
+
* Centralized quality upgrade scheduler for coordinating main-quality segment fetching.
|
|
387
|
+
* Lives alongside FrameController to manage background quality upgrades.
|
|
388
|
+
*/
|
|
389
|
+
#qualityUpgradeScheduler = new QualityUpgradeScheduler({ requestFrameRender: () => this.requestFrameRender() });
|
|
390
|
+
/**
|
|
391
|
+
* Get the quality upgrade scheduler for background segment fetching.
|
|
392
|
+
* @public
|
|
393
|
+
*/
|
|
394
|
+
get qualityUpgradeScheduler() {
|
|
395
|
+
return this.#qualityUpgradeScheduler;
|
|
396
|
+
}
|
|
397
|
+
/**
|
|
355
398
|
* Query timegroup's readiness state for a given time.
|
|
356
399
|
* Timegroups are always ready (no async preparation needed).
|
|
357
400
|
* @public
|
|
@@ -406,9 +449,28 @@ let EFTimegroup = class EFTimegroup$1 extends EFTargetable(EFTemporal(TWMixin(Li
|
|
|
406
449
|
incrementContentEpoch() {
|
|
407
450
|
this.#contentEpoch++;
|
|
408
451
|
}
|
|
452
|
+
/**
|
|
453
|
+
* Request a frame re-render at the current time.
|
|
454
|
+
*
|
|
455
|
+
* Use this when the source-to-timeline mapping has changed (e.g., sourcein/sourceout)
|
|
456
|
+
* but currentTimeMs hasn't. The FrameController only re-renders when currentTimeMs
|
|
457
|
+
* or durationMs change, so this provides a way for child elements to request a
|
|
458
|
+
* re-render when their internal state changes the visual output.
|
|
459
|
+
* @public
|
|
460
|
+
*/
|
|
461
|
+
requestFrameRender() {
|
|
462
|
+
this.#runThrottledFrameTask();
|
|
463
|
+
}
|
|
409
464
|
async #runThrottledFrameTask() {
|
|
410
465
|
if (this.playbackController) return this.playbackController.runThrottledFrameTask();
|
|
411
|
-
|
|
466
|
+
try {
|
|
467
|
+
await this.#frameController.renderFrame(this.currentTimeMs, { onAnimationsUpdate: (root) => {
|
|
468
|
+
updateAnimations(root);
|
|
469
|
+
} });
|
|
470
|
+
} catch (error) {
|
|
471
|
+
if (error instanceof DOMException && error.name === "AbortError") return;
|
|
472
|
+
console.error("FrameController error:", error);
|
|
473
|
+
}
|
|
412
474
|
}
|
|
413
475
|
/** @public */
|
|
414
476
|
set currentTime(time) {
|
|
@@ -432,8 +494,10 @@ let EFTimegroup = class EFTimegroup$1 extends EFTargetable(EFTemporal(TWMixin(Li
|
|
|
432
494
|
this.#currentTime = seekTarget;
|
|
433
495
|
this.#userTimeMs = seekTarget * 1e3;
|
|
434
496
|
this.#seekInProgress = true;
|
|
435
|
-
this.seekTask.run().catch(() => {}).finally(() => {
|
|
497
|
+
Promise.resolve(this.seekTask.run()).catch(() => {}).finally(async () => {
|
|
436
498
|
this.#seekInProgress = false;
|
|
499
|
+
const { updateAnimations: updateAnimations$1 } = await import("./updateAnimations.js");
|
|
500
|
+
updateAnimations$1(this);
|
|
437
501
|
if (this.#pendingSeekTime !== void 0 && this.#pendingSeekTime !== seekTarget) {
|
|
438
502
|
const pendingTime = this.#pendingSeekTime;
|
|
439
503
|
this.#pendingSeekTime = void 0;
|
|
@@ -474,7 +538,7 @@ let EFTimegroup = class EFTimegroup$1 extends EFTargetable(EFTemporal(TWMixin(Li
|
|
|
474
538
|
*
|
|
475
539
|
* Combines seeking (Purpose 3) with frame rendering (Purpose 4) to ensure
|
|
476
540
|
* all visible elements are ready after the seek completes.
|
|
477
|
-
*
|
|
541
|
+
*
|
|
478
542
|
* Updates both the source time AND userTimeMs (what the preview displays).
|
|
479
543
|
*
|
|
480
544
|
* @param timeMs - Time in milliseconds to seek to
|
|
@@ -486,12 +550,9 @@ let EFTimegroup = class EFTimegroup$1 extends EFTargetable(EFTemporal(TWMixin(Li
|
|
|
486
550
|
this.currentTimeMs = timeMs;
|
|
487
551
|
await this.seekTask.taskComplete;
|
|
488
552
|
if (this.playbackController) this.saveTimeToLocalStorage(this.currentTime);
|
|
489
|
-
await this.
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
if ("waitForFrameReady" in element && typeof element.waitForFrameReady === "function") await element.waitForFrameReady();
|
|
493
|
-
else await element.updateComplete;
|
|
494
|
-
}));
|
|
553
|
+
await this.#frameController.renderFrame(timeMs, { onAnimationsUpdate: (root) => {
|
|
554
|
+
updateAnimations(root);
|
|
555
|
+
} });
|
|
495
556
|
}
|
|
496
557
|
/**
|
|
497
558
|
* Optimized seek for render loops.
|
|
@@ -499,9 +560,9 @@ let EFTimegroup = class EFTimegroup$1 extends EFTargetable(EFTemporal(TWMixin(Li
|
|
|
499
560
|
* - Skips waitForMediaDurations (already loaded at render setup)
|
|
500
561
|
* - Skips localStorage persistence
|
|
501
562
|
* - Uses FrameController for centralized element coordination
|
|
502
|
-
*
|
|
563
|
+
*
|
|
503
564
|
* Still waits for all content to be ready (Lit updates, element preparation, rendering).
|
|
504
|
-
*
|
|
565
|
+
*
|
|
505
566
|
* @param timeMs - Time in milliseconds to seek to
|
|
506
567
|
* @internal
|
|
507
568
|
*/
|
|
@@ -509,15 +570,21 @@ let EFTimegroup = class EFTimegroup$1 extends EFTargetable(EFTemporal(TWMixin(Li
|
|
|
509
570
|
const newTime = timeMs / 1e3;
|
|
510
571
|
this.#userTimeMs = timeMs;
|
|
511
572
|
this.#currentTime = newTime;
|
|
573
|
+
if (this.playbackController) this.playbackController.currentTime = newTime;
|
|
574
|
+
this._setLocalTimeMs(timeMs);
|
|
512
575
|
this.requestUpdate("currentTime");
|
|
513
576
|
await this.updateComplete;
|
|
514
577
|
const allLitElements = this.#getAllLitElementDescendants();
|
|
515
578
|
await Promise.all(allLitElements.map((el) => el.updateComplete));
|
|
579
|
+
await Promise.all(allLitElements.map((el) => el.updateComplete));
|
|
516
580
|
const textElements = allLitElements.filter((el) => el.tagName === "EF-TEXT");
|
|
517
|
-
if (textElements.length > 0)
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
581
|
+
if (textElements.length > 0) {
|
|
582
|
+
await Promise.all(textElements.map((el) => {
|
|
583
|
+
if ("whenSegmentsReady" in el && typeof el.whenSegmentsReady === "function") return el.whenSegmentsReady();
|
|
584
|
+
return Promise.resolve();
|
|
585
|
+
}));
|
|
586
|
+
this.offsetHeight;
|
|
587
|
+
}
|
|
521
588
|
await this.#frameController.renderFrame(timeMs, {
|
|
522
589
|
waitForLitUpdate: false,
|
|
523
590
|
onAnimationsUpdate: (root) => {
|
|
@@ -530,36 +597,21 @@ let EFTimegroup = class EFTimegroup$1 extends EFTargetable(EFTemporal(TWMixin(Li
|
|
|
530
597
|
/**
|
|
531
598
|
* Collects all LitElement descendants recursively.
|
|
532
599
|
* Used by seekForRender to ensure all reactive elements have updated.
|
|
533
|
-
*
|
|
600
|
+
* Prunes subtrees of temporally-invisible elements — their Lit updates
|
|
601
|
+
* still fire via microtasks (OwnCurrentTimeController), so skipping
|
|
602
|
+
* the explicit await is safe.
|
|
534
603
|
*/
|
|
535
604
|
#getAllLitElementDescendants() {
|
|
536
605
|
const result = [];
|
|
537
606
|
const currentTimeMs = this.currentTimeMs;
|
|
538
|
-
let hiddenSubtreesSkipped = 0;
|
|
539
|
-
let temporallyFilteredOut = 0;
|
|
540
|
-
let totalLitElements = 0;
|
|
541
607
|
const walk = (el) => {
|
|
542
|
-
if (el instanceof HTMLElement && el.style.display === "none") {
|
|
543
|
-
hiddenSubtreesSkipped++;
|
|
544
|
-
return;
|
|
545
|
-
}
|
|
546
|
-
if (el instanceof HTMLElement) {
|
|
547
|
-
const style = getComputedStyle(el);
|
|
548
|
-
if (style.display === "none" || style.visibility === "hidden") {
|
|
549
|
-
hiddenSubtreesSkipped++;
|
|
550
|
-
return;
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
608
|
for (const child of el.children) {
|
|
554
|
-
if (child
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
const endMs = child.endTimeMs ?? Infinity;
|
|
559
|
-
if (currentTimeMs >= startMs && currentTimeMs <= endMs) result.push(child);
|
|
560
|
-
else temporallyFilteredOut++;
|
|
561
|
-
} else result.push(child);
|
|
609
|
+
if ("startTimeMs" in child && "endTimeMs" in child) {
|
|
610
|
+
const startMs = child.startTimeMs ?? -Infinity;
|
|
611
|
+
const endMs = child.endTimeMs ?? Infinity;
|
|
612
|
+
if (endMs > startMs && (currentTimeMs < startMs || currentTimeMs >= endMs)) continue;
|
|
562
613
|
}
|
|
614
|
+
if (child instanceof LitElement) result.push(child);
|
|
563
615
|
walk(child);
|
|
564
616
|
}
|
|
565
617
|
};
|
|
@@ -639,6 +691,8 @@ let EFTimegroup = class EFTimegroup$1 extends EFTargetable(EFTemporal(TWMixin(Li
|
|
|
639
691
|
flushSequenceDurationCache();
|
|
640
692
|
flushStartTimeMsCache();
|
|
641
693
|
this.requestUpdate();
|
|
694
|
+
this.#syncChildListeners();
|
|
695
|
+
this.emitContentChange("structure");
|
|
642
696
|
};
|
|
643
697
|
/** @internal */
|
|
644
698
|
loadTimeFromLocalStorage() {
|
|
@@ -654,8 +708,10 @@ let EFTimegroup = class EFTimegroup$1 extends EFTargetable(EFTemporal(TWMixin(Li
|
|
|
654
708
|
}
|
|
655
709
|
connectedCallback() {
|
|
656
710
|
super.connectedCallback();
|
|
711
|
+
if (this.canvasPreviewActive) return;
|
|
657
712
|
this.updateComplete.then(() => {
|
|
658
713
|
this.#runInitializer();
|
|
714
|
+
this.#syncChildListeners();
|
|
659
715
|
});
|
|
660
716
|
requestAnimationFrame(() => {
|
|
661
717
|
requestAnimationFrame(() => {
|
|
@@ -679,9 +735,7 @@ let EFTimegroup = class EFTimegroup$1 extends EFTargetable(EFTemporal(TWMixin(Li
|
|
|
679
735
|
#setupPlaybackListener() {
|
|
680
736
|
if (this.#playbackListener || !this.playbackController) return;
|
|
681
737
|
this.#playbackListener = (event) => {
|
|
682
|
-
if (event.property === "currentTimeMs" && typeof event.value === "number")
|
|
683
|
-
if (this.playing) this.#userTimeMs = event.value;
|
|
684
|
-
}
|
|
738
|
+
if (event.property === "currentTimeMs" && typeof event.value === "number") this.#userTimeMs = event.value;
|
|
685
739
|
};
|
|
686
740
|
this.playbackController.addListener(this.#playbackListener);
|
|
687
741
|
}
|
|
@@ -703,79 +757,29 @@ let EFTimegroup = class EFTimegroup$1 extends EFTargetable(EFTemporal(TWMixin(Li
|
|
|
703
757
|
}
|
|
704
758
|
disconnectedCallback() {
|
|
705
759
|
super.disconnectedCallback();
|
|
760
|
+
if (this.canvasPreviewActive) return;
|
|
706
761
|
this.#resizeObserver?.disconnect();
|
|
707
762
|
this.#removePlaybackListener();
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
* Does NOT modify currentTimeMs - captures are rendered independently.
|
|
712
|
-
*
|
|
713
|
-
* @param options - Capture options including timeMs, scale, contentReadyMode
|
|
714
|
-
* @returns Promise resolving to an HTMLCanvasElement with the captured frame
|
|
715
|
-
* @public
|
|
716
|
-
*/
|
|
717
|
-
async captureAtTime(options) {
|
|
718
|
-
return captureTimegroupAtTime(this, options);
|
|
719
|
-
}
|
|
720
|
-
/**
|
|
721
|
-
* Capture multiple timestamps as canvas thumbnails in a single batch.
|
|
722
|
-
*
|
|
723
|
-
* CLONE-TIMELINE ARCHITECTURE:
|
|
724
|
-
* Creates a single render clone and reuses it across all captures.
|
|
725
|
-
* Prime-timeline is NEVER seeked - user can continue previewing/editing during capture.
|
|
726
|
-
*
|
|
727
|
-
* @param timestamps - Array of timestamps (in milliseconds) to capture
|
|
728
|
-
* @param options - Capture options (scale, contentReadyMode, blockingTimeoutMs)
|
|
729
|
-
* @returns Promise resolving to array of HTMLCanvasElements
|
|
730
|
-
* @public
|
|
731
|
-
*/
|
|
732
|
-
async captureBatch(timestamps, options = {}) {
|
|
733
|
-
if (timestamps.length === 0) return [];
|
|
734
|
-
const { scale = .25, contentReadyMode = "immediate", blockingTimeoutMs = 5e3 } = options;
|
|
735
|
-
const batchStartTime = performance.now();
|
|
736
|
-
const cloneStartTime = performance.now();
|
|
737
|
-
const { clone: renderClone, container: renderContainer, cleanup: cleanupRenderClone } = await this.createRenderClone();
|
|
738
|
-
const cloneTime = performance.now() - cloneStartTime;
|
|
739
|
-
const prefetchStartTime = performance.now();
|
|
740
|
-
const videoElements = renderClone.querySelectorAll("ef-video");
|
|
741
|
-
if (videoElements.length > 0) await Promise.all(Array.from(videoElements).map((video) => video.prefetchScrubSegments(timestamps)));
|
|
742
|
-
const prefetchTime = performance.now() - prefetchStartTime;
|
|
743
|
-
const canvases = [];
|
|
744
|
-
let totalSeekTime = 0;
|
|
745
|
-
let totalCaptureTime = 0;
|
|
746
|
-
try {
|
|
747
|
-
for (let i = 0; i < timestamps.length; i++) {
|
|
748
|
-
const timeMs = timestamps[i];
|
|
749
|
-
const seekStart = performance.now();
|
|
750
|
-
await renderClone.seekForRender(timeMs);
|
|
751
|
-
totalSeekTime += performance.now() - seekStart;
|
|
752
|
-
const captureStart = performance.now();
|
|
753
|
-
const canvas = await captureFromClone(renderClone, renderContainer, {
|
|
754
|
-
scale,
|
|
755
|
-
contentReadyMode,
|
|
756
|
-
blockingTimeoutMs,
|
|
757
|
-
originalTimegroup: this
|
|
758
|
-
});
|
|
759
|
-
totalCaptureTime += performance.now() - captureStart;
|
|
760
|
-
canvases.push(canvas);
|
|
761
|
-
}
|
|
762
|
-
return canvases;
|
|
763
|
-
} finally {
|
|
764
|
-
const totalTime = performance.now() - batchStartTime;
|
|
765
|
-
console.log(`[captureBatch] ${timestamps.length} frames: clone=${cloneTime.toFixed(0)}ms, prefetch=${prefetchTime.toFixed(0)}ms, seek=${totalSeekTime.toFixed(0)}ms, capture=${totalCaptureTime.toFixed(0)}ms, total=${totalTime.toFixed(0)}ms`);
|
|
766
|
-
cleanupRenderClone();
|
|
763
|
+
for (const child of this.#trackedChildren) {
|
|
764
|
+
child.removeEventListener("readystatechange", this.#childReadyStateHandler);
|
|
765
|
+
child.removeEventListener("contentchange", this.#childContentChangeHandler);
|
|
767
766
|
}
|
|
767
|
+
this.#trackedChildren.clear();
|
|
768
|
+
this.#qualityUpgradeScheduler.dispose();
|
|
768
769
|
}
|
|
769
770
|
/**
|
|
770
771
|
* Render the timegroup to an MP4 video file and trigger download.
|
|
771
772
|
* Captures each frame at the specified fps, encodes using WebCodecs via
|
|
772
773
|
* MediaBunny, and downloads the resulting video.
|
|
773
|
-
*
|
|
774
|
+
*
|
|
775
|
+
* Uses dynamic import to only load render utilities in browser context.
|
|
776
|
+
*
|
|
774
777
|
* @param options - Rendering options (fps, codec, bitrate, filename, etc.)
|
|
775
778
|
* @returns Promise that resolves when video is downloaded
|
|
776
779
|
* @public
|
|
777
780
|
*/
|
|
778
781
|
async renderToVideo(options) {
|
|
782
|
+
const { renderTimegroupToVideo } = await import("../preview/renderTimegroupToVideo.js");
|
|
779
783
|
return renderTimegroupToVideo(this, options);
|
|
780
784
|
}
|
|
781
785
|
/**
|
|
@@ -808,7 +812,8 @@ let EFTimegroup = class EFTimegroup$1 extends EFTargetable(EFTemporal(TWMixin(Li
|
|
|
808
812
|
for (let i = 0; i < originalCaptions.length && i < cloneCaptions.length; i++) {
|
|
809
813
|
const origCap = originalCaptions[i];
|
|
810
814
|
const cloneCap = cloneCaptions[i];
|
|
811
|
-
|
|
815
|
+
const loadedData = origCap.captionsData ?? origCap.unifiedCaptionsDataTask?.value;
|
|
816
|
+
if (loadedData) cloneCap.captionsData = loadedData;
|
|
812
817
|
}
|
|
813
818
|
}
|
|
814
819
|
/**
|
|
@@ -873,10 +878,10 @@ let EFTimegroup = class EFTimegroup$1 extends EFTargetable(EFTemporal(TWMixin(Li
|
|
|
873
878
|
* @internal
|
|
874
879
|
*/
|
|
875
880
|
async #copyInitializersToClone(original, clone) {
|
|
876
|
-
const initializerPromises = [];
|
|
877
881
|
if (original.initializer) {
|
|
878
882
|
clone.initializer = original.initializer;
|
|
879
|
-
|
|
883
|
+
await clone.updateComplete;
|
|
884
|
+
clone.#runInitializer();
|
|
880
885
|
}
|
|
881
886
|
const originalNested = Array.from(original.querySelectorAll("ef-timegroup"));
|
|
882
887
|
const cloneNested = Array.from(clone.querySelectorAll("ef-timegroup"));
|
|
@@ -885,29 +890,104 @@ let EFTimegroup = class EFTimegroup$1 extends EFTargetable(EFTemporal(TWMixin(Li
|
|
|
885
890
|
const cloneNestedItem = cloneNested[i];
|
|
886
891
|
if (origNested.initializer) {
|
|
887
892
|
cloneNestedItem.initializer = origNested.initializer;
|
|
888
|
-
|
|
893
|
+
await cloneNestedItem.updateComplete;
|
|
894
|
+
cloneNestedItem.#runInitializer();
|
|
889
895
|
}
|
|
890
896
|
}
|
|
891
|
-
if (initializerPromises.length > 0) await Promise.all(initializerPromises);
|
|
892
897
|
}
|
|
893
898
|
/**
|
|
894
899
|
* Create an independent clone of this timegroup for rendering.
|
|
895
900
|
* The clone is a fully functional ef-timegroup with its own animations
|
|
896
901
|
* and time state, isolated from the original (Prime-timeline).
|
|
897
|
-
*
|
|
902
|
+
*
|
|
898
903
|
* OPTIONAL: An initializer can be set via `timegroup.initializer = (tg) => { ... }`
|
|
899
904
|
* to re-run JavaScript setup (frame callbacks, React components) on each clone.
|
|
900
|
-
*
|
|
905
|
+
*
|
|
901
906
|
* This enables:
|
|
902
907
|
* - Rendering without affecting user's preview position
|
|
903
908
|
* - Concurrent renders with different clones
|
|
904
909
|
* - Re-running JavaScript setup on each clone (if initializer is provided)
|
|
905
|
-
*
|
|
910
|
+
*
|
|
906
911
|
* @returns Promise resolving to clone, container, and cleanup function
|
|
907
912
|
* @throws Error if initializer is async or takes too long
|
|
908
913
|
* @public
|
|
909
914
|
*/
|
|
910
915
|
async createRenderClone() {
|
|
916
|
+
const factory = getCloneFactory(this);
|
|
917
|
+
if (factory) return this.#createRenderCloneFromFactory(factory);
|
|
918
|
+
return this.#createRenderCloneFromDOM();
|
|
919
|
+
}
|
|
920
|
+
/**
|
|
921
|
+
* Wait for all LitElement descendants to update and for text segments to be ready.
|
|
922
|
+
* This ensures the clone is fully initialized before rendering.
|
|
923
|
+
* @internal
|
|
924
|
+
*/
|
|
925
|
+
async #waitForDescendants(actualClone) {
|
|
926
|
+
const allLitElements = Array.from(actualClone.querySelectorAll("*")).filter((el) => el instanceof LitElement);
|
|
927
|
+
await Promise.all(allLitElements.map((el) => el.updateComplete));
|
|
928
|
+
const textElements = allLitElements.filter((el) => el.tagName === "EF-TEXT");
|
|
929
|
+
if (textElements.length > 0) {
|
|
930
|
+
await Promise.all(textElements.map((el) => {
|
|
931
|
+
if ("whenSegmentsReady" in el && typeof el.whenSegmentsReady === "function") return el.whenSegmentsReady();
|
|
932
|
+
return Promise.resolve();
|
|
933
|
+
}));
|
|
934
|
+
actualClone.offsetHeight;
|
|
935
|
+
await new Promise((resolve) => requestAnimationFrame(resolve));
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
/**
|
|
939
|
+
* Factory path: mount a fresh component tree (React, etc.) to produce
|
|
940
|
+
* a fully functional clone. The factory is responsible for rendering
|
|
941
|
+
* the component into the container and returning the root ef-timegroup.
|
|
942
|
+
*/
|
|
943
|
+
async #createRenderCloneFromFactory(factory) {
|
|
944
|
+
const width = this.offsetWidth || 1920;
|
|
945
|
+
const height = this.offsetHeight || 1080;
|
|
946
|
+
const container = document.createElement("div");
|
|
947
|
+
container.className = "ef-render-clone-container";
|
|
948
|
+
container.style.cssText = `
|
|
949
|
+
position: fixed;
|
|
950
|
+
left: -9999px;
|
|
951
|
+
top: 0;
|
|
952
|
+
width: ${width}px;
|
|
953
|
+
height: ${height}px;
|
|
954
|
+
pointer-events: none;
|
|
955
|
+
overflow: hidden;
|
|
956
|
+
`;
|
|
957
|
+
let renderTarget = container;
|
|
958
|
+
const originalConfig = this.closest("ef-configuration");
|
|
959
|
+
if (originalConfig) {
|
|
960
|
+
const configClone = originalConfig.cloneNode(false);
|
|
961
|
+
container.appendChild(configClone);
|
|
962
|
+
renderTarget = configClone;
|
|
963
|
+
}
|
|
964
|
+
document.body.appendChild(container);
|
|
965
|
+
const { timegroup: actualClone, cleanup: factoryCleanup } = factory(renderTarget);
|
|
966
|
+
if (!actualClone) throw new Error("Clone factory did not produce an ef-timegroup. Ensure the factory renders a component containing a Timegroup.");
|
|
967
|
+
actualClone.setAttribute("data-no-workbench", "true");
|
|
968
|
+
actualClone.setAttribute("data-no-playback-controller", "true");
|
|
969
|
+
actualClone.style.width = `${width}px`;
|
|
970
|
+
actualClone.style.height = `${height}px`;
|
|
971
|
+
actualClone.style.display = "block";
|
|
972
|
+
await customElements.whenDefined("ef-timegroup");
|
|
973
|
+
customElements.upgrade(container);
|
|
974
|
+
await actualClone.updateComplete;
|
|
975
|
+
await this.#waitForDescendants(actualClone);
|
|
976
|
+
await this.#finalizeRenderClone(actualClone);
|
|
977
|
+
return {
|
|
978
|
+
clone: actualClone,
|
|
979
|
+
container,
|
|
980
|
+
cleanup: () => {
|
|
981
|
+
container.remove();
|
|
982
|
+
factoryCleanup();
|
|
983
|
+
}
|
|
984
|
+
};
|
|
985
|
+
}
|
|
986
|
+
/**
|
|
987
|
+
* DOM path: deep clone the DOM tree and copy JavaScript properties.
|
|
988
|
+
* Used for vanilla HTML/JS timelines that don't have a factory registered.
|
|
989
|
+
*/
|
|
990
|
+
async #createRenderCloneFromDOM() {
|
|
911
991
|
const container = document.createElement("div");
|
|
912
992
|
container.className = "ef-render-clone-container";
|
|
913
993
|
container.style.cssText = `
|
|
@@ -921,6 +1001,14 @@ let EFTimegroup = class EFTimegroup$1 extends EFTargetable(EFTemporal(TWMixin(Li
|
|
|
921
1001
|
`;
|
|
922
1002
|
const cloneEl = this.cloneNode(true);
|
|
923
1003
|
cloneEl.removeAttribute("id");
|
|
1004
|
+
for (const el of cloneEl.querySelectorAll("[id]")) el.removeAttribute("id");
|
|
1005
|
+
cloneEl.setAttribute("data-no-workbench", "true");
|
|
1006
|
+
cloneEl.setAttribute("data-no-playback-controller", "true");
|
|
1007
|
+
const width = this.offsetWidth || 1920;
|
|
1008
|
+
const height = this.offsetHeight || 1080;
|
|
1009
|
+
cloneEl.style.width = `${width}px`;
|
|
1010
|
+
cloneEl.style.height = `${height}px`;
|
|
1011
|
+
cloneEl.style.display = "block";
|
|
924
1012
|
this.#copyCaptionsData(this, cloneEl);
|
|
925
1013
|
this.#copyTextContent(this, cloneEl);
|
|
926
1014
|
const originalConfig = this.closest("ef-configuration");
|
|
@@ -940,7 +1028,30 @@ let EFTimegroup = class EFTimegroup$1 extends EFTargetable(EFTemporal(TWMixin(Li
|
|
|
940
1028
|
actualClone = container.querySelector("ef-timegroup");
|
|
941
1029
|
if (!actualClone) throw new Error("ef-timegroup element lost after upgrade");
|
|
942
1030
|
await actualClone.updateComplete;
|
|
1031
|
+
await this.#waitForDescendants(actualClone);
|
|
943
1032
|
await this.#copyTextSegmentData(this, actualClone);
|
|
1033
|
+
await this.#finalizeRenderClone(actualClone);
|
|
1034
|
+
return {
|
|
1035
|
+
clone: actualClone,
|
|
1036
|
+
container,
|
|
1037
|
+
cleanup: () => {
|
|
1038
|
+
container.remove();
|
|
1039
|
+
const reactRoot = actualClone._reactRoot;
|
|
1040
|
+
if (reactRoot) queueMicrotask(() => {
|
|
1041
|
+
reactRoot.unmount();
|
|
1042
|
+
});
|
|
1043
|
+
}
|
|
1044
|
+
};
|
|
1045
|
+
}
|
|
1046
|
+
/**
|
|
1047
|
+
* Shared finalization for both factory and DOM clone paths:
|
|
1048
|
+
* - Set up parent-child temporal relationships
|
|
1049
|
+
* - Lock root timegroup references
|
|
1050
|
+
* - Wait for media durations and captions
|
|
1051
|
+
* - Remove PlaybackController
|
|
1052
|
+
* - Initial seek to frame 0
|
|
1053
|
+
*/
|
|
1054
|
+
async #finalizeRenderClone(actualClone) {
|
|
944
1055
|
const setupParentChildRelationships = (parent, root) => {
|
|
945
1056
|
for (const child of parent.children) if (child.tagName === "EF-TIMEGROUP") {
|
|
946
1057
|
const childTG = child;
|
|
@@ -953,10 +1064,10 @@ let EFTimegroup = class EFTimegroup$1 extends EFTargetable(EFTemporal(TWMixin(Li
|
|
|
953
1064
|
temporal.parentTimegroup = parent;
|
|
954
1065
|
temporal.rootTimegroup = root;
|
|
955
1066
|
if ("lockRootTimegroup" in temporal && typeof temporal.lockRootTimegroup === "function") temporal.lockRootTimegroup();
|
|
956
|
-
} else if (child instanceof Element)
|
|
1067
|
+
} else if (child instanceof Element) setupInContainer(child, parent, root);
|
|
957
1068
|
};
|
|
958
|
-
const
|
|
959
|
-
for (const child of container
|
|
1069
|
+
const setupInContainer = (container, nearestParentTG, root) => {
|
|
1070
|
+
for (const child of container.children) if (child.tagName === "EF-TIMEGROUP") {
|
|
960
1071
|
const childTG = child;
|
|
961
1072
|
childTG.parentTimegroup = nearestParentTG;
|
|
962
1073
|
childTG.rootTimegroup = root;
|
|
@@ -967,7 +1078,7 @@ let EFTimegroup = class EFTimegroup$1 extends EFTargetable(EFTemporal(TWMixin(Li
|
|
|
967
1078
|
temporal.parentTimegroup = nearestParentTG;
|
|
968
1079
|
temporal.rootTimegroup = root;
|
|
969
1080
|
if ("lockRootTimegroup" in temporal && typeof temporal.lockRootTimegroup === "function") temporal.lockRootTimegroup();
|
|
970
|
-
} else if (child instanceof Element)
|
|
1081
|
+
} else if (child instanceof Element) setupInContainer(child, nearestParentTG, root);
|
|
971
1082
|
};
|
|
972
1083
|
actualClone.rootTimegroup = actualClone;
|
|
973
1084
|
setupParentChildRelationships(actualClone, actualClone);
|
|
@@ -989,17 +1100,6 @@ let EFTimegroup = class EFTimegroup$1 extends EFTargetable(EFTemporal(TWMixin(Li
|
|
|
989
1100
|
actualClone.playbackController = void 0;
|
|
990
1101
|
}
|
|
991
1102
|
await actualClone.seek(0);
|
|
992
|
-
return {
|
|
993
|
-
clone: actualClone,
|
|
994
|
-
container,
|
|
995
|
-
cleanup: () => {
|
|
996
|
-
container.remove();
|
|
997
|
-
const reactRoot = actualClone._reactRoot;
|
|
998
|
-
if (reactRoot) queueMicrotask(() => {
|
|
999
|
-
reactRoot.unmount();
|
|
1000
|
-
});
|
|
1001
|
-
}
|
|
1002
|
-
};
|
|
1003
1103
|
}
|
|
1004
1104
|
/** @internal */
|
|
1005
1105
|
get storageKey() {
|
|
@@ -1020,54 +1120,6 @@ let EFTimegroup = class EFTimegroup$1 extends EFTargetable(EFTemporal(TWMixin(Li
|
|
|
1020
1120
|
const childTemporalsAsElements = this.childTemporals;
|
|
1021
1121
|
return evaluateDurationForMode(this, this.mode, childTemporalsAsElements);
|
|
1022
1122
|
}
|
|
1023
|
-
/**
|
|
1024
|
-
* Evaluates which elements should be rendered in the current frame.
|
|
1025
|
-
* Filters to only include temporally visible elements for frame processing.
|
|
1026
|
-
* Uses animation-friendly visibility to prevent animation jumps at exact boundaries.
|
|
1027
|
-
*/
|
|
1028
|
-
#evaluateVisibleElementsForFrame() {
|
|
1029
|
-
return deepGetElementsWithFrameTasks(this).filter((element) => {
|
|
1030
|
-
return evaluateAnimationVisibilityState(element).isVisible;
|
|
1031
|
-
});
|
|
1032
|
-
}
|
|
1033
|
-
/** @internal */
|
|
1034
|
-
async waitForFrameTasks(signal) {
|
|
1035
|
-
return await withSpan("timegroup.waitForFrameTasks", {
|
|
1036
|
-
timegroupId: this.id || "unknown",
|
|
1037
|
-
mode: this.mode
|
|
1038
|
-
}, void 0, async (span) => {
|
|
1039
|
-
signal?.throwIfAborted();
|
|
1040
|
-
const innerStart = performance.now();
|
|
1041
|
-
const temporalElements = deepGetElementsWithFrameTasks(this);
|
|
1042
|
-
if (isTracingEnabled()) span.setAttribute("temporalElementsCount", temporalElements.length);
|
|
1043
|
-
signal?.throwIfAborted();
|
|
1044
|
-
const visibleElements = this.#evaluateVisibleElementsForFrame();
|
|
1045
|
-
if (isTracingEnabled()) span.setAttribute("visibleElementsCount", visibleElements.length);
|
|
1046
|
-
const promiseStart = performance.now();
|
|
1047
|
-
await Promise.all(visibleElements.map(async (element) => {
|
|
1048
|
-
signal?.throwIfAborted();
|
|
1049
|
-
try {
|
|
1050
|
-
if ("waitForFrameReady" in element && typeof element.waitForFrameReady === "function") await element.waitForFrameReady();
|
|
1051
|
-
else {
|
|
1052
|
-
await element.updateComplete;
|
|
1053
|
-
await element.frameTask.run();
|
|
1054
|
-
}
|
|
1055
|
-
} catch (error) {
|
|
1056
|
-
if (error instanceof DOMException && error.name === "AbortError" || error instanceof Error && (error.name === "AbortError" || error.message?.includes("signal is aborted") || error.message?.includes("The user aborted a request"))) {
|
|
1057
|
-
signal?.throwIfAborted();
|
|
1058
|
-
return;
|
|
1059
|
-
}
|
|
1060
|
-
throw error;
|
|
1061
|
-
}
|
|
1062
|
-
}));
|
|
1063
|
-
const promiseEnd = performance.now();
|
|
1064
|
-
const innerEnd = performance.now();
|
|
1065
|
-
if (isTracingEnabled()) {
|
|
1066
|
-
span.setAttribute("actualInnerMs", innerEnd - innerStart);
|
|
1067
|
-
span.setAttribute("promiseAwaitMs", promiseEnd - promiseStart);
|
|
1068
|
-
}
|
|
1069
|
-
});
|
|
1070
|
-
}
|
|
1071
1123
|
#mediaDurationsPromise = void 0;
|
|
1072
1124
|
/** @internal */
|
|
1073
1125
|
async waitForMediaDurations(signal) {
|
|
@@ -1195,14 +1247,6 @@ let EFTimegroup = class EFTimegroup$1 extends EFTargetable(EFTemporal(TWMixin(Li
|
|
|
1195
1247
|
get childTemporals() {
|
|
1196
1248
|
return shallowGetTemporalElements(this);
|
|
1197
1249
|
}
|
|
1198
|
-
get #contextProvider() {
|
|
1199
|
-
let parent = this.parentNode;
|
|
1200
|
-
while (parent) {
|
|
1201
|
-
if (isContextMixin(parent)) return parent;
|
|
1202
|
-
parent = parent.parentNode;
|
|
1203
|
-
}
|
|
1204
|
-
return null;
|
|
1205
|
-
}
|
|
1206
1250
|
/**
|
|
1207
1251
|
* Returns true if the timegroup should be wrapped with a workbench.
|
|
1208
1252
|
*
|
|
@@ -1215,18 +1259,26 @@ let EFTimegroup = class EFTimegroup$1 extends EFTargetable(EFTemporal(TWMixin(Li
|
|
|
1215
1259
|
* @internal
|
|
1216
1260
|
*/
|
|
1217
1261
|
shouldWrapWithWorkbench() {
|
|
1262
|
+
if (this.canvasPreviewActive) return false;
|
|
1218
1263
|
if (!this.isRootTimegroup) return false;
|
|
1219
1264
|
if (this.closest("ef-canvas") !== null) return false;
|
|
1220
1265
|
if (this.closest("ef-preview") !== null || this.closest("ef-workbench") !== null || this.closest("ef-preview-context") !== null) return false;
|
|
1221
|
-
if (this.closest("test-context") !== null) return false;
|
|
1222
|
-
if (
|
|
1223
|
-
if (
|
|
1266
|
+
if (this.closest("test-context") !== null || this.hasAttribute("data-no-workbench")) return false;
|
|
1267
|
+
if (EF_RENDERING?.() === true) return false;
|
|
1268
|
+
if (typeof window !== "undefined") {
|
|
1269
|
+
const params = new URLSearchParams(window.location.search);
|
|
1270
|
+
if (params.get("noWorkbench") === "true" || params.get("no-workbench") === "true") return false;
|
|
1271
|
+
}
|
|
1224
1272
|
return this.workbench;
|
|
1225
1273
|
}
|
|
1226
1274
|
/** @internal */
|
|
1227
1275
|
wrapWithWorkbench() {
|
|
1228
1276
|
const workbench = document.createElement("ef-workbench");
|
|
1229
1277
|
const parent = this.parentElement;
|
|
1278
|
+
if (EF_RENDERING()) {
|
|
1279
|
+
workbench.setAttribute("rendering", "");
|
|
1280
|
+
workbench.rendering = true;
|
|
1281
|
+
}
|
|
1230
1282
|
if (parent === document.body) {
|
|
1231
1283
|
workbench.style.position = "fixed";
|
|
1232
1284
|
workbench.style.top = "0";
|
|
@@ -1234,6 +1286,12 @@ let EFTimegroup = class EFTimegroup$1 extends EFTargetable(EFTemporal(TWMixin(Li
|
|
|
1234
1286
|
workbench.style.width = "100vw";
|
|
1235
1287
|
workbench.style.height = "100vh";
|
|
1236
1288
|
workbench.style.zIndex = "0";
|
|
1289
|
+
} else {
|
|
1290
|
+
workbench.style.position = "absolute";
|
|
1291
|
+
workbench.style.top = "0";
|
|
1292
|
+
workbench.style.left = "0";
|
|
1293
|
+
workbench.style.width = "100%";
|
|
1294
|
+
workbench.style.height = "100%";
|
|
1237
1295
|
}
|
|
1238
1296
|
parent?.append(workbench);
|
|
1239
1297
|
if (!this.hasAttribute("id")) this.setAttribute("id", "root-timegroup");
|
|
@@ -1246,8 +1304,8 @@ let EFTimegroup = class EFTimegroup$1 extends EFTargetable(EFTemporal(TWMixin(Li
|
|
|
1246
1304
|
const rect = this.getBoundingClientRect();
|
|
1247
1305
|
const canvas = document.createElement("ef-canvas");
|
|
1248
1306
|
canvas.id = "workbench-canvas";
|
|
1249
|
-
canvas.style.width = `${
|
|
1250
|
-
canvas.style.height = `${
|
|
1307
|
+
canvas.style.width = `${rect.width}px`;
|
|
1308
|
+
canvas.style.height = `${rect.height}px`;
|
|
1251
1309
|
canvas.style.display = "block";
|
|
1252
1310
|
canvas.append(this);
|
|
1253
1311
|
panZoom.append(canvas);
|
|
@@ -1262,9 +1320,6 @@ let EFTimegroup = class EFTimegroup$1 extends EFTargetable(EFTemporal(TWMixin(Li
|
|
|
1262
1320
|
filmstrip.setAttribute("target", this.id);
|
|
1263
1321
|
workbench.append(filmstrip);
|
|
1264
1322
|
}
|
|
1265
|
-
get #efElements() {
|
|
1266
|
-
return Array.from(this.querySelectorAll("ef-audio, ef-video, ef-image, ef-captions, ef-waveform"));
|
|
1267
|
-
}
|
|
1268
1323
|
/**
|
|
1269
1324
|
* Returns media elements for playback audio rendering
|
|
1270
1325
|
* For standalone media, returns [this]; for timegroups, returns all descendants
|
|
@@ -1283,80 +1338,6 @@ let EFTimegroup = class EFTimegroup$1 extends EFTargetable(EFTemporal(TWMixin(Li
|
|
|
1283
1338
|
async renderAudio(fromMs, toMs, signal) {
|
|
1284
1339
|
return renderTemporalAudio(this, fromMs, toMs, signal);
|
|
1285
1340
|
}
|
|
1286
|
-
/**
|
|
1287
|
-
* TEMPORARY TEST METHOD: Renders audio and immediately plays it back
|
|
1288
|
-
* Usage: timegroup.testPlayAudio(0, 5000) // Play first 5 seconds
|
|
1289
|
-
*/
|
|
1290
|
-
async #testPlayAudio(fromMs, toMs) {
|
|
1291
|
-
const renderedBuffer = await this.renderAudio(fromMs, toMs);
|
|
1292
|
-
const playbackContext = new AudioContext();
|
|
1293
|
-
const bufferSource = playbackContext.createBufferSource();
|
|
1294
|
-
bufferSource.buffer = renderedBuffer;
|
|
1295
|
-
bufferSource.connect(playbackContext.destination);
|
|
1296
|
-
bufferSource.start(0);
|
|
1297
|
-
return new Promise((resolve) => {
|
|
1298
|
-
bufferSource.onended = () => {
|
|
1299
|
-
playbackContext.close();
|
|
1300
|
-
resolve();
|
|
1301
|
-
};
|
|
1302
|
-
});
|
|
1303
|
-
}
|
|
1304
|
-
async #loadMd5Sums() {
|
|
1305
|
-
const efElements = this.#efElements;
|
|
1306
|
-
const loaderTasks = [];
|
|
1307
|
-
for (const el of efElements) {
|
|
1308
|
-
const md5SumLoader = el.md5SumLoader;
|
|
1309
|
-
if (md5SumLoader && typeof md5SumLoader.run === "function") {
|
|
1310
|
-
md5SumLoader.run().catch(() => {});
|
|
1311
|
-
if (md5SumLoader.taskComplete) loaderTasks.push(md5SumLoader.taskComplete);
|
|
1312
|
-
}
|
|
1313
|
-
}
|
|
1314
|
-
await Promise.all(loaderTasks);
|
|
1315
|
-
efElements.forEach((el) => {
|
|
1316
|
-
if ("productionSrc" in el && el.productionSrc instanceof Function) el.setAttribute("src", el.productionSrc());
|
|
1317
|
-
});
|
|
1318
|
-
}
|
|
1319
|
-
#timegroupFrameTaskCount = 0;
|
|
1320
|
-
#timegroupFrameTaskLastReset = Date.now();
|
|
1321
|
-
static {
|
|
1322
|
-
this.TIMEGROUP_FRAME_TASK_THRESHOLD = 100;
|
|
1323
|
-
}
|
|
1324
|
-
static {
|
|
1325
|
-
this.TIMEGROUP_FRAME_TASK_RESET_MS = 1e3;
|
|
1326
|
-
}
|
|
1327
|
-
/** @internal */
|
|
1328
|
-
#frameTaskPromise = Promise.resolve();
|
|
1329
|
-
#frameTaskAbortController = null;
|
|
1330
|
-
async #runFrameTask(signal) {
|
|
1331
|
-
const now = Date.now();
|
|
1332
|
-
if (now - this.#timegroupFrameTaskLastReset > _EFTimegroup.TIMEGROUP_FRAME_TASK_RESET_MS) {
|
|
1333
|
-
this.#timegroupFrameTaskCount = 0;
|
|
1334
|
-
this.#timegroupFrameTaskLastReset = now;
|
|
1335
|
-
}
|
|
1336
|
-
this.#timegroupFrameTaskCount++;
|
|
1337
|
-
if (this.#timegroupFrameTaskCount > _EFTimegroup.TIMEGROUP_FRAME_TASK_THRESHOLD) return;
|
|
1338
|
-
try {
|
|
1339
|
-
signal.throwIfAborted();
|
|
1340
|
-
if (this.isRootTimegroup) await withSpan("timegroup.frameTask", {
|
|
1341
|
-
timegroupId: this.id || "unknown",
|
|
1342
|
-
ownCurrentTimeMs: this.ownCurrentTimeMs,
|
|
1343
|
-
currentTimeMs: this.currentTimeMs
|
|
1344
|
-
}, void 0, async () => {
|
|
1345
|
-
await this.#frameController.renderFrame(this.currentTimeMs, {
|
|
1346
|
-
waitForLitUpdate: false,
|
|
1347
|
-
onAnimationsUpdate: (root) => {
|
|
1348
|
-
updateAnimations(root);
|
|
1349
|
-
}
|
|
1350
|
-
});
|
|
1351
|
-
signal.throwIfAborted();
|
|
1352
|
-
await this.#executeCustomFrameTasks();
|
|
1353
|
-
});
|
|
1354
|
-
else await this.#executeCustomFrameTasks();
|
|
1355
|
-
} catch (error) {
|
|
1356
|
-
if (error instanceof DOMException && error.name === "AbortError") return;
|
|
1357
|
-
console.error("EFTimegroup frameTask error", error);
|
|
1358
|
-
}
|
|
1359
|
-
}
|
|
1360
1341
|
async #executeCustomFrameTasks() {
|
|
1361
1342
|
if (this.#customFrameTasks.size > 0) {
|
|
1362
1343
|
const percentComplete = this.durationMs > 0 ? this.ownCurrentTimeMs / this.durationMs : 0;
|
|
@@ -1462,7 +1443,7 @@ __decorate([property({
|
|
|
1462
1443
|
type: Number,
|
|
1463
1444
|
attribute: "currenttime"
|
|
1464
1445
|
})], EFTimegroup.prototype, "currentTime", null);
|
|
1465
|
-
EFTimegroup =
|
|
1446
|
+
EFTimegroup = __decorate([customElement("ef-timegroup")], EFTimegroup);
|
|
1466
1447
|
|
|
1467
1448
|
//#endregion
|
|
1468
1449
|
export { EFTimegroup, flushSequenceDurationCache, shallowGetTimegroups };
|