@pixerate/editor 0.61.0 → 0.63.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -36,6 +36,10 @@ interface MotionScene {
36
36
  * per second ("on twos" at 12), for a hand-drawn look. Default: smooth.
37
37
  */
38
38
  steps?: number;
39
+ /** A beat grid to cue shots to (`MotionShot.at.beat`): music or a voiceover's rhythm. */
40
+ beat?: MotionBeatGrid;
41
+ /** A voiceover's words with their times, to cue shots to (`MotionShot.at.word`). */
42
+ narration?: MotionNarration;
39
43
  /** Wanted length in seconds `[min, max]`; `check` warns outside it. */
40
44
  target?: [number, number];
41
45
  /** Parameters a Flair effect made from this scene exposes (see `toFlairVectorEffect`). */
@@ -63,6 +67,31 @@ type MotionCamera = (MotionRect | {
63
67
  /** Zoom at a steady rate (the size changes by the same factor each moment) instead of linearly. */
64
68
  geometric?: boolean;
65
69
  };
70
+ /** A steady beat: `bpm` beats a minute, the first at `offset` ms, `meter` beats a bar. */
71
+ interface MotionBeatGrid {
72
+ bpm: number;
73
+ /** When beat 0 falls, ms (default 0). */
74
+ offset?: number;
75
+ /** Beats in a bar (default 4), for reading beats as bar and beat. */
76
+ meter?: number;
77
+ }
78
+ /** A voiceover: its words in order, each with when it is said (ms), from a TTS or speech-to-text word timing. */
79
+ interface MotionNarration {
80
+ words: {
81
+ text: string;
82
+ start: number;
83
+ end?: number;
84
+ }[];
85
+ }
86
+ /** When a shot is cued to start: on a beat, on a narration word, or at a time. */
87
+ interface MotionCue {
88
+ /** Beat number on the scene's beat grid, from 0 (fractions for off-beats: 2.5 is the "and" of beat 3). */
89
+ beat?: number;
90
+ /** Index of a word in the scene's narration, from 0. */
91
+ word?: number;
92
+ /** A time in ms. */
93
+ ms?: number;
94
+ }
66
95
  /** One beat of the animation. */
67
96
  interface MotionShot {
68
97
  /** Stable id (unique in the scene), e.g. `intro`. */
@@ -71,10 +100,21 @@ interface MotionShot {
71
100
  label?: string;
72
101
  /** Omit to keep the current framing. */
73
102
  camera?: MotionCamera;
103
+ /**
104
+ * Start on a cue: a beat, a narration word or a time. The shot before holds until then; a
105
+ * cue that comes before the shot before has ended is missed (`check` says by how much).
106
+ * Give one of `beat`, `word` or `ms`.
107
+ */
108
+ at?: MotionCue;
74
109
  /** Commands, played one after another (unless a command says `with: "previous"`). */
75
110
  run: MotionCommand[];
76
111
  /** Milliseconds to hold after the commands finish (default 600). */
77
112
  hold?: number;
113
+ /**
114
+ * Plays the whole shot this many times as fast (default 1): its camera move, delays,
115
+ * durations, staggers and hold all scale by 1 / speed. `fit_animation` sets it to fit a length.
116
+ */
117
+ speed?: number;
78
118
  }
79
119
  /** Fields every command takes. */
80
120
  interface MotionCommandBase {
@@ -492,6 +532,14 @@ declare const MOTION_ISSUE_CODES: {
492
532
  readonly severity: "warning";
493
533
  readonly wording: "A spring is given a duration shorter than it takes to settle, so it jumps to its end.";
494
534
  };
535
+ readonly 'unknown-cue': {
536
+ readonly severity: "error";
537
+ readonly wording: "A shot is cued to a beat with no beat grid, or to a word the narration does not have.";
538
+ };
539
+ readonly 'cue-missed': {
540
+ readonly severity: "warning";
541
+ readonly wording: "A shot starts after its cue, because the shot before runs past it.";
542
+ };
495
543
  readonly 'scene-too-long': {
496
544
  readonly severity: "warning";
497
545
  readonly wording: "The scene runs past its target length.";
@@ -626,6 +674,10 @@ interface MotionShotTiming {
626
674
  /** When the last command ends (the hold follows). */
627
675
  commandsEnd: number;
628
676
  end: number;
677
+ /** The time the shot is cued to start (`at`), when it has a cue that resolves. */
678
+ cue?: number;
679
+ /** How late the shot starts after its cue (ms), when the shot before ran past it. */
680
+ missedBy?: number;
629
681
  }
630
682
  interface MotionCommandTiming {
631
683
  shot: string;
@@ -730,6 +782,18 @@ declare function fitMotionRect(rect: MotionRect, aspect: number): MotionRect;
730
782
  declare function resolveMotionCamera(camera: MotionCamera, scene: MotionScene): MotionRect | null;
731
783
  /** Length of a node's outline (its longest path for a group), in document units. */
732
784
  declare function motionPathLength(node: VectorNode, parentWorld?: AffineMatrix): number;
785
+ /** How much a shot's `speed` stretches its time (1 / speed; 1 when unset or not above 0). */
786
+ declare function motionShotTimeScale(shot: MotionShot): number;
787
+ /** When beat `beat` falls on a grid, ms: `offset + beat · 60000 / bpm`. */
788
+ declare function motionBeatTime(grid: MotionBeatGrid, beat: number): number;
789
+ /** The beat (fractional) at `ms` on a grid, and its bar and beat in the bar (both from 1). */
790
+ declare function motionBeatAt(grid: MotionBeatGrid, ms: number): {
791
+ beat: number;
792
+ bar: number;
793
+ beatInBar: number;
794
+ };
795
+ /** The time a cue names, ms, or undefined when it names a beat with no grid or a word the narration lacks. */
796
+ declare function motionCueTime(scene: Pick<MotionScene, 'beat' | 'narration'>, cue: MotionCue): number | undefined;
733
797
  /** How many times a command plays (1 for `enter`, `exit` and `wait`, which do not repeat). */
734
798
  declare function motionCommandRepeat(command: MotionCommand): number;
735
799
  /** How long one target of a command takes (ms), every repeat included. */
@@ -868,6 +932,8 @@ type MotionEdit = {
868
932
  loop?: MotionScene['loop'];
869
933
  fps?: number;
870
934
  steps?: number | null;
935
+ beat?: MotionScene['beat'] | null;
936
+ narration?: MotionScene['narration'] | null;
871
937
  target?: [number, number] | null;
872
938
  } | {
873
939
  op: 'insert_shots';
@@ -877,7 +943,7 @@ type MotionEdit = {
877
943
  op: 'update_shot';
878
944
  shot: string;
879
945
  set?: Partial<MotionShot>;
880
- remove?: ('label' | 'camera' | 'hold')[];
946
+ remove?: ('label' | 'camera' | 'hold' | 'speed' | 'at')[];
881
947
  } | {
882
948
  op: 'delete_shots';
883
949
  shots: string[];
@@ -931,6 +997,27 @@ declare function applyMotionEdits(scene: MotionScene, edits: MotionEdit | readon
931
997
  /** An empty scene over `artwork`. */
932
998
  declare function createMotionScene(artwork: VectorDocument, init?: Partial<Omit<MotionScene, 'artwork' | 'version'>>): MotionScene;
933
999
 
1000
+ interface MotionFitOptions {
1001
+ /** Shot ids that keep their pace (a logo hold, a line of narration); the others absorb the change. */
1002
+ keep?: readonly string[];
1003
+ }
1004
+ interface MotionFit {
1005
+ scene: MotionScene;
1006
+ /** The length after fitting, ms (within a few ms of the target: speeds are rounded). */
1007
+ duration: number;
1008
+ /** The new `speed` of every shot that changed. */
1009
+ speeds: Record<string, number>;
1010
+ }
1011
+ /** Speeds are kept within this range. */
1012
+ declare const MOTION_SPEED_RANGE: readonly [number, number];
1013
+ /**
1014
+ * Fits a scene to `ms` by setting its shots' `speed`: the shots in `keep` play as they are and
1015
+ * the rest stretch or squeeze by the same factor, so their timing keeps its proportions (the
1016
+ * responsive time of After Effects' protected regions). Throws, changing nothing, when the
1017
+ * kept shots alone outlast the target or a speed would leave `MOTION_SPEED_RANGE`.
1018
+ */
1019
+ declare function fitMotionScene(scene: MotionScene, ms: number, options?: MotionFitOptions): MotionFit;
1020
+
934
1021
  /**
935
1022
  * Export to Flair (`@pixerate/flair`): a scene becomes an `SvgMotion` (one SVG plus a list of
936
1023
  * from → to changes on its elements), a catalog `VectorEffect`, or an `EffectDocument` for
@@ -1655,6 +1742,8 @@ declare function describeMotionShots(scene: MotionScene): {
1655
1742
  note?: string;
1656
1743
  index: number;
1657
1744
  })[];
1745
+ missedBy?: number | undefined;
1746
+ cue?: number | undefined;
1658
1747
  hold?: number | undefined;
1659
1748
  camera?: MotionCamera | undefined;
1660
1749
  start: number;
@@ -1675,6 +1764,6 @@ declare function createAnimationEditorToolProvider(controller: AnimationEditorCo
1675
1764
  * A short authoring guide for a model writing vector animations with the animation editor's
1676
1765
  * tools. Static, so it caches well as part of a system prompt.
1677
1766
  */
1678
- declare const ANIMATION_EDITOR_AGENT_INSTRUCTIONS = "You animate vector artwork. A scene is artwork (vector paths and groups, each with an id) plus shots.\n\nHow it plays\n- Shots play in order. A shot optionally moves the camera, plays its commands, then holds (default 600 ms).\n- Commands in a shot play one after another; give \"with\": \"previous\" to start one together with the command before, \"delay\" to wait, \"stagger\" to offset several targets.\n- Timing comes from the content: each command has a default length (enter 600 ms, move 700 ms, draw follows the path length). Only set \"duration\" to change the pace.\n- Anything that enters later is hidden until it enters. Things that never enter are visible from the start.\n- Every frame is a pure function of time: the same scene always plays the same frames.\n\nCommands\n- enter (fade, pop, grow, slide, draw) and exit (fade, shrink, slide, undraw) bring things in and out.\n- enter also reveals through a clip over the target's box: wipe (behind an edge travelling \"direction\", default right), iris (from the centre; \"shape\": circle or box) and split (from a line through the middle; \"orientation\": horizontal or vertical). exit wipe hides the same way. Reveals need a width and a height: use draw / undraw for a straight line.\n- draw draws strokes on to a fraction; move, rotate, scale and fade change the pose (about the centre); style blends solid colours and stroke width.\n- enter also has zoom (settles from larger) and rise (rises a short way, overshooting a touch); pop and zoom take a starting \"scale\".\n- morph turns a shape into another node's shape (keep the target hidden); match does the same for a whole group, part by part (Smart Animate: draw the end state as a second, hidden group whose parts share names with the first); follow moves along a path node (with \"rotate\", moves made meanwhile turn with the path).\n- Emphasis draws the eye and returns to rest: pulse (swell), shake (side to side, or \"axis\": \"vertical\"), teeter (rock), wave (bob, no settling), wiggle (seeded wander; the same seed wanders the same way) and color-pulse (tint and back).\n- Emphasis stacks on other motion: a shake during a slide shakes as it slides. Give move, rotate or scale \"blend\": \"add\" to stack them too (what they add stays); \"blend\": \"replace\" makes a change take over instead.\n- Any command but enter and exit can \"repeat\" (loop, mirror back and forth, or offset to carry on: rotate by 90, repeat 4 is a full turn); \"duration\" is one cycle.\n- Springs (\"spring-gentle\", \"spring-quick\", \"spring-bouncy\", \"spring-slow\" or { \"type\": \"spring\", \u2026 }) feel physical; leave \"duration\" out and the spring sets it.\n- \"steps\": 12 (on a command, or for the whole scene with set_animation_settings) holds poses \"on twos\" for a hand-drawn look. \"geometric\": true on scale or a camera zooms at an even rate.\n- Commands share their names and defaults with Flair's motion primitives (get_animation shows each one's \"flairPrimitive\"), and emphasis, reveals and follows export to Flair exactly.\n- effect tweens a numeric parameter of a live path effect already on the node (twist angle, wiggle time, zig zag size).\n\nWorking method\n1. get_animation to learn the element ids (set_animation_artwork_svg first if there is no artwork: give every element you will animate an id; or import_flair_effect to start from a Flair effect and edit it).\n2. Plan a few shots, each one idea. Add them with insert_shots, or edit_animation to make several edits as one step (dry_run first when unsure).\n3. check_animation and fix every error and warning; render_animation_frame (shot + \"end\") to look at the result.\n4. To make a reusable Flair effect, set_animation_controls (colour controls stand for every use of their default colour) and export_flair_effect.\n\nKeep motion purposeful: one thing moving at a time reads best, ease-out for arrivals, ease-in for exits, and hold long enough to see each result.";
1767
+ declare const ANIMATION_EDITOR_AGENT_INSTRUCTIONS = "You animate vector artwork. A scene is artwork (vector paths and groups, each with an id) plus shots.\n\nHow it plays\n- Shots play in order. A shot optionally moves the camera, plays its commands, then holds (default 600 ms).\n- Commands in a shot play one after another; give \"with\": \"previous\" to start one together with the command before, \"delay\" to wait, \"stagger\" to offset several targets.\n- Timing comes from the content: each command has a default length (enter 600 ms, move 700 ms, draw follows the path length). Only set \"duration\" to change the pace.\n- Anything that enters later is hidden until it enters. Things that never enter are visible from the start.\n- Every frame is a pure function of time: the same scene always plays the same frames.\n\nCommands\n- enter (fade, pop, grow, slide, draw) and exit (fade, shrink, slide, undraw) bring things in and out.\n- enter also reveals through a clip over the target's box: wipe (behind an edge travelling \"direction\", default right), iris (from the centre; \"shape\": circle or box) and split (from a line through the middle; \"orientation\": horizontal or vertical). exit wipe hides the same way. Reveals need a width and a height: use draw / undraw for a straight line.\n- draw draws strokes on to a fraction; move, rotate, scale and fade change the pose (about the centre); style blends solid colours and stroke width.\n- enter also has zoom (settles from larger) and rise (rises a short way, overshooting a touch); pop and zoom take a starting \"scale\".\n- morph turns a shape into another node's shape (keep the target hidden); match does the same for a whole group, part by part (Smart Animate: draw the end state as a second, hidden group whose parts share names with the first); follow moves along a path node (with \"rotate\", moves made meanwhile turn with the path).\n- Emphasis draws the eye and returns to rest: pulse (swell), shake (side to side, or \"axis\": \"vertical\"), teeter (rock), wave (bob, no settling), wiggle (seeded wander; the same seed wanders the same way) and color-pulse (tint and back).\n- Emphasis stacks on other motion: a shake during a slide shakes as it slides. Give move, rotate or scale \"blend\": \"add\" to stack them too (what they add stays); \"blend\": \"replace\" makes a change take over instead.\n- Any command but enter and exit can \"repeat\" (loop, mirror back and forth, or offset to carry on: rotate by 90, repeat 4 is a full turn); \"duration\" is one cycle.\n- Springs (\"spring-gentle\", \"spring-quick\", \"spring-bouncy\", \"spring-slow\" or { \"type\": \"spring\", \u2026 }) feel physical; leave \"duration\" out and the spring sets it.\n- To time shots to music or a voiceover: set a \"beat\" grid or \"narration\" word timings with set_animation_settings, read them with get_timing_grid, and give a shot \"at\": { \"beat\": n } or { \"word\": i }. The shot before holds until the cue; check_animation warns when a cue is missed.\n- \"steps\": 12 (on a command, or for the whole scene with set_animation_settings) holds poses \"on twos\" for a hand-drawn look. \"geometric\": true on scale or a camera zooms at an even rate.\n- Commands share their names and defaults with Flair's motion primitives (get_animation shows each one's \"flairPrimitive\"), and emphasis, reveals and follows export to Flair exactly.\n- effect tweens a numeric parameter of a live path effect already on the node (twist angle, wiggle time, zig zag size).\n\nWorking method\n1. get_animation to learn the element ids (set_animation_artwork_svg first if there is no artwork: give every element you will animate an id; or import_flair_effect to start from a Flair effect and edit it).\n2. Plan a few shots, each one idea. Add them with insert_shots, or edit_animation to make several edits as one step (dry_run first when unsure).\n3. To hit a length, fit_animation (keep the shots whose pace matters). check_animation and fix every error and warning; render_animation_frame (shot + \"end\") to look at the result.\n4. To make a reusable Flair effect, set_animation_controls (colour controls stand for every use of their default colour) and export_flair_effect.\n\nKeep motion purposeful: one thing moving at a time reads best, ease-out for arrivals, ease-in for exits, and hold long enough to see each result.";
1679
1768
 
1680
- export { ANIMATION_EDITOR_AGENT_INSTRUCTIONS, AnimationEditorController, type AnimationEditorOptions, type AnimationEditorSelection, type AnimationEditorState, type AnimationEditorToolProviderOptions, FLAIR_EASES, FLAIR_EXPORT_VERSION, type FlairEase, type FlairEaseName, type FlairEffectDocument, type FlairEffectOptions, type FlairExportOptions, type FlairImportOptions, type FlairImportResult, type FlairMotionExport, type FlairSpringEase, type FlairSvgAnimation, type FlairSvgMotion, type FlairVectorEffect, MOTION_ADDITIVE_PROPERTIES, MOTION_BLENDS, MOTION_CAMERA_MS, MOTION_COMMAND_SCHEMA, MOTION_COMMAND_TYPES, MOTION_DEFAULT_DURATIONS, MOTION_DEFAULT_HOLD, MOTION_DIRECTIONS, MOTION_DRAW_EFFECT_ID, MOTION_DRAW_MS_PER_UNIT, MOTION_DRAW_RANGE, MOTION_EASE_IN_OUT, MOTION_EASE_OUT, MOTION_EDIT_OPS, MOTION_ENTER_STYLES, MOTION_EXIT_STYLES, MOTION_IRIS_SHAPES, MOTION_ISSUE_CODES, MOTION_MIN_CHANGE_MS, MOTION_REPEAT_MODES, MOTION_SPLIT_ORIENTATIONS, type MotionCamera, type MotionClipShape, type MotionColorPulseCommand, type MotionCommand, type MotionCommandBase, type MotionCommandTiming, type MotionCommandType, type MotionControl, type MotionDirection, type MotionDrawCommand, type MotionEdit, type MotionEditOp, type MotionEditResult, type MotionEffectCommand, type MotionEnterCommand, type MotionEnterStyle, type MotionExitCommand, type MotionExitStyle, type MotionFadeCommand, type MotionFollowCommand, type MotionFrame, type MotionFrameOptions, type MotionIrisShape, type MotionIssue, type MotionIssueCode, type MotionIssueSeverity, type MotionMatch, type MotionMatchCommand, type MotionMorphCommand, type MotionMoveCommand, type MotionNodeEntry, type MotionPreset, type MotionProperty, type MotionPulseCommand, type MotionRect, type MotionReveal, type MotionRotateCommand, type MotionScaleCommand, type MotionScene, MotionSceneFormatError, type MotionSegment, type MotionShakeCommand, type MotionShot, type MotionShotTiming, type MotionSplitOrientation, type MotionStyleCommand, type MotionSvgOptions, type MotionTeeterCommand, type MotionTimeline, type MotionValue, type MotionWaitCommand, type MotionWaveCommand, type MotionWiggleCommand, activeSegment, applyMotionControlValues, applyMotionEdits, checkMotionScene, commandShapeProblems, compileMotionScene, createAnimationEditorToolProvider, createMotionScene, describeMotionElements, describeMotionShots, fitMotionRect, flairAtLeast, flairCurveFor, flairEaseFor, freshShotId, fromFlairSvgMotion, fromFlairVectorEffect, indexMotionNodes, interpolateMotionValue, isMotionCommand, isMotionShot, matchMotionNodes, motionAddTrackKey, motionClipAttrs, motionCommandDuration, motionCommandRepeat, motionCycleDuration, motionFlairPrimitive, motionFollowRoute, motionFrameAt, motionFrameToSvg, motionIssue, motionIssueKey, motionIssueLine, motionNodeClips, motionNodeOffset, motionPathLength, motionRestValue, motionRevealClip, motionRevealPadding, motionSceneShapeProblems, motionSceneToJson, motionShotAt, motionTrackKey, namedWithSuggestion, parseMotionScene, resolveMotionCamera, segmentProgress, segmentValue, shotShapeProblems, suggestName, toFlairEffectDocument, toFlairSvgMotion, toFlairVectorEffect, trackValue, withMotionLayers, withViewBox };
1769
+ export { ANIMATION_EDITOR_AGENT_INSTRUCTIONS, AnimationEditorController, type AnimationEditorOptions, type AnimationEditorSelection, type AnimationEditorState, type AnimationEditorToolProviderOptions, FLAIR_EASES, FLAIR_EXPORT_VERSION, type FlairEase, type FlairEaseName, type FlairEffectDocument, type FlairEffectOptions, type FlairExportOptions, type FlairImportOptions, type FlairImportResult, type FlairMotionExport, type FlairSpringEase, type FlairSvgAnimation, type FlairSvgMotion, type FlairVectorEffect, MOTION_ADDITIVE_PROPERTIES, MOTION_BLENDS, MOTION_CAMERA_MS, MOTION_COMMAND_SCHEMA, MOTION_COMMAND_TYPES, MOTION_DEFAULT_DURATIONS, MOTION_DEFAULT_HOLD, MOTION_DIRECTIONS, MOTION_DRAW_EFFECT_ID, MOTION_DRAW_MS_PER_UNIT, MOTION_DRAW_RANGE, MOTION_EASE_IN_OUT, MOTION_EASE_OUT, MOTION_EDIT_OPS, MOTION_ENTER_STYLES, MOTION_EXIT_STYLES, MOTION_IRIS_SHAPES, MOTION_ISSUE_CODES, MOTION_MIN_CHANGE_MS, MOTION_REPEAT_MODES, MOTION_SPEED_RANGE, MOTION_SPLIT_ORIENTATIONS, type MotionBeatGrid, type MotionCamera, type MotionClipShape, type MotionColorPulseCommand, type MotionCommand, type MotionCommandBase, type MotionCommandTiming, type MotionCommandType, type MotionControl, type MotionCue, type MotionDirection, type MotionDrawCommand, type MotionEdit, type MotionEditOp, type MotionEditResult, type MotionEffectCommand, type MotionEnterCommand, type MotionEnterStyle, type MotionExitCommand, type MotionExitStyle, type MotionFadeCommand, type MotionFit, type MotionFitOptions, type MotionFollowCommand, type MotionFrame, type MotionFrameOptions, type MotionIrisShape, type MotionIssue, type MotionIssueCode, type MotionIssueSeverity, type MotionMatch, type MotionMatchCommand, type MotionMorphCommand, type MotionMoveCommand, type MotionNarration, type MotionNodeEntry, type MotionPreset, type MotionProperty, type MotionPulseCommand, type MotionRect, type MotionReveal, type MotionRotateCommand, type MotionScaleCommand, type MotionScene, MotionSceneFormatError, type MotionSegment, type MotionShakeCommand, type MotionShot, type MotionShotTiming, type MotionSplitOrientation, type MotionStyleCommand, type MotionSvgOptions, type MotionTeeterCommand, type MotionTimeline, type MotionValue, type MotionWaitCommand, type MotionWaveCommand, type MotionWiggleCommand, activeSegment, applyMotionControlValues, applyMotionEdits, checkMotionScene, commandShapeProblems, compileMotionScene, createAnimationEditorToolProvider, createMotionScene, describeMotionElements, describeMotionShots, fitMotionRect, fitMotionScene, flairAtLeast, flairCurveFor, flairEaseFor, freshShotId, fromFlairSvgMotion, fromFlairVectorEffect, indexMotionNodes, interpolateMotionValue, isMotionCommand, isMotionShot, matchMotionNodes, motionAddTrackKey, motionBeatAt, motionBeatTime, motionClipAttrs, motionCommandDuration, motionCommandRepeat, motionCueTime, motionCycleDuration, motionFlairPrimitive, motionFollowRoute, motionFrameAt, motionFrameToSvg, motionIssue, motionIssueKey, motionIssueLine, motionNodeClips, motionNodeOffset, motionPathLength, motionRestValue, motionRevealClip, motionRevealPadding, motionSceneShapeProblems, motionSceneToJson, motionShotAt, motionShotTimeScale, motionTrackKey, namedWithSuggestion, parseMotionScene, resolveMotionCamera, segmentProgress, segmentValue, shotShapeProblems, suggestName, toFlairEffectDocument, toFlairSvgMotion, toFlairVectorEffect, trackValue, withMotionLayers, withViewBox };
@@ -36,6 +36,10 @@ interface MotionScene {
36
36
  * per second ("on twos" at 12), for a hand-drawn look. Default: smooth.
37
37
  */
38
38
  steps?: number;
39
+ /** A beat grid to cue shots to (`MotionShot.at.beat`): music or a voiceover's rhythm. */
40
+ beat?: MotionBeatGrid;
41
+ /** A voiceover's words with their times, to cue shots to (`MotionShot.at.word`). */
42
+ narration?: MotionNarration;
39
43
  /** Wanted length in seconds `[min, max]`; `check` warns outside it. */
40
44
  target?: [number, number];
41
45
  /** Parameters a Flair effect made from this scene exposes (see `toFlairVectorEffect`). */
@@ -63,6 +67,31 @@ type MotionCamera = (MotionRect | {
63
67
  /** Zoom at a steady rate (the size changes by the same factor each moment) instead of linearly. */
64
68
  geometric?: boolean;
65
69
  };
70
+ /** A steady beat: `bpm` beats a minute, the first at `offset` ms, `meter` beats a bar. */
71
+ interface MotionBeatGrid {
72
+ bpm: number;
73
+ /** When beat 0 falls, ms (default 0). */
74
+ offset?: number;
75
+ /** Beats in a bar (default 4), for reading beats as bar and beat. */
76
+ meter?: number;
77
+ }
78
+ /** A voiceover: its words in order, each with when it is said (ms), from a TTS or speech-to-text word timing. */
79
+ interface MotionNarration {
80
+ words: {
81
+ text: string;
82
+ start: number;
83
+ end?: number;
84
+ }[];
85
+ }
86
+ /** When a shot is cued to start: on a beat, on a narration word, or at a time. */
87
+ interface MotionCue {
88
+ /** Beat number on the scene's beat grid, from 0 (fractions for off-beats: 2.5 is the "and" of beat 3). */
89
+ beat?: number;
90
+ /** Index of a word in the scene's narration, from 0. */
91
+ word?: number;
92
+ /** A time in ms. */
93
+ ms?: number;
94
+ }
66
95
  /** One beat of the animation. */
67
96
  interface MotionShot {
68
97
  /** Stable id (unique in the scene), e.g. `intro`. */
@@ -71,10 +100,21 @@ interface MotionShot {
71
100
  label?: string;
72
101
  /** Omit to keep the current framing. */
73
102
  camera?: MotionCamera;
103
+ /**
104
+ * Start on a cue: a beat, a narration word or a time. The shot before holds until then; a
105
+ * cue that comes before the shot before has ended is missed (`check` says by how much).
106
+ * Give one of `beat`, `word` or `ms`.
107
+ */
108
+ at?: MotionCue;
74
109
  /** Commands, played one after another (unless a command says `with: "previous"`). */
75
110
  run: MotionCommand[];
76
111
  /** Milliseconds to hold after the commands finish (default 600). */
77
112
  hold?: number;
113
+ /**
114
+ * Plays the whole shot this many times as fast (default 1): its camera move, delays,
115
+ * durations, staggers and hold all scale by 1 / speed. `fit_animation` sets it to fit a length.
116
+ */
117
+ speed?: number;
78
118
  }
79
119
  /** Fields every command takes. */
80
120
  interface MotionCommandBase {
@@ -492,6 +532,14 @@ declare const MOTION_ISSUE_CODES: {
492
532
  readonly severity: "warning";
493
533
  readonly wording: "A spring is given a duration shorter than it takes to settle, so it jumps to its end.";
494
534
  };
535
+ readonly 'unknown-cue': {
536
+ readonly severity: "error";
537
+ readonly wording: "A shot is cued to a beat with no beat grid, or to a word the narration does not have.";
538
+ };
539
+ readonly 'cue-missed': {
540
+ readonly severity: "warning";
541
+ readonly wording: "A shot starts after its cue, because the shot before runs past it.";
542
+ };
495
543
  readonly 'scene-too-long': {
496
544
  readonly severity: "warning";
497
545
  readonly wording: "The scene runs past its target length.";
@@ -626,6 +674,10 @@ interface MotionShotTiming {
626
674
  /** When the last command ends (the hold follows). */
627
675
  commandsEnd: number;
628
676
  end: number;
677
+ /** The time the shot is cued to start (`at`), when it has a cue that resolves. */
678
+ cue?: number;
679
+ /** How late the shot starts after its cue (ms), when the shot before ran past it. */
680
+ missedBy?: number;
629
681
  }
630
682
  interface MotionCommandTiming {
631
683
  shot: string;
@@ -730,6 +782,18 @@ declare function fitMotionRect(rect: MotionRect, aspect: number): MotionRect;
730
782
  declare function resolveMotionCamera(camera: MotionCamera, scene: MotionScene): MotionRect | null;
731
783
  /** Length of a node's outline (its longest path for a group), in document units. */
732
784
  declare function motionPathLength(node: VectorNode, parentWorld?: AffineMatrix): number;
785
+ /** How much a shot's `speed` stretches its time (1 / speed; 1 when unset or not above 0). */
786
+ declare function motionShotTimeScale(shot: MotionShot): number;
787
+ /** When beat `beat` falls on a grid, ms: `offset + beat · 60000 / bpm`. */
788
+ declare function motionBeatTime(grid: MotionBeatGrid, beat: number): number;
789
+ /** The beat (fractional) at `ms` on a grid, and its bar and beat in the bar (both from 1). */
790
+ declare function motionBeatAt(grid: MotionBeatGrid, ms: number): {
791
+ beat: number;
792
+ bar: number;
793
+ beatInBar: number;
794
+ };
795
+ /** The time a cue names, ms, or undefined when it names a beat with no grid or a word the narration lacks. */
796
+ declare function motionCueTime(scene: Pick<MotionScene, 'beat' | 'narration'>, cue: MotionCue): number | undefined;
733
797
  /** How many times a command plays (1 for `enter`, `exit` and `wait`, which do not repeat). */
734
798
  declare function motionCommandRepeat(command: MotionCommand): number;
735
799
  /** How long one target of a command takes (ms), every repeat included. */
@@ -868,6 +932,8 @@ type MotionEdit = {
868
932
  loop?: MotionScene['loop'];
869
933
  fps?: number;
870
934
  steps?: number | null;
935
+ beat?: MotionScene['beat'] | null;
936
+ narration?: MotionScene['narration'] | null;
871
937
  target?: [number, number] | null;
872
938
  } | {
873
939
  op: 'insert_shots';
@@ -877,7 +943,7 @@ type MotionEdit = {
877
943
  op: 'update_shot';
878
944
  shot: string;
879
945
  set?: Partial<MotionShot>;
880
- remove?: ('label' | 'camera' | 'hold')[];
946
+ remove?: ('label' | 'camera' | 'hold' | 'speed' | 'at')[];
881
947
  } | {
882
948
  op: 'delete_shots';
883
949
  shots: string[];
@@ -931,6 +997,27 @@ declare function applyMotionEdits(scene: MotionScene, edits: MotionEdit | readon
931
997
  /** An empty scene over `artwork`. */
932
998
  declare function createMotionScene(artwork: VectorDocument, init?: Partial<Omit<MotionScene, 'artwork' | 'version'>>): MotionScene;
933
999
 
1000
+ interface MotionFitOptions {
1001
+ /** Shot ids that keep their pace (a logo hold, a line of narration); the others absorb the change. */
1002
+ keep?: readonly string[];
1003
+ }
1004
+ interface MotionFit {
1005
+ scene: MotionScene;
1006
+ /** The length after fitting, ms (within a few ms of the target: speeds are rounded). */
1007
+ duration: number;
1008
+ /** The new `speed` of every shot that changed. */
1009
+ speeds: Record<string, number>;
1010
+ }
1011
+ /** Speeds are kept within this range. */
1012
+ declare const MOTION_SPEED_RANGE: readonly [number, number];
1013
+ /**
1014
+ * Fits a scene to `ms` by setting its shots' `speed`: the shots in `keep` play as they are and
1015
+ * the rest stretch or squeeze by the same factor, so their timing keeps its proportions (the
1016
+ * responsive time of After Effects' protected regions). Throws, changing nothing, when the
1017
+ * kept shots alone outlast the target or a speed would leave `MOTION_SPEED_RANGE`.
1018
+ */
1019
+ declare function fitMotionScene(scene: MotionScene, ms: number, options?: MotionFitOptions): MotionFit;
1020
+
934
1021
  /**
935
1022
  * Export to Flair (`@pixerate/flair`): a scene becomes an `SvgMotion` (one SVG plus a list of
936
1023
  * from → to changes on its elements), a catalog `VectorEffect`, or an `EffectDocument` for
@@ -1655,6 +1742,8 @@ declare function describeMotionShots(scene: MotionScene): {
1655
1742
  note?: string;
1656
1743
  index: number;
1657
1744
  })[];
1745
+ missedBy?: number | undefined;
1746
+ cue?: number | undefined;
1658
1747
  hold?: number | undefined;
1659
1748
  camera?: MotionCamera | undefined;
1660
1749
  start: number;
@@ -1675,6 +1764,6 @@ declare function createAnimationEditorToolProvider(controller: AnimationEditorCo
1675
1764
  * A short authoring guide for a model writing vector animations with the animation editor's
1676
1765
  * tools. Static, so it caches well as part of a system prompt.
1677
1766
  */
1678
- declare const ANIMATION_EDITOR_AGENT_INSTRUCTIONS = "You animate vector artwork. A scene is artwork (vector paths and groups, each with an id) plus shots.\n\nHow it plays\n- Shots play in order. A shot optionally moves the camera, plays its commands, then holds (default 600 ms).\n- Commands in a shot play one after another; give \"with\": \"previous\" to start one together with the command before, \"delay\" to wait, \"stagger\" to offset several targets.\n- Timing comes from the content: each command has a default length (enter 600 ms, move 700 ms, draw follows the path length). Only set \"duration\" to change the pace.\n- Anything that enters later is hidden until it enters. Things that never enter are visible from the start.\n- Every frame is a pure function of time: the same scene always plays the same frames.\n\nCommands\n- enter (fade, pop, grow, slide, draw) and exit (fade, shrink, slide, undraw) bring things in and out.\n- enter also reveals through a clip over the target's box: wipe (behind an edge travelling \"direction\", default right), iris (from the centre; \"shape\": circle or box) and split (from a line through the middle; \"orientation\": horizontal or vertical). exit wipe hides the same way. Reveals need a width and a height: use draw / undraw for a straight line.\n- draw draws strokes on to a fraction; move, rotate, scale and fade change the pose (about the centre); style blends solid colours and stroke width.\n- enter also has zoom (settles from larger) and rise (rises a short way, overshooting a touch); pop and zoom take a starting \"scale\".\n- morph turns a shape into another node's shape (keep the target hidden); match does the same for a whole group, part by part (Smart Animate: draw the end state as a second, hidden group whose parts share names with the first); follow moves along a path node (with \"rotate\", moves made meanwhile turn with the path).\n- Emphasis draws the eye and returns to rest: pulse (swell), shake (side to side, or \"axis\": \"vertical\"), teeter (rock), wave (bob, no settling), wiggle (seeded wander; the same seed wanders the same way) and color-pulse (tint and back).\n- Emphasis stacks on other motion: a shake during a slide shakes as it slides. Give move, rotate or scale \"blend\": \"add\" to stack them too (what they add stays); \"blend\": \"replace\" makes a change take over instead.\n- Any command but enter and exit can \"repeat\" (loop, mirror back and forth, or offset to carry on: rotate by 90, repeat 4 is a full turn); \"duration\" is one cycle.\n- Springs (\"spring-gentle\", \"spring-quick\", \"spring-bouncy\", \"spring-slow\" or { \"type\": \"spring\", \u2026 }) feel physical; leave \"duration\" out and the spring sets it.\n- \"steps\": 12 (on a command, or for the whole scene with set_animation_settings) holds poses \"on twos\" for a hand-drawn look. \"geometric\": true on scale or a camera zooms at an even rate.\n- Commands share their names and defaults with Flair's motion primitives (get_animation shows each one's \"flairPrimitive\"), and emphasis, reveals and follows export to Flair exactly.\n- effect tweens a numeric parameter of a live path effect already on the node (twist angle, wiggle time, zig zag size).\n\nWorking method\n1. get_animation to learn the element ids (set_animation_artwork_svg first if there is no artwork: give every element you will animate an id; or import_flair_effect to start from a Flair effect and edit it).\n2. Plan a few shots, each one idea. Add them with insert_shots, or edit_animation to make several edits as one step (dry_run first when unsure).\n3. check_animation and fix every error and warning; render_animation_frame (shot + \"end\") to look at the result.\n4. To make a reusable Flair effect, set_animation_controls (colour controls stand for every use of their default colour) and export_flair_effect.\n\nKeep motion purposeful: one thing moving at a time reads best, ease-out for arrivals, ease-in for exits, and hold long enough to see each result.";
1767
+ declare const ANIMATION_EDITOR_AGENT_INSTRUCTIONS = "You animate vector artwork. A scene is artwork (vector paths and groups, each with an id) plus shots.\n\nHow it plays\n- Shots play in order. A shot optionally moves the camera, plays its commands, then holds (default 600 ms).\n- Commands in a shot play one after another; give \"with\": \"previous\" to start one together with the command before, \"delay\" to wait, \"stagger\" to offset several targets.\n- Timing comes from the content: each command has a default length (enter 600 ms, move 700 ms, draw follows the path length). Only set \"duration\" to change the pace.\n- Anything that enters later is hidden until it enters. Things that never enter are visible from the start.\n- Every frame is a pure function of time: the same scene always plays the same frames.\n\nCommands\n- enter (fade, pop, grow, slide, draw) and exit (fade, shrink, slide, undraw) bring things in and out.\n- enter also reveals through a clip over the target's box: wipe (behind an edge travelling \"direction\", default right), iris (from the centre; \"shape\": circle or box) and split (from a line through the middle; \"orientation\": horizontal or vertical). exit wipe hides the same way. Reveals need a width and a height: use draw / undraw for a straight line.\n- draw draws strokes on to a fraction; move, rotate, scale and fade change the pose (about the centre); style blends solid colours and stroke width.\n- enter also has zoom (settles from larger) and rise (rises a short way, overshooting a touch); pop and zoom take a starting \"scale\".\n- morph turns a shape into another node's shape (keep the target hidden); match does the same for a whole group, part by part (Smart Animate: draw the end state as a second, hidden group whose parts share names with the first); follow moves along a path node (with \"rotate\", moves made meanwhile turn with the path).\n- Emphasis draws the eye and returns to rest: pulse (swell), shake (side to side, or \"axis\": \"vertical\"), teeter (rock), wave (bob, no settling), wiggle (seeded wander; the same seed wanders the same way) and color-pulse (tint and back).\n- Emphasis stacks on other motion: a shake during a slide shakes as it slides. Give move, rotate or scale \"blend\": \"add\" to stack them too (what they add stays); \"blend\": \"replace\" makes a change take over instead.\n- Any command but enter and exit can \"repeat\" (loop, mirror back and forth, or offset to carry on: rotate by 90, repeat 4 is a full turn); \"duration\" is one cycle.\n- Springs (\"spring-gentle\", \"spring-quick\", \"spring-bouncy\", \"spring-slow\" or { \"type\": \"spring\", \u2026 }) feel physical; leave \"duration\" out and the spring sets it.\n- To time shots to music or a voiceover: set a \"beat\" grid or \"narration\" word timings with set_animation_settings, read them with get_timing_grid, and give a shot \"at\": { \"beat\": n } or { \"word\": i }. The shot before holds until the cue; check_animation warns when a cue is missed.\n- \"steps\": 12 (on a command, or for the whole scene with set_animation_settings) holds poses \"on twos\" for a hand-drawn look. \"geometric\": true on scale or a camera zooms at an even rate.\n- Commands share their names and defaults with Flair's motion primitives (get_animation shows each one's \"flairPrimitive\"), and emphasis, reveals and follows export to Flair exactly.\n- effect tweens a numeric parameter of a live path effect already on the node (twist angle, wiggle time, zig zag size).\n\nWorking method\n1. get_animation to learn the element ids (set_animation_artwork_svg first if there is no artwork: give every element you will animate an id; or import_flair_effect to start from a Flair effect and edit it).\n2. Plan a few shots, each one idea. Add them with insert_shots, or edit_animation to make several edits as one step (dry_run first when unsure).\n3. To hit a length, fit_animation (keep the shots whose pace matters). check_animation and fix every error and warning; render_animation_frame (shot + \"end\") to look at the result.\n4. To make a reusable Flair effect, set_animation_controls (colour controls stand for every use of their default colour) and export_flair_effect.\n\nKeep motion purposeful: one thing moving at a time reads best, ease-out for arrivals, ease-in for exits, and hold long enough to see each result.";
1679
1768
 
1680
- export { ANIMATION_EDITOR_AGENT_INSTRUCTIONS, AnimationEditorController, type AnimationEditorOptions, type AnimationEditorSelection, type AnimationEditorState, type AnimationEditorToolProviderOptions, FLAIR_EASES, FLAIR_EXPORT_VERSION, type FlairEase, type FlairEaseName, type FlairEffectDocument, type FlairEffectOptions, type FlairExportOptions, type FlairImportOptions, type FlairImportResult, type FlairMotionExport, type FlairSpringEase, type FlairSvgAnimation, type FlairSvgMotion, type FlairVectorEffect, MOTION_ADDITIVE_PROPERTIES, MOTION_BLENDS, MOTION_CAMERA_MS, MOTION_COMMAND_SCHEMA, MOTION_COMMAND_TYPES, MOTION_DEFAULT_DURATIONS, MOTION_DEFAULT_HOLD, MOTION_DIRECTIONS, MOTION_DRAW_EFFECT_ID, MOTION_DRAW_MS_PER_UNIT, MOTION_DRAW_RANGE, MOTION_EASE_IN_OUT, MOTION_EASE_OUT, MOTION_EDIT_OPS, MOTION_ENTER_STYLES, MOTION_EXIT_STYLES, MOTION_IRIS_SHAPES, MOTION_ISSUE_CODES, MOTION_MIN_CHANGE_MS, MOTION_REPEAT_MODES, MOTION_SPLIT_ORIENTATIONS, type MotionCamera, type MotionClipShape, type MotionColorPulseCommand, type MotionCommand, type MotionCommandBase, type MotionCommandTiming, type MotionCommandType, type MotionControl, type MotionDirection, type MotionDrawCommand, type MotionEdit, type MotionEditOp, type MotionEditResult, type MotionEffectCommand, type MotionEnterCommand, type MotionEnterStyle, type MotionExitCommand, type MotionExitStyle, type MotionFadeCommand, type MotionFollowCommand, type MotionFrame, type MotionFrameOptions, type MotionIrisShape, type MotionIssue, type MotionIssueCode, type MotionIssueSeverity, type MotionMatch, type MotionMatchCommand, type MotionMorphCommand, type MotionMoveCommand, type MotionNodeEntry, type MotionPreset, type MotionProperty, type MotionPulseCommand, type MotionRect, type MotionReveal, type MotionRotateCommand, type MotionScaleCommand, type MotionScene, MotionSceneFormatError, type MotionSegment, type MotionShakeCommand, type MotionShot, type MotionShotTiming, type MotionSplitOrientation, type MotionStyleCommand, type MotionSvgOptions, type MotionTeeterCommand, type MotionTimeline, type MotionValue, type MotionWaitCommand, type MotionWaveCommand, type MotionWiggleCommand, activeSegment, applyMotionControlValues, applyMotionEdits, checkMotionScene, commandShapeProblems, compileMotionScene, createAnimationEditorToolProvider, createMotionScene, describeMotionElements, describeMotionShots, fitMotionRect, flairAtLeast, flairCurveFor, flairEaseFor, freshShotId, fromFlairSvgMotion, fromFlairVectorEffect, indexMotionNodes, interpolateMotionValue, isMotionCommand, isMotionShot, matchMotionNodes, motionAddTrackKey, motionClipAttrs, motionCommandDuration, motionCommandRepeat, motionCycleDuration, motionFlairPrimitive, motionFollowRoute, motionFrameAt, motionFrameToSvg, motionIssue, motionIssueKey, motionIssueLine, motionNodeClips, motionNodeOffset, motionPathLength, motionRestValue, motionRevealClip, motionRevealPadding, motionSceneShapeProblems, motionSceneToJson, motionShotAt, motionTrackKey, namedWithSuggestion, parseMotionScene, resolveMotionCamera, segmentProgress, segmentValue, shotShapeProblems, suggestName, toFlairEffectDocument, toFlairSvgMotion, toFlairVectorEffect, trackValue, withMotionLayers, withViewBox };
1769
+ export { ANIMATION_EDITOR_AGENT_INSTRUCTIONS, AnimationEditorController, type AnimationEditorOptions, type AnimationEditorSelection, type AnimationEditorState, type AnimationEditorToolProviderOptions, FLAIR_EASES, FLAIR_EXPORT_VERSION, type FlairEase, type FlairEaseName, type FlairEffectDocument, type FlairEffectOptions, type FlairExportOptions, type FlairImportOptions, type FlairImportResult, type FlairMotionExport, type FlairSpringEase, type FlairSvgAnimation, type FlairSvgMotion, type FlairVectorEffect, MOTION_ADDITIVE_PROPERTIES, MOTION_BLENDS, MOTION_CAMERA_MS, MOTION_COMMAND_SCHEMA, MOTION_COMMAND_TYPES, MOTION_DEFAULT_DURATIONS, MOTION_DEFAULT_HOLD, MOTION_DIRECTIONS, MOTION_DRAW_EFFECT_ID, MOTION_DRAW_MS_PER_UNIT, MOTION_DRAW_RANGE, MOTION_EASE_IN_OUT, MOTION_EASE_OUT, MOTION_EDIT_OPS, MOTION_ENTER_STYLES, MOTION_EXIT_STYLES, MOTION_IRIS_SHAPES, MOTION_ISSUE_CODES, MOTION_MIN_CHANGE_MS, MOTION_REPEAT_MODES, MOTION_SPEED_RANGE, MOTION_SPLIT_ORIENTATIONS, type MotionBeatGrid, type MotionCamera, type MotionClipShape, type MotionColorPulseCommand, type MotionCommand, type MotionCommandBase, type MotionCommandTiming, type MotionCommandType, type MotionControl, type MotionCue, type MotionDirection, type MotionDrawCommand, type MotionEdit, type MotionEditOp, type MotionEditResult, type MotionEffectCommand, type MotionEnterCommand, type MotionEnterStyle, type MotionExitCommand, type MotionExitStyle, type MotionFadeCommand, type MotionFit, type MotionFitOptions, type MotionFollowCommand, type MotionFrame, type MotionFrameOptions, type MotionIrisShape, type MotionIssue, type MotionIssueCode, type MotionIssueSeverity, type MotionMatch, type MotionMatchCommand, type MotionMorphCommand, type MotionMoveCommand, type MotionNarration, type MotionNodeEntry, type MotionPreset, type MotionProperty, type MotionPulseCommand, type MotionRect, type MotionReveal, type MotionRotateCommand, type MotionScaleCommand, type MotionScene, MotionSceneFormatError, type MotionSegment, type MotionShakeCommand, type MotionShot, type MotionShotTiming, type MotionSplitOrientation, type MotionStyleCommand, type MotionSvgOptions, type MotionTeeterCommand, type MotionTimeline, type MotionValue, type MotionWaitCommand, type MotionWaveCommand, type MotionWiggleCommand, activeSegment, applyMotionControlValues, applyMotionEdits, checkMotionScene, commandShapeProblems, compileMotionScene, createAnimationEditorToolProvider, createMotionScene, describeMotionElements, describeMotionShots, fitMotionRect, fitMotionScene, flairAtLeast, flairCurveFor, flairEaseFor, freshShotId, fromFlairSvgMotion, fromFlairVectorEffect, indexMotionNodes, interpolateMotionValue, isMotionCommand, isMotionShot, matchMotionNodes, motionAddTrackKey, motionBeatAt, motionBeatTime, motionClipAttrs, motionCommandDuration, motionCommandRepeat, motionCueTime, motionCycleDuration, motionFlairPrimitive, motionFollowRoute, motionFrameAt, motionFrameToSvg, motionIssue, motionIssueKey, motionIssueLine, motionNodeClips, motionNodeOffset, motionPathLength, motionRestValue, motionRevealClip, motionRevealPadding, motionSceneShapeProblems, motionSceneToJson, motionShotAt, motionShotTimeScale, motionTrackKey, namedWithSuggestion, parseMotionScene, resolveMotionCamera, segmentProgress, segmentValue, shotShapeProblems, suggestName, toFlairEffectDocument, toFlairSvgMotion, toFlairVectorEffect, trackValue, withMotionLayers, withViewBox };