feat(studio): edit a clip's speed ramp with a rate lane and presets - #4153
Conversation
somanshreddy
left a comment
There was a problem hiding this comment.
Reviewed at 9def196f. The code is sound — including the defect fix — and every blocker is downstack.
Verified (this PR's own code)
- The keep-pitch fix is correct and fixes the class, not just the symptom. The optimistic live-preview path treated any
value === "false"as "remove the attribute," butpersist()only removes"false"forHTML_BOOLEAN_ATTRIBUTES. Sodata-preserve-pitch="false"(keep-pitch OFF) was dropped from the preview node while written to disk — preview/persist divergence.resolveOptimisticAttributeValue(attr, value)aligns them by reusingHTML_BOOLEAN_ATTRIBUTES(data-preserve-pitch isn't one →"false"is kept, matching persist). Root-level in the shared commit path, covered by a new test. It also closes the same divergence for any other non-boolean"false"attribute, not only keep-pitch. - The Speed UI consumes the shared format consistently —
propertyPanelFlatMediaSectionimportsRATE_RANGE/RATE_TARGET/SpeedPresetIdfrom@hyperframes/core, reads theratelane +playback-rateconstant +preserve-pitch, and maps the slider through the sharedRATE_RANGE.useVolumeAutomationis cleanly generalized to bind both the volume and rate lanes bytarget. The new./speed-rampcore subpath (src for bun, dist published) is the right way to expose it to Studio.
Why I'm not stamping — all blockers are downstack
- Merge-order: stacked on #4143 (tai's, engine) → #4129 (core), and #4129 is a draft I'm holding (its own CI is red and it's coupled to #4143). #4153 can't merge before both, and #4129 must be marked ready first.
- The red
Preflighthere is inherited from #4129, not this PR: it failsformat:checkonpackages/core/src/{speedRamp,clock,runtime/media,runtime/playbackRate}.test.ts— #4129's files, which live in this PR's base branch; #4153's own files pass (oxlint0/0). It clears when #4129 isbun run format-ed.player-perf/preview-regression/regression(2-4s) are the usual gating cascade.
Net: #4153 itself is good — the defect fix is well-reasoned and the UI is on the shared format. Unblock it by getting #4129 ready + formatted and #4143 landed; it'll rebase and need a fresh stamp then (the head moves). I'll re-verify the UI wiring end-to-end once it's not sitting on a draft.
Codex disabled per workspace cap — manual pass only.
6fd34f5 to
1b6f5a5
Compare
9def196 to
d85f1a3
Compare
1b6f5a5 to
728b8b0
Compare
e973061 to
f484ba0
Compare
somanshreddy
left a comment
There was a problem hiding this comment.
Approving at f484ba0e — pure replay on the fixed stack, CI green (mergeStateStatus CLEAN, 0 failure conclusions, 0 pending).
My earlier review carries: the keep-pitch fix is a correct root-level preview/persist alignment (resolveOptimisticAttributeValue reusing HTML_BOOLEAN_ATTRIBUTES, so data-preserve-pitch="false" is no longer dropped from the live preview), and the Speed UI consumes the shared core format (RATE_RANGE/RATE_TARGET/speedPresetLane, useVolumeAutomation generalized to both volume + rate lanes). Range-diff identical to what I reviewed.
Stacked on #4143 (@tai's engine half) → merges after it per the stack order. Approving on merit.
Codex disabled per workspace cap — manual pass only.
013e26d to
8d6fc26
Compare
f484ba0 to
6476ed6
Compare
8d6fc26 to
2689165
Compare
c4ac1b5 to
3b5559c
Compare
The base branch was changed.
b7aa702 to
67187a6
Compare
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Automations to automatically generate PRs for you. |
…to 10x hyperframes snapshot clamped the constant playback rate at 5 and ignored a rate lane in data-automation, so a sped-up or ramped clip showed the wrong frame. It now reads the rate through the runtime's own reader and maps time with the shared source-time function.
Adds the speed-ramps reference, corrects the 0.1 to 5 rate range to 0.1 to 10 and the 'speed ramps are not supported' lines in the skills, and regenerates the skills manifest.
…r approximates pitch
A preset on a clip with no data-duration was stretched over a made-up one second. The panel now offers presets only when the duration is known.
… the slice-cap wording
37f12c8 to
59dffa7
Compare
#4153 added supported speed ramps as rate lanes in data-automation. The previously unselected capability tests still required preprocessing. Require the documented rate-lane representation and its precedence over the constant playback rate, matching the runtime resolver.
#4153 added supported speed ramps as rate lanes in data-automation. The previously unselected capability tests still required preprocessing. Require the documented rate-lane representation and its precedence over the constant playback rate, matching the runtime resolver.
* ci: select the remaining orphan tests in their owning runners * ci: provide FFmpeg for the catalog preview witness * ci: pass the installed Chrome path to catalog rendering * test: align creator capability checks with speed ramp support #4153 added supported speed ramps as rate lanes in data-automation. The previously unselected capability tests still required preprocessing. Require the documented rate-lane representation and its precedence over the constant playback rate, matching the runtime resolver.
Speed ramps, end to end: an editor can ramp a clip's speed in Studio, an agent can write the same ramp in the format, and snapshots and the docs agree with the preview and the render. (This folds the former #4170 and #4171 into one PR, one feature, one review.)
What a user can do now
Editor, in Studio
Agent or anyone reading a project, from the CLI
hyperframes snapshotnow shows the right frame for a clip with a speed ramp, and for a clip at a constant rate above 5x. It used to clamp at 5x and ignore the ramp, so those snapshots disagreed with the preview and the render.Anyone learning the format, in the docs
speed-ramps, teaches theratelane indata-automation(fields, presets, what Studio shows, pitch, limits, and which speed limits belong to the viewer instead of the clip).data-playback-raterange in the HTML schema now says 0.1 to 10, and the skills no longer tell agents that speed ramps are unsupported.Shape
@hyperframes/core/speed-rampsubpath mirroring the existing subpath shape."false". The live write now matches the file write for exactly the attributes the patcher treats as booleans, with a regression test.sourceTimeAt/timeAtSourceTime, so there is no second copy of the clamp.packages/core/src/playbackRateBounds.ts); they are not unified.Before
Only a constant Rate slider, no way to automate it:
before.mp4
After
Speed slider, automate toggle, preset picker; applying a preset draws the curve as a lane on the timeline:
after-v2.mp4
Verification
propertyPanelFlatMediaSection,useVolumeAutomation,useDomEditAttributeCommitstests 40 passed;snapshot.test.ts38 passed;tscclean forpackages/cli. Studiotscon the devbox lists only four errors in files that do not exist in this branch (stale leftovers on that copy).hyperframes snapshotof a ramped clip, a docs preview build.Pre-review pass
Each part was reviewed independently before folding, and the combined diff was reviewed again at this head (results in the table). Findings that were fixed along the way (the last two came from the combined review): a Speed preset on a clip with no
data-durationwas stretched over a made-up one second, so the panel now hides presets until the duration is known; one stale 'not in the format' line left in the editing recipes; a snapshot regression where an invalid authored rate ignored the browser default; two docs wording claims (clip length needsdata-duration; the render approximates the curve in quarter-second slices); the docs now state transport speed per surface (Studio menu 0.25 to 2, player menu up to 4, runtime clamps a request to 0.1 to 5).Current-head verification
The focused suites and typechecks above supersede the earlier narrower test note.