Split Selected Clips at Specified Marker Track
Title
Split Selected Clips at Specified Marker Track
What do you expect to happen when you run the script/macro?
Hello! Script works, but splits selected clips based on all marker rulers in Pro Tools. Is it possible to use this script so that it splits clips based off a specified marker timeline? Marker 1, Marker 2, etc? Thank you!
Are you seeing an error?
What happens when you run this script?
Clips are separated at all markers in session instead of a secified marker lane
How were you running this script?
I used a keyboard shortcut within the target app
How important is this issue to you?
4
Details
{ "inputExpected": "Hello! Script works, but splits selected clips based on all marker rulers in Pro Tools. Is it possible to use this script so that it splits clips based off a specified marker timeline? Marker 1, Marker 2, etc? Thank you!", "inputIsError": false, "inputWhatHappens": "Clips are separated at all markers in session instead of a secified marker lane", "inputHowRun": { "key": "-Mpfwh4RkPLb2LPwjePT", "title": "I used a keyboard shortcut within the target app" }, "inputImportance": 4, "inputTitle": "Split Selected Clips at Specified Marker Track" }
Source
//Store original selection
let originalSelection = sf.ui.proTools.selectionGet();
let originalSelectionSamples = sf.ui.proTools.selectionGetInSamples();
//Ensure the user has actually made a selection within which we should operate
if (originalSelectionSamples.selectionLength === 0)
throw `Please make a selection before running this script`;
try {
//Collapse selection to the left hand side
sf.ui.proTools.selectionSet({
selectionStart: originalSelection.selectionStart,
selectionEnd: originalSelection.selectionStart,
});
//Perform an endless loop
while (true) {
//Go to the next memory location
let goRes = sf.ui.proTools.memoryLocationsGotoDelta({
delta: 1,
onError: 'Continue',
});
//If we didn't find a next memory location, just abort the loop
if (!goRes.success)
break;
//Retrieve the selection at this point
let newSelection = sf.ui.proTools.selectionGet();
//If we're now further to the right than the original selection,
//break the loop
if (newSelection.selectionStart > originalSelection.selectionEnd)
break;
//Otherwise, click Separate Clip At Selection, and continue the loop
//also - if for some reason we're in between clips we're allowing the menu click to fail silently
sf.ui.proTools.menuClick({
menuPath: ["Edit", "Separate Clip", "At Selection"],
onError: 'Continue',
});
//Continue the loop
}
} finally {
//Finally, regardless of any error occurring in the previous code,
//restore the original selection
sf.ui.proTools.selectionSetInSamples({
selectionStart: originalSelectionSamples.selectionStart,
selectionEnd: originalSelectionSamples.selectionEnd,
});
}
Links
User UID: BAHRTrNpErQGSMCXb1Gj6AHsSU13
Feedback Key: sffeedback:BAHRTrNpErQGSMCXb1Gj6AHsSU13:-OPHIc8gTZsGACFJm22x
Feedback ZIP: S+aW2eb8llXsIbzoF7bgxktAXBXOyFNbkS1lhAdZuqqAT2430ot3Z4qNvdQxqUx8QZZH/pxfQbBTFXtKOZXxx9YXnP0zU++NjRhcJveSiyUwKY2R+BTBcTgZhVp+L7cNChy7VS++Nw7vVzbrIFwC9REvmnSfM+AHzubsyWGC3XKVvAkYU+bP5CH9D1zPyfVd44rllcVqkUVEmlj0nPUCayMYm9eQav2AiCGo3Jyenq9Dh2uTLx9r2RCOKDm6g7Qcq521f8+VAmTEgx2Z5e4Q17Nj1JJn6+xnzJqFUh775O/mY0oGkFrLMA6yzAWtbdmRcG9BKGYiAhNy7/yv8C7sdw==
- Chad Wahlbrink @Chad2025-05-03 00:09:38.086Z
Hi, @Curtis_Macdonald,
Since you are asking about a specific script, I've moved this post to the “Macro and Script Help” section of the forum.
The
sf.ui.proTools.memoryLocationsGotoDelta()
does not have a property for marker track name, so we have to use a different approach. Typically, you'd use something likesf.app.proTools.memoryLocations.invalidate().allItems.map(memLocs => memLocs.trackName)
- however, this seems to currently throw some "null" values for the global marker tracks, which is not very helpful.Therefore, I'm approaching this differently by utilizing
sf.app.proTools.getSessionInfoAsText()
. This SDK call can retrieve the session info text you typically get from File > Export > Session Info as Text. This text can include a marker list, including the marker track names. Therefore, I'm filtering that text with some regex (thanks to ChatGPT 😊). From there, we have all the necessary information to make it happen!Here's the script - I have refactored it a bit to use more SDK calls than UI automation. Set the name of your desired Marker Lane at the top of the script (line 3 below):
// Set the Marker Track Name Here (Markers, Markers 2, Markers 3, Another Track Name...) let markerTrackName = 'MIX'; //////////////////// if (!sf.ui.proTools.isRunning) throw `Pro Tools is not running`; sf.ui.proTools.appActivateMainWindow(); sf.ui.proTools.mainWindow.invalidate(); // Get the Session Info as Text - This is how we are getting the markers list with Marker Tracks let sessionInfoResult = sf.app.proTools.getSessionInfoAsText({ includeMarkers: true, includeClipList: false, includePluginList: false, includeTrackEdls: false, includeUserTimestamps: false, includeFileList: false, }) // Use Regex to Filter for Lines that Start with a Number const markerLines = sessionInfoResult.sessionInfo .split('\n') .filter(line => /^\d+\s+/.test(line)); // lines that start with a number // Further Split These Lines by their "headers" of Number, Location, Time Reference, Units, Name, and Marker Track Name // Store this as an array of Marker Objects const markers = markerLines.map(line => { const parts = line.split('\t').map(p => p.trim()).filter(Boolean); return { number: parseInt(parts[0]), location: parts[1], timeReference: parts[2], units: parts[3], name: parts[4], trackName: parts[5] }; }); //Store original selection using SDK let originalSelectionSamples = sf.app.proTools.getTimelineSelection({ timeScale: "Samples" }) //Ensure the user has actually made a selection within which we should operate if (originalSelectionSamples.inTime === originalSelectionSamples.outTime) throw `Please make a selection before running this script`; try { // Go to Selection Start sf.app.proTools.setTimelineSelection({ inTime: originalSelectionSamples.inTime, outTime: originalSelectionSamples.inTime }) // Filter Markers for the Marker Track Name, // the location is after or equal to the in time // the location is before or equal to the out time let markersOnNamedTrack = markers.filter( marker => (marker.trackName === markerTrackName && Number(marker.location) >= Number(originalSelectionSamples.inTime) && Number(marker.location) <= Number(originalSelectionSamples.outTime) ) ); // For each Marker On the Named Marker Track and Within our Selection, Split at the Marker markersOnNamedTrack.forEach((marker) => { // Go to the Markers Location sf.app.proTools.setTimelineSelection({ inTime: marker.location }); // Seperate the Clip sf.ui.proTools.menuClick({ menuPath: ["Edit", "Separate Clip", "At Selection"], onError: 'Continue', }); }) } finally { //Finally, regardless of any error occurring in the previous code, //restore the original selection sf.app.proTools.setTimelineSelection({ inTime: originalSelectionSamples.inTime, outTime: originalSelectionSamples.outTime, }); }
- OOwen Granich-Young @Owen_Granich_Young
YOINK!!!!! Huge Chad, huge.