Hi,
ExtendScript’s ProjectItem has a “nodeID”,
but does UXP’s ClipProjectItem have an ID that clearly identifies one clip from another?
Hi,
ExtendScript’s ProjectItem has a “nodeID”,
but does UXP’s ClipProjectItem have an ID that clearly identifies one clip from another?
UXP project items have IDs; track items do not.
Is there any plans to implement IDs for clip items?
This is useful, if extension keeps track of a clip items. If clip item will be moved to a different track by user, then there is no way to know if it is the same clip it was before, on previous track (besides adding “tagID” to its name, which will be seen by user).
Here’s the workaround that I’m using. It involves attaching a UUID to the VideoClipTrackItem via the Properties API and then finding it as needed. It probably would work on other kinds of objects as well.
/**
* Sets a UUID property on a VideoClipTrackItem using the Properties API
* @param {Object} targetClip - VideoClipTrackItem to attach UUID to
* @param {string} uuid - UUID string to attach to the clip
* @returns {Promise<boolean>} - True if UUID was successfully attached, false otherwise
*/
async function setVideoClipTrackItemUUID(targetClip, uuid) {
try {
// Get the active project for transaction execution
const project = await ppro.Project.getActiveProject();
if (!project) {
return false;
}
const propertyKey = 'com.mycompany.trackitem.uuid';
// STEP 1: Get the Properties object for this specific track item
let properties = null;
try {
properties = await ppro.Properties.getProperties(targetClip);
if (!properties) {
return false;
}
} catch (propertiesError) {
return false;
}
// STEP 2: Create an Action object describing the change
let setValueAction = null;
try {
setValueAction = properties.createSetValueAction(
propertyKey,
uuid,
ppro.Constants.PropertyType.PERSISTENT
);
if (!setValueAction) {
return false;
}
} catch (actionError) {
return false;
}
// STEP 3: Execute the Action inside a transaction using lockedAccess
let success = false;
try {
project.lockedAccess(() => {
try {
success = project.executeTransaction((compoundAction) => {
try {
// Add the property set action to the compound action
compoundAction.addAction(setValueAction);
return true;
} catch (transactionError) {
return false;
}
}, "Set Track Item UUID");
} catch (executeError) {
success = false;
}
});
} catch (lockedAccessError) {
return false;
}
return success;
} catch (error) {
return false;
}
}
/**
* Retrieves the UUID property from a VideoClipTrackItem using the Properties API
* @param {Object} targetClip - VideoClipTrackItem to retrieve UUID from
* @returns {Promise<string|null>} - The UUID string if found, null otherwise
*/
async function getVideoClipTrackItemUUID(targetClip) {
try {
const propertyKey = 'com.mycompany.trackitem.uuid';
// Get the Properties object for this specific track item
let properties = null;
try {
properties = await ppro.Properties.getProperties(targetClip);
if (!properties) {
return null;
}
} catch (propertiesError) {
return null;
}
// Check if the property exists and retrieve it
try {
const hasProperty = await properties.hasValue(propertyKey);
if (!hasProperty) {
return null;
}
// Retrieve the property value
const uuid = await properties.getValue(propertyKey);
return uuid;
} catch (retrievalError) {
return null;
}
} catch (error) {
return null;
}
}
/**
* Finds a VideoClipTrackItem by UUID on a given track
* @param {Object} sequence - The sequence to search in
* @param {number} videoTrackIndex - Zero-based index of the video track to search
* @param {string} uuid - UUID to search for
* @returns {Promise<Object|null>} - VideoClipTrackItem if found, null otherwise
*/
async function findVideoClipTrackItemByUUID(sequence, videoTrackIndex, uuid) {
try {
// Get the video track
const videoTrack = await sequence.getVideoTrack(videoTrackIndex);
if (!videoTrack) {
return null;
}
// Get all clips on the track
const clips = await videoTrack.getTrackItems(1, false); // 1 = clip types only
if (!clips || clips.length === 0) {
return null;
}
// Search through all clips for the one with matching UUID
for (const clip of clips) {
try {
const clipUUID = await getVideoClipTrackItemUUID(clip);
if (clipUUID === uuid) {
return clip;
}
} catch (clipError) {
// Skip clips that can't be read - they might not have UUIDs or be invalid
continue;
}
}
return null;
} catch (error) {
return null;
}
}
Hopefully this helps!
Thank you for your help.
But I don’t think that’s a complete solution.
e.g. After setting the UUID to ClipTrackItem, if you “Add Edit” or “Clone” ClipTrackItem.
This will result in clips with the same UUID existing.
I hope a PremierePro API to get the implement ID in a clip.
Yep, coming in the next pre-release SDK!