import type { Composition, KeyframeProperty, KeyframeEasing } from "../../composition.js";
export interface KeyframeWrite {
    clipId: string;
    property: KeyframeProperty;
    atSec: number;
    value: number;
    easing?: KeyframeEasing;
}
/**
 * Author (add-or-replace) a keyframe at clip-local time `atSec` on `clipId`'s
 * `property` curve. Idempotent on a `(property, atSec)` collision — the new
 * value replaces the old one, never duplicating (D4). Mints the clip's
 * `keyframes` array on first write.
 *
 * Throws `CompositionOpError{code:4}` when:
 *  - no clip matches `clipId`, or
 *  - the clip is a text clip (text carries no keyframes — D8), or
 *  - `property` is not a real keyframe property, or
 *  - `atSec` is negative / non-finite (keyframe time is clip-local seconds ≥ 0), or
 *  - `atSec` exceeds the clip's own duration (a keyframe must land within the
 *    clip's clip-local span `[0, clipDuration]` — same bound the Studio
 *    Inspector enforces, #40; an absurd `--at 100` on a 5s clip is rejected), or
 *  - `value` is non-finite, or
 *  - `easing` (when given) is not a real easing, or
 *  - `property === "speed"` and `value` is outside [0.1, 4.0] (D10).
 */
export declare function addKeyframe(comp: Composition, p: KeyframeWrite): void;
/**
 * `setKeyframe` — the same idempotent author-or-update as `addKeyframe`. Exposed
 * as a second verb so the CLI surface (`clip keyframe add` / `clip keyframe set`)
 * reads naturally: "add a keyframe here" and "set this property's value at this
 * point" are the same composition mutation (replace-on-collision), driven
 * through one implementation so the two never drift. Same code:4 guards.
 */
export declare function setKeyframe(comp: Composition, p: KeyframeWrite): void;
//# sourceMappingURL=keyframe.d.ts.map