Skip to content

snapshot --at renders on a 30 fps grid instead of the exact time #4430

Description

@vanceingalls

Summary

hyperframes snapshot --at <t> does not seek to the exact time <t> — it renders the state for floor(t * 30) / 30, a 30 fps grid, regardless of the project's own declared data-fps. On a project with data-fps below 30 (the common NTSC-derived 29.97 case), this silently renders the wrong instant by up to 1/30 s (≈33 ms).

Numeric proof (research on hyperframes-ae-mcp, corpus row long-shadow-titles, data-fps="29.97")

Four independent back-solves against an AE-rendered reference frame all landed on the same ~0.019 s offset:

  • Root time requested: 19.019018 s (AE frame 126 at 29.97 fps, i.e. AE's own frame boundary for that instant).
  • hyperframes snapshot --at 19.019018 actually rendered the state for 19.000 s (sample 125.43 of a 29.97 fps composition), not 19.019.
  • The back-solved sample values from the four independent measurements: 125.42–125.46, all clustering just below sample 125.5 (19.000 s), while AE's own reference measured 125.99–126.03 (19.019 s) — a constant ~0.019 s (0.57 of a 29.97 fps frame) offset, in every case.

Step 1 reproduction (AE-free, CLI 0.8.72, this issue's own isolated measurement)

Built a synthetic project (data-fps="29.97", one .clip element with a linear GSAP tween ease:"none" moving at exactly 1000 px/s, so the rendered x position back-solves the exact instant the runtime rendered) and swept --at across several 1/30 s boundaries. Measured the element's left edge in each PNG:

--at requested (s) rendered as (s) back-solved from pixels
1.0190 1.0000 left = 1000 → t = 1.000
1.0333 1.0000 left = 1000 → t = 1.000
1.0500 1.0333 left = 1033 → t = 1.033
1.0667 1.0667 left = 1067 → t = 1.067
2.3457 2.3333 left = 2333 → t = 2.333
19.000000 19.0000 left = 1900 → t = 19.000
19.019018 19.0000 left = 1900 → t = 19.000
19.038000 19.0333 left = 1903 → t = 19.033
19.050000 19.0333 left = 1903 → t = 19.033 (byte-identical to 19.038)
19.066700 19.0667 left = 1907 → t = 19.067

This exactly reproduces the plan's back-solve (19.019018 → 19.000, not 19.019) and confirms the rule is floor to the nearest 1/30 s, not round-to-nearest and not the project's own 29.97 fps grid: 19.05 s (571.5/30, past the half-frame boundary) still floors down to 571/30 = 19.0333, which a round-to-nearest rule would not do.

Ask

Either:

  1. Make --at seek to the exact requested time (no quantization), or
  2. Document the quantization explicitly and add a --fps (or similar) flag so a caller can request the project's own frame grid instead of a hardcoded 30.

Right now snapshot --help on 0.8.72 documents --at, --frames, --no-end with no mention of any seek grid, so a caller has no way to know --at is quantized at all.

Environment

  • hyperframes --version: 0.8.72
  • Reproduced with --no-browser-gpu --no-end --describe false

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions