feat: add keyframe-animation skill#4
Open
Ripwords wants to merge 2 commits into
Open
Conversation
Add a skill for animating clip properties over time with set_keyframes (fades, Ken Burns push-ins, PIP slides, pans, spins, crop reveals, audio ducks). Grounded in the compositor's actual sampling: scale is a fraction-of-canvas size (>1 zooms in, <1 shrinks), position is the top-left corner, frames are clip-relative, and volume keyframes are in dB. Verified end-to-end against a live project. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Multi-agent audit (audit → adversarial verify) of every factual claim against the app source surfaced and confirmed 15 issues; all fixed: - Wrong tool name: update_clip does not exist; the real tool is set_clip_properties (3 occurrences). - Scale-only zoom auto-centers (topLeftAt else-branch recenters from transform.center each frame); the old "scaling alone drifts to the corner" claim was backwards. Position lockstep is only needed for off-center moves or when a position track is already active. - apply_layout DELETES position/scale/rotation/crop tracks (animation lost), whereas a static transform via set_clip_properties is merely overridden by an active motion track — run apply_layout first. - Retime gotcha: set_clip_properties speed/duration clamps (not rescales) keyframes and silently drops any past the new end, flattening a move to a constant (looks like a hard cut). - Volume dB range: positive boosts, capped +15 dB; <= -60 dB hard mute. - Opacity keyframes multiply with the native fade envelope (double-fade risk), they don't replace it. - Interp token must sit inside the leaving (first) row of its segment; a bare trailing "linear" is rejected by the parser. Fixed the slow-pan, spin, and audio-duck recipes. - Live-preview caveat: transform keyframes render on PLAYBACK and frame-stepping; scrub-dragging can under-render a short move (the "hard cut" symptom). MCP edits auto-rebuild the preview. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Author
keyframe-demo.mp4Used the skill to create something dramatic just to confirm that it's working |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds a new skill,
keyframe-animation, for animating a clip's properties over time inside Palmier Pro via theset_keyframesMCP tool — fades, Ken Burns push-ins, PIP slides, slow pans, spins, crop reveals, and audio ducks.Why it's grounded (not guessed)
The skill is written against the compositor's actual sampling behavior (read from
Models/Timeline.swift,Models/Keyframe.swift,ToolExecutor+Clips.swift) and verified end-to-end against a live project by rendering composited frames withinspect_timeline. Two things the intuitive reading gets wrong — and that this skill nails:scaleis the clip's size as a fraction of the canvas, not a zoom factor.> 1overfills and crops (zoom in);< 1shrinks and shows background (zoom out). Keeping a zoom centered requires movingposition(the top-left corner) in lockstep:topLeft = (1 − size) / 2, which goes negative for a push-in.volumekeyframes are in dB (0 = unchanged), not linear 0–1 — the staticvolumescalar is the 0–1 one.Also documents the clip-relative frame model, whole-track replacement, no-extrapolation holds,
linear|hold|smoothinterpolation, and the order-of-operations rule (setting a scalar clears the keyframe track).Validation
node scripts/build-catalog.mjsrun;catalog.jsonregenerated and committed.🤖 Generated with Claude Code