perf(studio): grow composition duration live on extend, no preview remount

Extending a clip past the video end used to force the server-fallback
path that fully remounts the preview iframe (the SDK fast path can't
express the root composition's data-duration, and the runtime bakes+drops
data-duration at load so it can't be patched live). On a large comp that
remount is a visible hitch.

Add a runtime control-bridge action set-root-duration -> clock.setDuration,
so the studio can grow the transport length in place. On an extend the
studio now posts it (and patches the clip's own timing live) instead of
reloading; it only reloads when a GSAP source rewrite actually happened
(the gsap-mutation endpoints now report a mutated flag). Non-animated
extends — the common case — commit as fast as a normal edit.

Verified: bridge dispatch + studio no-reload/post-message paths unit-
tested; core/studio/studio-server typecheck + suites green; the built
runtime artifact carries the handler; E2E confirms the extend no longer
remounts the preview and still persists.
This commit is contained in:
Miguel Angel Simon Sierra
2026-07-08 23:46:28 -04:00
parent 580676bbf4
commit 9f6c20e482
9 changed files with 221 additions and 38 deletions
+8
View File
@@ -16,6 +16,7 @@ function createMockDeps() {
onSetPlaybackRate: vi.fn(),
onSetColorGrading: vi.fn(),
onSetColorGradingCompare: vi.fn(),
onSetRootDuration: vi.fn(),
onEnablePickMode: vi.fn(),
onDisablePickMode: vi.fn(),
};
@@ -155,6 +156,13 @@ describe("installRuntimeControlBridge", () => {
expect(deps.onSetPlaybackRate).toHaveBeenCalledWith(1);
});
it("dispatches set-root-duration command with numeric seconds", () => {
const deps = createMockDeps();
const handler = installRuntimeControlBridge(deps);
handler(makeControlMessage("set-root-duration", { durationSeconds: "18.5" }));
expect(deps.onSetRootDuration).toHaveBeenCalledWith(18.5);
});
it("dispatches set-color-grading command with target and grading payload", () => {
const deps = createMockDeps();
const handler = installRuntimeControlBridge(deps);