Hi Adobe team,
I’m evaluating the Premiere Pro UXP DOM for timeline automation. In current Beta builds I can access require(‘premierepro’), Project.getActiveProject(), the active Sequence, and SequenceEditor actions like createRemoveItemsAction. However, I can’t find a way to programmatically split/razor track items at arbitrary times (or remove by an arbitrary time range).
Could you please clarify:
Is a programmatic split/razor API planned (e.g., a createSplitTrackItemAction, edit-range action, or equivalent)? If yes, what’s the ETA (target Beta build) and the plan for stable (GA) availability?
Is there a recommended workaround today from UXP DOM (e.g., time-selection + ripple delete, or callable menu commands)?
Any best practices for capability detection across Beta builds (reliable probes for require(‘premierepro’), SequenceEditor.getEditor, and method presence)?
Environment: Premiere Pro Beta 25.6.0.046 (Aug 29, 2025), OS: Windows.
There is no ‘razor tool’ API planned for the 1.0 release, which is prioritizing functional parity with the CEP+ExtendScript APIs (not including QE DOM).
We know there’s interest, and…As a rule, Adobe won’t speculate about dates for releases which haven’t been publicly announced.
Cathy’s release notes are the best source of info on pre-release SDK improvements.
Bumping this thread with a workaround since I needed one for myself. It’s not ideal but works for me. The basic idea is instead of splitting the VideoClipTrackItem, you overwrite it with two halves of the base ClipProjectItem where you set the in/out points on it before inserting. To the end user it looks like a split. Unfortunately the undo isn’t clean.
const ppro = require("premierepro");
/**
* Split a clip at a given sequence time (seconds).
* Workaround: removes the original and overwrites two halves back in place.
*
* @param {string} clipGuid - The GUID of the clip to split
* @param {number} splitTimeSeconds - Sequence time to split at (seconds)
* @param {number} videoTrackIndex - Zero-based video track index
* @param {number} audioTrackIndex - Zero-based audio track index
*/
async function splitClipAtTime(clipGuid, splitTimeSeconds, videoTrackIndex, audioTrackIndex) {
const project = await ppro.Project.getActiveProject();
const sequence = await project.getActiveSequence();
const sequenceEditor = await ppro.SequenceEditor.createForSequence(sequence);
// Find the target clip by GUID on the video track
const videoTracks = await sequence.getVideoTracks();
const track = videoTracks[videoTrackIndex];
const clips = await track.getClips();
let targetClip = null;
for (const clip of clips) {
const guid = await clip.getGuid();
if (guid === clipGuid) {
targetClip = clip;
break;
}
}
if (!targetClip) throw new Error(`Clip ${clipGuid} not found on V${videoTrackIndex + 1}`);
// Read original clip properties (tick-precise)
const origStartTT = await targetClip.getStartTime();
const origEndTT = await targetClip.getEndTime();
const origInTT = await targetClip.getInPoint(); // source in
const origOutTT = await targetClip.getOutPoint(); // source out
// Compute source-relative split point, aligned to nearest frame
const splitTimeTT = ppro.TickTime.createWithSeconds(splitTimeSeconds);
const sourceSplitTT = origInTT.add(splitTimeTT.subtract(origStartTT));
const ticksPerFrame = Number(await sequence.getTimebase());
const frameRate = ppro.FrameRate.createWithValue(
ppro.TickTime.createWithSeconds(1).ticksNumber / ticksPerFrame
);
const sourceSplitAligned = sourceSplitTT.alignToNearestFrame(frameRate);
const splitTicks = sourceSplitAligned.ticks;
// Recompute the sequence-level split time from the aligned source split
const seqSplitTT = origStartTT.add(sourceSplitAligned.subtract(origInTT));
// Get source ClipProjectItem for overwrite operations
const sourceProjectItem = await targetClip.getProjectItem();
const clipPI = ppro.ClipProjectItem.cast(sourceProjectItem);
let success = false;
ppro.TrackItemSelection.createEmptySelection((selection) => {
selection.addItem(targetClip);
project.lockedAccess(() => {
// Transaction 1: Remove original clip + set source in/out for left half
project.executeTransaction((compoundAction) => {
compoundAction.addAction(
sequenceEditor.createRemoveItemsAction(selection, false, ppro.Constants.MediaType.ANY)
);
compoundAction.addAction(clipPI.createClearInOutPointsAction());
compoundAction.addAction(clipPI.createSetInOutPointsAction(
ppro.TickTime.createWithTicks(origInTT.ticks),
ppro.TickTime.createWithTicks(splitTicks)
));
return true;
}, "Split Clip - Remove Original");
// Transaction 2: Overwrite left half + set source in/out for right half
project.executeTransaction((compoundAction) => {
compoundAction.addAction(sequenceEditor.createOverwriteItemAction(
sourceProjectItem,
ppro.TickTime.createWithTicks(origStartTT.ticks),
videoTrackIndex, audioTrackIndex
));
compoundAction.addAction(clipPI.createClearInOutPointsAction());
compoundAction.addAction(clipPI.createSetInOutPointsAction(
ppro.TickTime.createWithTicks(splitTicks),
ppro.TickTime.createWithTicks(origOutTT.ticks)
));
return true;
}, "Split Clip - Insert Left Half");
// Transaction 3: Overwrite right half + clear source in/out
success = project.executeTransaction((compoundAction) => {
compoundAction.addAction(sequenceEditor.createOverwriteItemAction(
sourceProjectItem,
ppro.TickTime.createWithTicks(seqSplitTT.ticks),
videoTrackIndex, audioTrackIndex
));
compoundAction.addAction(clipPI.createClearInOutPointsAction());
return true;
}, "Split Clip - Insert Right Half");
});
});
if (!success) throw new Error("Split transaction failed");
return {
splitTime: seqSplitTT.seconds,
leftHalf: { startTime: origStartTT.seconds, endTime: seqSplitTT.seconds },
rightHalf: { startTime: seqSplitTT.seconds, endTime: origEndTT.seconds },
};
}