fix(core): ceil timeline payload duration to match render frames

This commit is contained in:
func25
2026-05-20 06:04:29 +07:00
parent efc5f0584b
commit 0fc3937809
2 changed files with 16 additions and 1 deletions
@@ -183,6 +183,21 @@ describe("collectRuntimeTimelinePayload", () => {
expect(result.durationInFrames).toBe(300); // 10s * 30fps 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", () => { it("preserves the authored root duration when clips end earlier", () => {
const root = document.createElement("div"); const root = document.createElement("div");
root.setAttribute("data-composition-id", "main"); root.setAttribute("data-composition-id", "main");
+1 -1
View File
@@ -674,7 +674,7 @@ export function collectRuntimeTimelinePayload(params: {
const shouldEmitNonDeterministicInf = timelineLooksLoopInflated && attrDurationCandidate == null; const shouldEmitNonDeterministicInf = timelineLooksLoopInflated && attrDurationCandidate == null;
const durationInFrames = shouldEmitNonDeterministicInf const durationInFrames = shouldEmitNonDeterministicInf
? Number.POSITIVE_INFINITY ? 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 { return {
source: "hf-preview", source: "hf-preview",
type: "timeline", type: "timeline",