Conventions
- Units are the project's: composition pixels from the top left with x right and y down, degrees, percent for scale and opacity, and seconds.
- A time is seconds or a
gp.Time; a place is agp.Place. The receiving operation resolves them on its own clock. …marks an argument with a default. Arguments after*are given by name.- The edit steps and tools that
gp.stepandgp.toolcall are listed in Steps and tools. - The values and number helpers every Python program shares, such as
gp.Vec2andgp.ease, are in Python in Grapple.
Find and read
gp.comp(name: str) → ObjectA composition by name or path: exact, then case-folded.
gp.find(name: str = …, kind: str | None = …) → list[Object]Objects anywhere in the project whose name matches a glob, in authored order.
gp.read(objects: Any, fields: list[str], at: Any = …) → list[dict[str, Any]]Read project.query fields of many objects at one time: one row per object, in order.
gp.selection: SelectionThe person's selection when the run started, as handles.
gp.project: ProjectThe open project.
Write
gp.set(objects: Any, /, **props: Any) → ResultSet properties on many objects in one step. A list gives one value per object, in order.
gp.relate(kind: str, objects: Any, **arguments: Any) → ResultRelate objects with a registered relate kind.
gp.controller(name: str, drives: dict[str, Prop], active_range: tuple[float, float], source: str, params: list[Any] | None = …, entrypoint: str = …) → ObjectDrive several properties from one Python source.
drives maps each output port evaluate(ctx) returns to the property it drives. A whole-vector property needs a vector output; an axis property takes a number. active_range is (start, end) in seconds.
gp.edit(label: str) → EditGroup the calls in a with block under a label. e.receipt reports what the block staged, with committed false; the run commits once at its end.
gp.speculate(label: str = …) → EditStage the calls in a with block, read and render the result inside it, then discard them.
gp.progress(fraction: float, message: str = …) → NoneReport how far the script has got, from 0 to 1, with a short message.
Times and places
gp.frames(n: int) → TimeAn exact frame on the receiving operation's composition clock; frames count from 0.
gp.marker(name: Any, offset: float = …) → MarkerA marker, by name, path or handle, and an offset in seconds after it (negative is before).
gp.source(seconds: float) → TimeSeconds on the footage's source clock.
gp.seconds(time: Any, in_: Any) → floatA time in seconds on the clock of in_, resolved by the project.
gp.playhead: TimeA typed time: a frame, a marker and an offset, the playhead or footage source time. It stays symbolic until the operation that receives it resolves it.
gp.world(x: float, y: float, z: float = …) → PlaceA point in world pixels: x right, y down, z toward the default camera.
gp.point(of: Any, point: Any = …, at: Any = …) → PlaceAn evaluated point of an object: anchor, center, top-left, top, top-right, right, bottom-right, bottom, bottom-left or left; or {"path": fraction} of a Path's arc length.
gp.rect(x: float, y: float, width: float, height: float, in_: str = …, at: Any = …) → PlaceA rectangle in output pixels from the top left.
gp.mask_region(mask: Any, at: Any = …) → PlaceThe region a mask covers.
See
gp.render(of: Any, /, *, at: Any = …, times: list[Any] | None = …, range: tuple[Any, Any] | None = …, as_: str = …, size: Any = …, crop: Any = …, columns: int | None = …, camera: Any = …, only: list[Any] | None = …, alpha: bool | None = …, overlay: list[Overlay] | None = …, compare: dict[str, Any] | None = …) → AnyRender synchronously from the run's staged project.
at renders one frame (or a list of frames); times=[...] renders a labelled contact sheet; as_="audio" with range=(start, end) renders the mixed audio and returns its artifact and coverage. size scales the composition's output size (a number) or gives (width, height); crop is (x, y, width, height) in output pixels. camera, only and alpha choose the view; overlay draws gp.overlay(...) items; compare is {"against": ..., "as": "split" or "difference"}.
gp.overlay(of: Any, show: str, **arguments: Any) → OverlayAn overlay for gp.render: what to show for which object, from the render contract's overlays.
Learn
gp.search(text: str) → NonePrint every class, method, adapter, step, tool and measure kind matching text.
gp.examples(topic: str | None = …) → NonePrint short runnable examples: gp.examples() lists the topics, gp.examples("keys") shows one.
gp.api() → NonePrint the type stub of this run's API.
gp.objects.Object
Every handle: an identity in the project. Facts are read-only attributes; any other attribute is a property.
A project object. A handle is an identity; every read goes to the project.
Facts: name, path, kind, id, start, end, duration, parent, children, layer, comp, z_order, driven_by, used_by. Properties are attributes: obj.opacity, obj.position.x; obj.prop(id) reaches any registered id.
obj.idThe object's id; an owned item's id is its owner, kind and key.
obj.nameThe object's name.
obj.pathThe identity path of names from the composition down.
obj.kindThe object's kind.
obj.startStart in seconds on the object's own composition clock.
obj.endEnd in seconds on the object's own composition clock.
obj.z_orderStacking order; higher is in front.
obj.driven_byObjects that drive this one.
obj.used_byObjects that use this one.
obj.durationend - start, in seconds.
obj.createdThe native result of the call that created this handle's object, when this run created it.
obj.parentThe object that contains this one, or None at the top.
obj.childrenThe objects directly inside this one, in authored order.
obj.layerThe layer this object is on, or None.
obj.compThe composition this object is in, or None.
obj.relationsThe relations this object owns, as handles.
obj.find(name: str = …, kind: str | None = …) → list[Object]Objects inside this one whose name matches a glob (* and ?), in authored order.
obj.presented_transform(at: Any) → dict[str, Any]Position, scale, rotation and opacity after parents and layout, at a time.
obj.bounds(at: Any) → AnyEvaluated bounds at a time.
obj.screen_bounds(at: Any) → AnyBounds on the rendered frame at a time, in output pixels.
obj.in_frame(at: Any) → AnyWhether the object shows in the rendered frame at a time.
obj.props(at: Any = …) → PropTableThis object's properties with units, choices, whether each is settable and animated.
obj.prop(name: str) → PropA property by any registered spelling, including its full id.
gp.Prop
A property of one object, reached as an attribute: title.opacity, title.position.x.
A property of one object.
The name is the registry's: the property id, its label or the last part of its id, without case, spaces or underscores; .x, .y and .z name one axis. Values use the property's units: pixels from the top left, degrees, percent, seconds.
prop.valueThe authored value, before keys, drivers and programs are sampled.
prop.at(time: Any) → AnyThe sampled value at a time on the object's own clock: keys, drivers and programs.
prop.keyframesEvery stored key, with every field the writer takes.
prop.animatedWhether keys, a driver or a program animate this property.
prop.addressThe bound property address: ownerNodeId, propertyId and componentIndex for one axis.
prop.set(value: Any) → ResultSet the static value. On a keyed property this writes a key at the playhead.
prop.keys(keys: list[Any], mode: str = …) → ResultWrite keys: (time, value) or (time, value, ease) tuples, or gp.Key records.
A tuple's time is on the object's composition clock; a gp.marker time anchors the key to the marker. ease is how the value leaves that key: hold, linear, ease_in, ease_out, ease_in_out, smooth_through or overshoot. mode replace sets the whole schedule; merge adds keys and replaces keys at the same times.
prop.key(time: Any, value: Any, ease: str | None = …) → ResultAdd or replace one key.
prop.clear() → ResultRemove every key.
prop.shift(seconds: float) → ResultMove every key later by seconds on the property's key clock; negative is earlier.
prop.drive(expression: str | None) → NoneDrive the property every frame with a Python expression, or remove the driver with None.
The expression can use time (composition seconds), value (the property's own keyed or static value), gp and math.
prop.xThe x axis.
prop.yThe y axis.
prop.zThe z axis.
gp.Key
One stored key, as prop.keyframes returns it.
One stored key with every field the writer takes.
keyframe_id; time on the schedule's clock (composition or source) and its time_anchor (a marker and an offset, or None); value, or endpoint when the key stands for its channel's loop start; interpolation, how the value leaves this key; dimensions (joined or separated) and component_index for one axis; hold_until and hold_until_anchor for a source-time hold; incoming_tangent and outgoing_tangent. prop.keys(prop.keyframes) writes the same animation back. Build new keys as (time, value, ease) tuples; change a stored key with replace().
key.replace(**changes: Any) → KeyA copy of this key with the given fields changed.
gp.Image
What gp.render returns for frames and contact sheets.
The images of one render: its frames, or its contact sheet. show(caption) returns them to you with this run's result. result is the render's native result: resolved times, extents, view and problems.
image.problemsWhat the render reports about these images.
image.show(caption: str) → ImageReturn these images to you with the run's result, under a caption.
gp.Result
What a step, a tool or an adapter returns.
A step's or tool's native result. id is the object the call created, when it creates one.
result.idresult.objectThe created object as a handle.
gp.Error
The exception every failed operation raises.
A Grapple operation failed.
code names the failure; message says what happened and what to do next; path is the argument that failed; got and expected are the supplied and accepted values; candidates lists the objects a name could mean, closest first; next suggests a tool call that can help.
gp.Time
A typed time. gp.frames, gp.marker, gp.source and gp.playhead make them.
A typed time: a frame, a marker and an offset, the playhead or footage source time. It stays symbolic until the operation that receives it resolves it.
gp.Place
A typed place or region. gp.world, gp.point, gp.rect and gp.mask_region make them.
A place or region, resolved by the operation that receives it.
gp.objects
One handle class for each kind of object. Each has everything gp.objects.Object has, and the kinds below add their own methods.
gp.objects.Asset
A project object of kind asset.
gp.objects.Camera
A project object of kind camera.
gp.objects.Clip
A project object of kind clip.
clip.rename(name: str) → NoneRename this clip.
gp.objects.Collection
A project object of kind collection.
gp.objects.Comp
A project object of kind composition.
comp.clipsEvery clip inside this object, in authored order.
comp.layersEvery layer inside this object, in authored order.
comp.add_layer(name: str, kind: str) → ObjectCreate a layer on top: kind is visual, audio or adjustment.
comp.add_camera(name: str, focal_length: float | None = …, **fields: Any) → ObjectCreate a camera. focal_length is millimetres; other fields use the step's registered names.
gp.objects.Effect
A project object of kind effect.
gp.objects.Layer
A project object of kind layer.
layer.clipsEvery clip inside this object, in authored order.
layer.add_text(text: str, start: Any, end: Any, font: str | None = …, size: float | None = …) → ObjectCreate a text clip from start to end. font is an exact font family; size is pixels. Without them the text is Inter at 48 px, white, centred in a box 80% wide and 25% high. The result's layout (clip.created["layout"]) reports overflow. A new text clip has no name; give it one with rename().
layer.add_media(asset: Any, *, start: Any, source_range: tuple[Any, Any], duration: float | None = …) → ObjectPlace an asset's picture on this layer: source_range is (start, end) in source seconds. With duration, the clip spans start to start + duration. Place the audio component with gp.step("timeline.place_media", ...).
gp.objects.Light
A project object of kind light.
gp.objects.Marker
A project object of kind marker.
gp.objects.Member
A project object of kind member.
gp.objects.Relation
A project object of kind relation.
gp.measure
Measurements of evaluated motion, rendered pixels, output audio or analysis results. Each kind takes the keywords shown, inside one call: gp.measure.colour(of=main, at=2.0, region=…).
gp.measure.bounds(*, at = …, of = …, view = …)Visible pixel bounds of each requested object inside the output frame, with alpha strictly above the visibility threshold. This is rendered support, not geometric query bounds.
gp.measure.colour(*, at = …, of = …, region = …, view = …)Region- and alpha-weighted straight working-linear RGBA and luminance: mean, minimum, maximum and weighted empirical 5/50/95 percent quantiles. Display pixels and overlays do not contribute.
gp.measure.contrast(*, at = …, of = …, regions = …, view = …)Relative-luminance contrast and signed delta L* from the first region to the second. Give two regions for their alpha- and region-weighted mean luminances. Omit regions and give one placed visual object in of for median luminances of its covered pixels and the surrounding ring, in the full composition. The ring lies outside object coverage above 1/255 alpha, within the greater of 8 output pixels and 10% of its visible bounding-box short side, using Euclidean distance on the rendered mask. An empty object or ring reports a problem. Regions retain their own mask sampling moments.
gp.measure.cuts(*, of = …, range = …, view = …)Cut times over a half-open range at the composition's frame cadence, through the temporal cut detector. The first sample is the baseline; each later time names the right frame of its detected interval. Detector scores are not probabilities. Overlays do not contribute.
gp.measure.difference(*, against = …, at = …, of = …, view = …)Matching resolution and working profile are required. Mean and maximum absolute premultiplied working-linear RGBA difference and the fraction of pixels whose largest channel difference exceeds the changed-pixel threshold; no optical alignment.
gp.measure.flicker(*, of = …, range = …, region = …, view = …)Population standard deviation of signed frame-to-frame changes in region- and alpha-weighted mean working-linear luma, and the maximum absolute change. Samples follow the composition's frame cadence over the half-open range; at least two frames are required. A region without at follows each frame; region.at fixes its coverage. Overlays do not contribute.
gp.measure.landing(*, near = …, of = …, range = …, view = …)Observe each clip's evaluated screen-space approach over a half-open range. The destination is the first key after the approach whose following interval holds or stays below 1 px/frame until the next key; without a rest inside the range, use its last delivered frame. Landing is the first run of at least two frames below 1 px/frame at that rest, measured with motion's one-frame difference, one-sided at clip or delivered-range edges. Overshoot is the furthest excursion past that destination along the start-to-destination direction, in pixels and as a percentage of the approach distance. near adds the landing-time offset. Missing placement, an unsettled interval or a zero approach distance reports a named problem.
gp.measure.loop(*, of = …, thresholds = …, view = …)Measure each footage, layer and periodic driver's seam, with numerical pass or fail and a note to look at it. Of is one composition; T is its duration in whole frames N and L = (N - 1) / fps its last delivered frame. Each footage and layer item, isolated, compares frame L with frame 0 over the pixels either covers: the excess is the seam's mean premultiplied working-linear difference beyond the larger of its neighbouring frame differences (L - 1 to L, and 0 to 1); fewer than three frames leaves continuation unavailable. Each Wave, Spring and Audio level compares its own state at T with 0: a Spring's position and velocity, a Wave's phase in cycles (whole cycles close the loop) and an Audio level's smoothed power. The output mix's continuation is fitted per channel by a two-sample linear predictor on each side of the seam; the residual is the forecast error across the seam beyond each side's own. Each driver component gives its change from 0 to T and its residual. An item the renderer withholds from a frame is unavailable, with the reason. Rows are footage, then layers, then drivers, then sound. Missing evidence is unavailable, never a pass.
gp.measure.loudness(*, of = …, range = …)Measure the composition's native stereo output mix over range: EBU R128 integrated LUFS, maximum three-second short-term LUFS, and ITU-R BS.1770-4 Annex 2 FIR true peak in dBTP. Both absolute and relative gates apply. Silence and insufficient duration return null with a reason. Also each output channel's RMS and sample peak in dBFS, the peak and the number of samples over full scale before the delivery clamp, the intervals where a playing clip's source has no PCM, and how many seconds are exactly silent or quiet (stereo RMS below -80 dBFS over a 20 ms window).
gp.measure.motion(*, at = …, of = …, view = …)Screen-space velocity of the whole-object transform position and evaluated Euler angular velocity of each placed visual clip. A central difference spans one composition frame interval; at a clip edge it uses a one-sided difference inside the clip's presence. Position projects through the same view as render; angular components retain the evaluated degrees about x, y and z. An absent, failed or unprojectable placement reports a named problem.
gp.measure.overlap(*, at = …, of = …, view = …)Give two placed visual objects in of, ordered A then B. Return the fraction of A's visible output pixels covered by B, and their area in square output pixels. The front object is determined by the view's render order; B covers none of A when it is drawn behind A. A is visible above 1/255 alpha; B covers a pixel at alpha at least 0.5. Mask holes and fractional coverage come from the render, not geometric boxes. Empty A reports a problem.
gp.measure.plane_fit(*, of = …, plane = …)How well each camera solve plane fits its measured cloud points: the support count, the points' RMS distance from the plane in solve depth units (one unit is the solve's median scene depth) and as a share of their depth, their spread across the plane, the fit's state and the camera axis its frame follows. Read from each solve's stored result; nothing is solved again.
gp.measure.reprojection(*, of = …)Reprojection error of camera solves, read from each solve's stored result: the inlier RMS and p95 over its measured features in source pixels, the inlier share, weak and unposed frames, and which lens and depth values were determined. Samples give each frame's own error. Nothing is solved again.
gp.measure.signal(*, of = …, power = …, property = …, range = …, step = …)Sample one object's signal over range, in the clock of the composition that holds it or of the root composition that holds its outermost use. With property, the property's value as the runtime evaluates it for that occurrence, drivers and instance inputs included, every step seconds, in the units set uses. With power, an audio clip's power in dBFS over completed 20 ms windows of a tap, band-filtered and smoothed as an Audio level on that clock hears it: on a seamless loop its windows start one period before 0, and a window whose smoothing remembers a window with no source PCM is unavailable. Each sample is the window ending at its time, and silence is null with a reason. The result shows the first samples; every sample is in its artifact. Give property or power.
gp.presets
Readable motion presets. Each writes ordinary keys that merge into the property's schedule.
gp.presets.ease(prop: Any, *, at: Any, to: Any = …, from_: Any = …, duration: float = …, amount: Real | None = …)Ease from one value to another, landing at the end. Amount 0 is linear, 100 is a full ease.
prop is a property such as title.scale. at is the beat in seconds of the object's composition clock, or gp.marker(name, offset=...), which anchors every key to the marker. to defaults to the property's authored value, from_ to zero and duration to one second. The keys merge into the property's schedule.
gp.presets.overshoot(prop: Any, *, at: Any, to: Any = …, from_: Any = …, duration: float = …, amount: Real | None = …)Pass the target by amount percent at the beat, then settle.
prop is a property such as title.scale. at is the beat in seconds of the object's composition clock, or gp.marker(name, offset=...), which anchors every key to the marker. to defaults to the property's authored value, from_ to zero and duration to one second. The keys merge into the property's schedule.
gp.presets.bounce(prop: Any, *, at: Any, to: Any = …, from_: Any = …, duration: float = …, amount: Real | None = …)Arrive at the beat and bounce back twice, the second bounce a quarter of the first.
prop is a property such as title.scale. at is the beat in seconds of the object's composition clock, or gp.marker(name, offset=...), which anchors every key to the marker. to defaults to the property's authored value, from_ to zero and duration to one second. The keys merge into the property's schedule.
gp.presets.anticipate(prop: Any, *, at: Any, to: Any = …, from_: Any = …, duration: float = …, amount: Real | None = …)Pull back by amount percent first, then move to the target at the beat.
prop is a property such as title.scale. at is the beat in seconds of the object's composition clock, or gp.marker(name, offset=...), which anchors every key to the marker. to defaults to the property's authored value, from_ to zero and duration to one second. The keys merge into the property's schedule.
gp.presets.pop(prop: Any, *, at: Any, to: Any = …, from_: Any = …, duration: float = …, amount: Real | None = …)Pop to amount percent at the beat, then settle with two smaller swings.
prop is a property such as title.scale. at is the beat in seconds of the object's composition clock, or gp.marker(name, offset=...), which anchors every key to the marker. to defaults to the property's authored value, from_ to zero and duration to one second. The keys merge into the property's schedule.
gp.presets.hold(prop: Any, *, at: Any, to: Any = …, from_: Any = …, duration: float = …, amount: Real | None = …)Hold the first value, then step to the target at the beat. Amount has no effect.
prop is a property such as title.scale. at is the beat in seconds of the object's composition clock, or gp.marker(name, offset=...), which anchors every key to the marker. to defaults to the property's authored value, from_ to zero and duration to one second. The keys merge into the property's schedule.