From 0fc3937809c5d2d629476e1a97421ccf453fa7df Mon Sep 17 00:00:00 2001 From: func25 Date: Wed, 20 May 2026 06:04:29 +0700 Subject: [PATCH] fix(core): ceil timeline payload duration to match render frames --- packages/core/src/runtime/timeline.test.ts | 15 +++++++++++++++ packages/core/src/runtime/timeline.ts | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/packages/core/src/runtime/timeline.test.ts b/packages/core/src/runtime/timeline.test.ts index bc3a1a093..8ee1eca9c 100644 --- a/packages/core/src/runtime/timeline.test.ts +++ b/packages/core/src/runtime/timeline.test.ts @@ -183,6 +183,21 @@ describe("collectRuntimeTimelinePayload", () => { expect(result.durationInFrames).toBe(300); // 10s * 30fps }); + it("ceil durationInFrames to match render frame count", () => { + const root = document.createElement("div"); + root.setAttribute("data-composition-id", "main"); + root.setAttribute("data-duration", "1.01"); + document.body.appendChild(root); + + const clip = document.createElement("div"); + clip.setAttribute("data-start", "0"); + clip.setAttribute("data-duration", "1.01"); + root.appendChild(clip); + + const result = collectRuntimeTimelinePayload(defaultParams); + expect(result.durationInFrames).toBe(31); // ceil(1.01s * 30fps), same as render. + }); + it("preserves the authored root duration when clips end earlier", () => { const root = document.createElement("div"); root.setAttribute("data-composition-id", "main"); diff --git a/packages/core/src/runtime/timeline.ts b/packages/core/src/runtime/timeline.ts index f8246f2e8..4d598fb04 100644 --- a/packages/core/src/runtime/timeline.ts +++ b/packages/core/src/runtime/timeline.ts @@ -674,7 +674,7 @@ export function collectRuntimeTimelinePayload(params: { const shouldEmitNonDeterministicInf = timelineLooksLoopInflated && attrDurationCandidate == null; const durationInFrames = shouldEmitNonDeterministicInf ? Number.POSITIVE_INFINITY - : Math.max(1, Math.round(safeDuration * Math.max(1, params.canonicalFps))); + : Math.max(1, Math.ceil(safeDuration * Math.max(1, params.canonicalFps))); return { source: "hf-preview", type: "timeline",