Editing from code Preview
Everything the editor's controls do is also available from code: build your own controls, apply templates, or automate edits. Each call is one undo step, and the views update right away. Calls fail with an error on invalid input, e.g. an unknown clip or a clip that would overlap another.
These APIs are in preview. On the web, typed editing calls aren't available yet.
Clips
- iOS
- Android
- React Native
_ = try editor.apply(edit: .move(clip: clip, track: track, startUs: 3_000_000))
_ = try editor.apply(edit: .trimStart(clip: clip, startUs: 1_000_000))
_ = try editor.apply(edit: .trimEnd(clip: clip, endUs: 6_000_000))
let right = try editor.apply(edit: .split(clip: clip, atUs: 4_000_000))
_ = try editor.apply(edit: .setSpeed(clip: clip, speed: 2))
let copy = try editor.apply(edit: .duplicate(clip: clip))
_ = try editor.apply(edit: .delete(clip: clip, ripple: true))
editor.apply(Edit.Move(clip, track, 3_000_000))
editor.apply(Edit.TrimStart(clip, 1_000_000))
editor.apply(Edit.TrimEnd(clip, 6_000_000))
val right = editor.apply(Edit.Split(clip, 4_000_000))
editor.apply(Edit.SetSpeed(clip, 2.0))
val copy = editor.apply(Edit.Duplicate(clip))
editor.apply(Edit.Delete(clip, true))
editor.move(clip, track, 3_000_000)
editor.trimStart(clip, 1_000_000)
editor.trimEnd(clip, 6_000_000)
const right = editor.split(clip, 4_000_000)
editor.setSpeed(clip, 2)
const copy = editor.duplicate(clip)
editor.remove(clip, true)
- Trim times are timeline times. The SDK tells you how far each end can go (
trimLimits/trimRange), e.g. for your own trim handles. splitreturns the new right-hand clip;duplicateplaces the copy right after.- Deleting with ripple closes the gap.
Properties
Every editable value of a clip is a property: position, scale, rotation, opacity, volume,
crop, masks, text style, each effect's controls and more. Ask the SDK for a clip's
properties instead of hard-coding them: each comes with its path, a label, its group (e.g.
Transform), its type, range, unit, default and whether it can be keyframed. That's everything
needed to build a panel.
- iOS
- Android
- React Native
for p in try editor.properties(clip: clip) { print(p.path, p.label) }
try editor.setProperty(clip: clip, path: "rotation", value: .number(value: 15), atUs: nil)
let scale = try editor.property(clip: clip, path: "scale", atUs: 0)
try editor.resetProperty(clip: clip, path: "rotation")
editor.properties(clip).forEach { println("${it.path} ${it.label}") }
editor.setProperty(clip, "rotation", PropertyValue.Number(15.0), null)
val scale = editor.`property`(clip, "scale", 0)
editor.resetProperty(clip, "rotation")
for (const p of editor.properties(clip)) console.log(p.path, p.label)
editor.setProperty(clip, 'rotation', { number: 15 })
const scale = editor.getProperty(clip, 'scale', 0)
editor.resetProperty(clip, 'rotation')
Values are numbers, booleans, colours or text (for text, fonts and choices). Reading a value takes a time because keyframed values change over time.
Keyframes
Animatable properties change over time through keyframes. Keyframe times are relative to the clip's start.
- iOS
- Android
- React Native
_ = try editor.setKeyframe(clip: clip, path: "scale", atUs: 0, value: 1)
let k = try editor.setKeyframe(clip: clip, path: "scale", atUs: 2_000_000, value: 1.3)
_ = try editor.apply(edit: .setKeyframeEasing(clip: clip, path: "scale", keyframe: k, easing: .easeOut))
editor.setKeyframe(clip, "scale", 0, 1f)
val k = editor.setKeyframe(clip, "scale", 2_000_000, 1.3f)
editor.apply(Edit.SetKeyframeEasing(clip, "scale", k, EasingKind.EaseOut))
editor.setKeyframe(clip, 'scale', 0, 1)
const k = editor.setKeyframe(clip, 'scale', 2_000_000, 1.3)
editor.setKeyframeEasing(clip, 'scale', k, 'ease_out')
Once a property has keyframes, setting it at a time changes the keyframe there.
Effects, transitions and animations
The SDK has catalogs of its built-in effects, transitions and animations. Offer them from the catalog rather than hard-coding ids, which can change between releases.
Each catalog effect has an id, a label, a kind (effect, transition or audio), whether
it's a ready-made bundle with a few controls, and a picker category such as look.
- iOS
- Android
- React Native
let catalog = editor.effectCatalog()
let look = catalog.first { $0.kind == "effect" && $0.bundle }!
let fx = try editor.addEffect(clip: clip, kind: look.id)
let transition = catalog.first { $0.kind == "transition" }!
_ = try editor.apply(edit: .setTransition(clip: clip, kind: transition.id, durationUs: 500_000))
let zoomIn = editor.animationPresets().first { $0.kind == .in }!
_ = try editor.apply(edit: .setAnimation(clip: clip, kind: .in, preset: zoomIn.id))
val catalog = editor.effectCatalog()
val look = catalog.first { it.kind == "effect" && it.bundle }
val fx = editor.addEffect(clip, look.id)
val transition = catalog.first { it.kind == "transition" }
editor.apply(Edit.SetTransition(clip, transition.id, 500_000))
val zoomIn = editor.animationPresets().first { it.kind == AnimationKind.IN }
editor.apply(Edit.SetAnimation(clip, AnimationKind.IN, zoomIn.id))
const catalog = editor.effectCatalog()
const look = catalog.find((e) => e.kind === 'effect' && e.bundle)!
const fx = editor.addEffect(clip, look.id)
const transition = catalog.find((e) => e.kind === 'transition')!
editor.setTransition(clip, 500_000, transition.id)
const zoomIn = editor.animationPresets().find((a) => a.kind === 'in')!
editor.setAnimation(clip, 'in', zoomIn.id)
- An effect's controls appear among the clip's properties.
- A transition goes from a clip into the next one; set none to remove it.
- Clips have In, Out and Loop animations; setting none removes one.
- An effect clip on an effects track changes everything below it while it plays.
Grouping edits
Wrap several calls in a session to make them one undo step, e.g. for a panel with Done and Cancel. Cancelling reverts everything since the session began.
- iOS
- Android
- React Native
editor.beginSession()
do {
try editor.setProperty(clip: clip, path: "x", value: .number(value: 0), atUs: nil)
try editor.setProperty(clip: clip, path: "y", value: .number(value: 0), atUs: nil)
editor.commitSession()
} catch {
editor.cancelSession()
}
editor.beginSession()
try {
editor.setProperty(clip, "x", PropertyValue.Number(0.0), null)
editor.setProperty(clip, "y", PropertyValue.Number(0.0), null)
editor.commitSession()
} catch (e: EditorError) {
editor.cancelSession()
}
editor.beginSession()
try {
editor.setProperty(clip, 'x', { number: 0 })
editor.setProperty(clip, 'y', { number: 0 })
editor.commitSession()
} catch (e) {
editor.cancelSession()
}
Linked clips
Link clips that belong together:
| Link | |
|---|---|
| Media | A video and its audio from the same file: moving, trimming, speed changes and splits stay in sync; deleting one deletes both. |
| Attached | The first clip is the anchor; the others move and are deleted with it, e.g. a title on a shot. Their trims stay independent. |
| Set | A group with no rules of its own, e.g. one caption set. |
Undo and changes
undo() and redo() step through the history, and canUndo() / canRedo() tell you
whether there's anything to step to. A change listener tells you after every change, whether
from your code, the user's gestures, undo, or a selection change. Use it to update your own
buttons and to save.