Hi all. First off, I'm new here and not experienced at all in writing code.
I'm wanting to put together a macro that will split selected clips at markers then rename the clips to the right of the markers to match marker name. Any help and/or direction in this would be greatly appreciated. Thanks!
Will LeMaster
- Christian Scheuer @chrscheuer2022-05-03 12:34:25.102Z
Hi Will,
For the first part, there's an existing script in the official Pro Tools integration under Memory Locations that should do that:
The script is open source, click View Source to see how it works under the hood :)
Christian Scheuer @chrscheuer2022-05-03 12:34:59.640Z
The 2nd part of your question is likely to be quite a lot more advanced and would require a pretty deep understanding of scripting.
- WWill LeMaster @Will_LeMaster
Hi Christian, thanks for the response.
Yes, I know and have used the 'Split Selected Clip(s) at Markers' macro. I included that to give some context to the overall action I am wanting to accomplish. I also figured that the naming of the clip(s) to the right of the adjacent marker(s) would be fairly advanced. Is this something that is possible to accomplish in Pro Tools using SoundFlow?Christian Scheuer @chrscheuer2022-05-04 11:00:24.390Z
Yes it should be possible :) I don't have time to work on it myself right now, but yes, it should be achievable through SF.
- WWill LeMaster @Will_LeMaster
Well that's promising. :)
I'm going to attend the SF weekly webinar w/ Kitch today, hopefully I'll be able to tap into some resources there. :)- WWill LeMaster @Will_LeMaster
Just finished up weekly webinar, had a great time. Kitch dove into the coding to rename the clips with the marker names. Huge Thanks to you, @Kitch!
Kitch Membery @Kitch2022-05-04 21:46:06.616Z2022-05-05 02:18:13.056Z
Hi Will,
Here is that script we worked on in the webinar. :-)
function renameClip(name) { sf.ui.proTools.menuClick({ menuPath: ['Clip', 'Rename...'] }); const renameWindow = sf.ui.proTools.windows.whoseTitle.is('Name').first.elementWaitFor({ waitType: "Appear" }).element; const nameClipOnlyButton = renameWindow.groups.first.radioButtons.first; if (nameClipOnlyButton.exists) { renameWindow.groups.first.radioButtons.first.checkboxSet({ targetValue: "Enable" }); } renameWindow.groups.first.textFields.first.elementSetTextFieldWithAreaValue({ value: name }); renameWindow.buttons.whoseTitle.is('OK').first.elementClick(); renameWindow.elementWaitFor({ waitType: "Disappear" }); } function main() { sf.ui.proTools.appActivateMainWindow(); sf.ui.proTools.mainWindow.invalidate(); const isMemoryLoactionWindowOpen = sf.ui.proTools.getMenuItem('Window', 'Memory Locations').isMenuChecked; if (!isMemoryLoactionWindowOpen) { sf.ui.proTools.memoryLocationsShowWindow(); } sf.ui.proTools.mainCounterDoWithValue({ targetValue: "Samples", action: () => { const memoryLocations = sf.proTools.memoryLocationsFetch().collection["List"]; sf.ui.proTools.clipDoForEachSelectedClip({ action: function () { const mainCounterVal = sf.ui.proTools.selectionGet().mainCounter; let memoryLocation = memoryLocations.filter(x => x.mainCounterValue && x.mainCounterValue === mainCounterVal)[0]; if (memoryLocation !== undefined) { renameClip(memoryLocation.name); } }, }); }, }); if (!isMemoryLoactionWindowOpen) { sf.ui.proTools.memoryLocationsWindow.windowClose(); } } main();
Updated to ensure the Memory Locations window is open.
- WWill LeMaster @Will_LeMaster
Got it, thanks @Kitch . I tried it several times using multiple PT sessions and different clips split to markers. Each attempt failed, with the same error message. I pasted the error message from the log, below:
04.05.2022 18:13:32.18 [Backend]: #StreamDeck: KeyDown (8,2) -> Clip Rename to Marker
04.05.2022 18:13:32.18 [Backend]: >> Command: Clip Rename to Marker [user:default:cl2s9t0cu0002jn106qa9tpo4]
Checking for running apps with bundle 'com.avid.ProTools'04.05.2022 18:13:32.19 [Backend]: NSArray.ArrayFromHandle count = 1
04.05.2022 18:13:32.26 [Backend]: Mouse current pos is: (1334, 270)
Clicking with mouse here: (12, 60)04.05.2022 18:13:32.26 [Backend]: #App: Activate "com.avid.ProTools" -> Show Pro Tools Deck [cl2e1lny10001pn10mg6nq21n]
#App: Activate "com.avid.ProTools" -> My Pro Tools Deck [cl2js0k5m00004g10bvmqtk5w]04.05.2022 18:13:32.27 [Backend]: Moving mouse back to: (1334, 270)
04.05.2022 18:13:32.27 [Backend]: Position is now: (1334, 270)
04.05.2022 18:13:32.75 [Backend]: Marker count: 39
04.05.2022 18:13:33.24 [Backend]: Mouse current pos is: (1334, 270)
Clicking with mouse here: (773, 86)04.05.2022 18:13:33.25 [Backend]: Moving back...
04.05.2022 18:13:33.26 [Backend]: Position is now: (1334, 270)
04.05.2022 18:13:33.52 [Backend]: Succesfully set selection to: MainCounter: Sel Start: Sel End: Sel Length: 0
04.05.2022 18:13:33.57 [Backend]: Pressing key: kVK_ANSI_Quote. Flags: kCGEventFlagMaskShift
04.05.2022 18:13:36.94 [Backend]: Logging error in action (01) WaitForElementAction: Element was not found or removed after waiting 2000 ms
04.05.2022 18:13:36.94 [Backend]: Error running Js Callback: 'WaitForElementAction' ( line 4)
04.05.2022 18:13:37.06 [Backend]: Succesfully set selection to: MainCounter: Sel Start: 42061026 Sel End: 61937339 Sel Length:
04.05.2022 18:13:37.12 [Backend]: Pressing key: kVK_LeftArrow. Flags: Zero
04.05.2022 18:13:37.26 [Backend]: Logging unknown error in action (02) DoMainCounterAction: Clip Rename to Marker: Line 4
Logging unknown error in action (02) DoForEachClipAction: Clip Rename to Marker: Line 4
Logging unknown error in action (02) DoForEachSelectedClipAction: Clip Rename to Marker: Line 404.05.2022 18:13:37.26 [Backend]: Error running Js Callback: 'Clip Rename to Marker: Line 4' ( line 28)
JavaScript error with InnerException: Element was not found or removed after waiting 2000 ms (Clip Rename to Marker: Line 4)04.05.2022 18:13:37.39 [Backend]: Logging error in action (01) DoMainCounterAction: Error: Clip Rename to Marker: Line 4
(Clip Rename to Marker line 28)04.05.2022 18:13:37.39 [Backend]: !! Command Error: Clip Rename to Marker [user:default:cl2s9t0cu0002jn106qa9tpo4]:
Error: Clip Rename to Marker: Line 4
(Clip Rename to Marker line 28) (Clip Rename to Marker: Line 23)<< Command: Clip Rename to Marker [user:default:cl2s9t0cu0002jn106qa9tpo4]
04.05.2022 18:13:37.57 [Backend]: [AxDeckInstance] InstanceShow: user:default:cku6k9r2l0000lu10a8we29rx:streamDeckHid.CL04L2A03786.6719ae48-adf4-417b-9322-9197ccf74126 (My Pro Tools Deck) Device: 'CL04L2A03786'
[AxDeckInstance] TriggerDraw: user:default:cku6k9r2l0000lu10a8we29rx:streamDeckHid.CL04L2A03786.6719ae48-adf4-417b-9322-9197ccf74126 (My Pro Tools Deck) Device: 'CL04L2A03786'
[AxStreamDeckDevice] Device 'CL04L2A03786' -> ShowDeckInstance: user:default:cku6k9r2l0000lu10a8we29rx:streamDeckHid.CL04L2A03786.6719ae48-adf4-417b-9322-9197ccf74126
[AxStreamDeckDevice] DrawInstance. instance 'user:default:cku6k9r2l0000lu10a8we29rx:streamDeckHid.CL04L2A03786.6719ae48-adf4-417b-9322-9197ccf74126'
[AxDeckInstance] InstanceShow: user:default:cku6k9r2l0000lu10a8we29rx:streamDeckHid.CL04L2A03786.6719ae48-adf4-417b-9322-9197ccf74126 (My Pro Tools Deck) Device: 'CL04L2A03786'
[AxDeckInstance] TriggerDraw: user:default:cku6k9r2l0000lu10a8we29rx:streamDeckHid.CL04L2A03786.6719ae48-adf4-417b-9322-9197ccf74126 (My Pro Tools Deck) Device: 'CL04L2A03786'
[AxStreamDeckDevice] Device 'CL04L2A03786' -> ShowDeckInstance: user:default:cku6k9r2l0000lu10a8we29rx:streamDeckHid.CL04L2A03786.6719ae48-adf4-417b-9322-9197ccf74126
[AxStreamDeckDevice] DrawInstance. instance 'user:default:cku6k9r2l0000lu10a8we29rx:streamDeckHid.CL04L2A03786.6719ae48-adf4-417b-9322-9197ccf74126'04.05.2022 18:13:51.04 [Backend]: [SF_FIREBASE_WS]: Sending keep-alive
Thanks Kitch,
WillKitch Membery @Kitch2022-05-05 02:09:45.320Z
Hi Will,
Did you try it with the Memory Locations window open?
I did not put that in the code. (I'll add it shortly.)
Hopefully that's what the issue is. :-)
- WWill LeMaster @Will_LeMaster
Hi Kitch,
I just tried it with the Memory Locations window open and closed. The error came up on both. When I tried it with the Memory Locations window closed, the process opened the Memory Locations window for a moment, then it closed.Kitch Membery @Kitch2022-05-05 03:19:39.488Z
Hi @Will_LeMaster,
Did you use the updated version of the Script above?
If you could create a new script and paste the code and run it independent of the other script that would be great.Make sure to have "Link Track and edit Selection" on.
Make sure you have a single track with the clips selected that you want to rename.And if it continues to fail if you could do a screen recording of it failing that would be very helpful.
Rock on!
- In reply toWill_LeMaster⬆:
Kitch Membery @Kitch2022-05-05 03:26:13.916Z
Here is a video of it in action;
- WIn reply toWill_LeMaster⬆:Will LeMaster @Will_LeMaster
Hi @Kitch .
Thanks for the updated script. It is still unsuccessful for me, though. Here's a screen recording:Kitch Membery @Kitch2022-05-05 17:13:09.559Z
Hi @Will_LeMaster,
Thanks for the video, It looks like you are doing everything right. I'll revisit the script today to see if there is something I missed.
What line is the error you are seeing on (the one that logs in the top right corner)?
- WWill LeMaster @Will_LeMaster
The error is in line 4. Thanks @Kitch .
Kitch Membery @Kitch2022-05-05 19:27:49.045Z
Oh... That's strange indeed. Line 4 of the script is just waiting for the "Name" (or rename) window to appear, which leads me to believe that the ['Clip', 'Rename...'] ,menu item is not being clicked.
Can you select a clip and run the following code and let me know if the "Name" window appears?
sf.ui.proTools.appActivateMainWindow(); sf.ui.proTools.menuClick({ menuPath: ['Clip', 'Rename...'] });
Hopefully we can work this out.
Rock on!
- WWill LeMaster @Will_LeMaster
Very interesting...
I ran your script and it didn't work.
I ran a script to 'group clips and rename' that I made as a macro, then converted it to script.
Then I reran your script, and it worked.Here's a recording of the process:
https://www.dropbox.com/s/xgklrwyufe00o22/Screen Recording 2022-05-05 at 12.57.33 PM.mov?dl=0Kitch Membery @Kitch2022-05-05 20:13:52.300Z
Hmmm... All I can think is that SoundFlow or Pro Tools was stuck with cached information.
Is it continuing to work now?
If so try the script from post 8 again and let me know if that now works.
It also may be a good idea to make sure that you are on the latest version of SoundFlow from https://my.soundflow.org/install.
:-)
- WIn reply toWill_LeMaster⬆:Will LeMaster @Will_LeMaster
That behavior is on a clip by clip basis. If I selected a different clip (that I hadn't ran my macro/script on) then the name window would not open. Run my script on that clip then rerun your script, the name window would open. Very repeatable.
SoundFlow ver 5.1.4 , I believe that's the latest version.
- WIn reply toWill_LeMaster⬆:Will LeMaster @Will_LeMaster
I can screen record it, if you'd like.
- WIn reply toWill_LeMaster⬆:Will LeMaster @Will_LeMaster
Hi @Kitch !
I have finally been able to come back to this. The script works great, you ROCK, Dude!!
Thanks for all your valuable input, on this and all other things SF!
WillKitch Membery @Kitch2022-05-12 19:51:54.199Z
My pleasure, Will :-)
Curtis Macdonald @Curtis_Macdonald
Just found this useful script! But it's not working for me in PT 2024.6, and SF 5.8.0.
Here is the error I'm getting:
Error: Rename Clips by Markers: Line 4 (Rename Clips by Markers line 34) (Rename Clips by Markers: Line 29)
Is it possible to update this script with the new PT marker window in mind?
Thank you!
CurtisKitch Membery @Kitch2024-08-19 19:35:44.363Z
Unfortunately, the information you've provided is not sufficient for me to troubleshoot the issue.
The best way to get help with a command from a package you've downloaded from the SoundFlow store is to use the command's red "Need Help" button.
To learn how to do this please see the video in the following link.
https://soundflow.org/docs/help#script-help
Hopefully, with more information, I'll be able to troubleshoot the issue further.
Since I originally wrote this script, once the new thread has been create please tag me with
@Kitch
so that I get notified.Thanks in advance.
- In reply toCurtis_Macdonald⬆:
Kitch Membery @Kitch2024-08-19 19:46:32.202Z
Actually, this may be a simple fix, please add the following line of code...
sf.keyboard.press({keys:"left"});
above line 2.
sf.ui.proTools.menuClick({ menuPath: ['Clip', 'Rename...'] });
Let me know if that works for you. :-)
Curtis Macdonald @Curtis_Macdonald
Thank you @Kitch for your quick reply, expert guidance and willingness to help!
Everything worked flawlessly after I showed "Auto-created" clips in the Clip List. Love this script!
This PT behavior has confused me in the past: If the clip name has been auto-generated and "Auto-created" clips are hidden in the Clip List, then simple menu commands like Clip - Rename become unresponsive, which I often forget!
Thank you so much again,
CurtisKitch Membery @Kitch2024-08-20 17:03:13.874Z
Ah, yes that will do it. I'm glad you got it working :-)
Rock on!
Curtis Macdonald @Curtis_Macdonald
Hi Kitch! Wondering if this script could be updated to allow the renaming of clips based of selected marker rulers.
@Chad made a script to split clips based off of selected marker rulers, and so am wondering if a similar method could be done here. Split Selected Clips at Specified Marker Track #post-2
Thanks for the help!
Chad Wahlbrink @Chad2025-05-05 16:11:37.965Z
Hey @Curtis_Macdonald,
If you wanted to add the ability to rename the clips by markers on a named marker track, you could use this expanded version of the other script I shared. You can turn on and off "separate" and "rename" functions at the top of the script (true - on, false - off). Let me know if this is what you are after:
// Set the Marker Track Name Here (Markers, Markers 2, Markers 3, Another Track Name...) let markerTrackName = 'MIX'; // Set to True to Separate at Markers let separateAtMarkers = true; // Set to True to rename by Markers let renameClipsByMarkers = true; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Function to get a list of the currently online audio files in the session */ function getOnlineAudioFilesInSession() { // Get Session Info as Text let sessionInfo = sf.app.proTools.getSessionInfoAsText({ includeFileList: true }).sessionInfo; // Split Session Info Text by Online Files in Session Section let onlineFilesRaw = sessionInfo.split('O N L I N E F I L E S I N S E S S I O N')[1].split('O F F L I N E F I L E S I N S E S S I O N')[0] // Split the Online Files by New Line Characters (\n) let onlineFilesRawSplitByLine = onlineFilesRaw.split(/\n/); // Trim the excess from the front and bottom let onlineFilesRawSliced = onlineFilesRawSplitByLine.slice(2, onlineFilesRawSplitByLine.length - 3) // Trim the file names - now we have a list of the audio files in the session. let onlineFilesList = onlineFilesRawSliced.map(file => file.split('\t')[0].trim()); // Capture just the Audio File Name - remove .wav let re = /(.*)(.wav)/ let onlineFilesWithoutFileType = onlineFilesList.map(fileWithWAV => fileWithWAV.match(re)[1]) return onlineFilesWithoutFileType; } /** * Function to rename files and add a postfix number if needed */ function smartClipRename(newClipName) { // Files let files = getOnlineAudioFilesInSession(); // If File List has a match for the new name if (files.includes(newClipName)) { let re = /(\d+)$/; //Split the file Name by '_' let filesWithSplit = files.map(file => file.split(re)); // Filter the Split Files by names that match the prefix of the new name let filesWithSplitFiltered = filesWithSplit.filter(x => x[0] == newClipName.split(re)[0]) // What is the last file of the filtered files let lastFile = filesWithSplitFiltered.slice(-1)[0]; let number; // Add Leading Zeros for under 10; if (Number(lastFile[1]) < 9) { number = `0${Number(lastFile[1]) + 1}` } else { number = `${Number(lastFile[1]) + 1}` } newClipName = lastFile[0] + number; } sf.app.proTools.renameSelectedClip({ clipLocation: "Timeline", newName: newClipName, renameFile: true, executionMode: "Foreground" }); } function main() { 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) ) ); // If we want to separate at the markers for the named Marker Track if (separateAtMarkers) { // 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', }); }) } // If we want to rename the clips by the markers if (renameClipsByMarkers) { // For each Marker On the Named Marker Track and Within our Selection, Rename the Clip by the named marker track markersOnNamedTrack.forEach((marker) => { // Go to the Markers Location + 1 - this gets us to the right selected clip sf.app.proTools.setTimelineSelection({ inTime: String(Number(marker.location) + 1), }); // Store the selected clip Info let selectedClipInfo = sf.app.proTools.getSelectedClipInfo().clips[0] // Select the full Clip sf.app.proTools.setTimelineSelection({ inTime: String(selectedClipInfo.startTime), outTime: String(selectedClipInfo.endTime), }); // You can use `renameClip` to rename via the clip list or `smartClipRename` to rename with the SDK // renameClip(`${marker.name}`); smartClipRename(`${marker.name}`) }) } } 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, }); } } main();
Curtis Macdonald @Curtis_Macdonald
Chad, this is a super powerful script! Can't thank you enough.
I see it gets tripped on some special characters if found in the marker tracks, like a ":" for example. Is there a way to have the script remove or ignore any illegal characters automatically?
Thank you again!
Chad Wahlbrink @Chad2025-05-06 23:20:49.671Z
That should be doable! I'll look into this in the coming days.