mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-10-30 09:16:55 +00:00
perf(core): a video edit with no animation timeline stops rewriting every clip each frame
This commit is contained in:
@@ -612,6 +612,25 @@ describe("initSandboxRuntimeModular", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("leaves hidden clips alone on every jump when the page has no timeline", () => {
|
||||
document.body.innerHTML =
|
||||
`<div data-composition-id="main" data-root="true" data-start="0" data-duration="10" data-width="1920" data-height="1080">` +
|
||||
`<video id="first" src="a.mp4" data-start="0" data-duration="2" data-track-index="0"></video>` +
|
||||
`<video id="second" src="a.mp4" data-start="2" data-duration="8" data-track-index="0"></video>` +
|
||||
`</div>`;
|
||||
window.__timelines = {};
|
||||
initSandboxRuntimeModular();
|
||||
const query = vi.spyOn(document, "querySelectorAll");
|
||||
const looked = () =>
|
||||
query.mock.calls.filter(([selector]) => selector === "[data-hf-clip-hidden]").length;
|
||||
try {
|
||||
for (const t of [0.5, 1, 1.5, 3, 6]) window.__player?.seek(t);
|
||||
expect(looked()).toBe(0);
|
||||
} finally {
|
||||
query.mockRestore();
|
||||
}
|
||||
});
|
||||
|
||||
it("styles a hidden clip visible once while playing toward its start, far scene included", () => {
|
||||
document.body.innerHTML =
|
||||
`<div data-composition-id="main" data-root="true" data-start="0" data-duration="10" data-width="1920" data-height="1080">` +
|
||||
|
||||
@@ -5163,6 +5163,16 @@ export function initSandboxRuntimeModular(): void {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
// Registered timelines other than the root composition's: each scene's own clock.
|
||||
const sceneTimelines = () => {
|
||||
const timelines = (window.__timelines ?? {}) as Record<string, RuntimeTimelineLike | undefined>;
|
||||
const rootCompositionId =
|
||||
resolveRootCompositionElement()?.getAttribute("data-composition-id") ?? null;
|
||||
return Object.entries(timelines).filter(
|
||||
(entry): entry is [string, RuntimeTimelineLike] =>
|
||||
!!entry[1] && typeof entry[1] === "object" && entry[0] !== rootCompositionId,
|
||||
);
|
||||
};
|
||||
const seekStandaloneRegisteredTimelines = (
|
||||
timeSeconds: number,
|
||||
revision: number,
|
||||
@@ -5172,12 +5182,7 @@ export function initSandboxRuntimeModular(): void {
|
||||
sceneClocks = new WeakMap();
|
||||
sceneClocksRevision = revision;
|
||||
}
|
||||
const timelines = (window.__timelines ?? {}) as Record<string, RuntimeTimelineLike | undefined>;
|
||||
const rootCompositionId =
|
||||
resolveRootCompositionElement()?.getAttribute("data-composition-id") ?? null;
|
||||
for (const [compositionId, timeline] of Object.entries(timelines)) {
|
||||
if (!timeline || typeof timeline !== "object" || compositionId === rootCompositionId)
|
||||
continue;
|
||||
for (const [compositionId, timeline] of sceneTimelines()) {
|
||||
const scene = sceneClockOf(compositionId, timeline);
|
||||
if (!scene) continue;
|
||||
const sourceTime =
|
||||
@@ -5291,9 +5296,10 @@ export function initSandboxRuntimeModular(): void {
|
||||
// Only clips holding a tween that renders for the first time on this seek need their authored style read.
|
||||
const firstRendered =
|
||||
firstRenders && tl ? clipsFirstRenderedIn(tl, tweensRenderedThrough.time, t) : null;
|
||||
// An empty set means no tween draws for the first time: nothing to show, so no page-wide query.
|
||||
// An empty set means no tween draws for the first time, and a page with no timeline has no tween:
|
||||
// nothing to show, so no page-wide query.
|
||||
const hideClipsAgain =
|
||||
firstRenders && firstRendered?.size !== 0
|
||||
firstRenders && firstRendered?.size !== 0 && (tl || sceneTimelines().length > 0)
|
||||
? showHiddenClips(firstRendered ? (el) => firstRendered.has(el) : undefined)
|
||||
: null;
|
||||
// Scenes first, each paused on its own clock, so the root's pass skips them and its later
|
||||
|
||||
Reference in New Issue
Block a user