Rename clips by markers in Pro Tools
Hello, I wonder if there is a way to make a script for Pro tools to rename all clips in a track (Beginnig to end of the session) by each marker in front of each clip
I am trying to repeat this several times
I found some script here but I think is incomplete for what I need
Also, I would like to run this for clips that are already cut, avoiding a last strip silence again
function getMemLocName() {
const currentLocation = sf.ui.proTools.selectionGetInSamples()
const memLocName = sf.proTools.memoryLocationsFetch().collection['list'].filter(x =>
x.mainCounterValue >= currentLocation.selectionStart &&
x.mainCounterValue <= currentLocation.selectionEnd
)[0]
return memLocName
}
function renameClip() {
// Get First Memory Location Name from selection
const memLocName = getMemLocName()
if (memLocName != undefined) {
//Open Rename window
sf.ui.proTools.menuClick({ menuPath: ['Clip', 'Rename...'] });
//Reference for Rename Window
const renameWin = sf.ui.proTools.windows.whoseTitle.is('Name').first.elementWaitFor({ waitType: "Appear" }).element
const nameClipOnlyButton = renameWin.groups.first.radioButtons.first
/// Set Clip Name Only
if (nameClipOnlyButton.exists)
renameWin.groups.first.radioButtons.first.checkboxSet({ targetValue: "Enable" });
// Set the clip name to Track name
renameWin.groups.first.textFields.first.elementSetTextFieldWithAreaValue({ value: memLocName.Name });
// Click OK
renameWin.buttons.whoseTitle.is('OK').first.elementClick()
// Wait for window to cloce
renameWin.elementWaitFor({ waitType: "Disappear" })
}
}
function main() {
// Acivate Pro Tools
sf.ui.proTools.appActivateMainWindow()
// Do For Each
sf.ui.proTools.clipDoForEachSelectedClip({
action: renameClip,
onError: "Continue"
})
}
main()
- samuel henriques @samuel_henriques
Hello Maggy,
I think this was my code, and has a fundamental mistake, maybe it worked when I made it, but I can see now how it could fail.
Here's the fixed code, and made it faster.
Let me know how it goes.
function getMemLoc() { // Functions to grab start and end time on any counter //( because its runnign on clipDoForEachSelectedClip it should be Samples, but will work on any) const getSelectionStart = () => sf.ui.proTools.selectionGet().selectionStart.replace(/[:.+| ]/g, ''); const getSelectionEnd = () => sf.ui.proTools.selectionGet().selectionEnd.replace(/[:.+| ]/g, ''); // filter mem locs within selection const memLocFromSelection = sf.proTools.memoryLocationsFetch().collection['list'].filter(m => m.mainCounterValue.replace(/[:.+| ]/g, '') >= getSelectionStart() && m.mainCounterValue.replace(/[:.+| ]/g, '') <= getSelectionEnd() ); // return first memory location within selection return memLocFromSelection[0] }; function renameClip() { // Get First Memory Location Name from selection const memLocFromSelection = getMemLoc() if (memLocFromSelection) { //Open Rename window sf.ui.proTools.menuClick({ menuPath: ['Clip', 'Rename...'] }); //Reference for Rename Window const renameWin = sf.ui.proTools.windows.whoseTitle.is('Name').first.elementWaitFor({ waitType: "Appear" }).element const nameClipOnlyButton = renameWin.groups.first.radioButtons.first /// Set Clip Name Only if (nameClipOnlyButton.exists) renameWin.groups.first.radioButtons.first.checkboxSet({ targetValue: "Enable" }); // Set the clip name to Track name renameWin.groups.first.textFields.first.elementSetTextFieldWithAreaValue({ value: memLocFromSelection.name }); // Click OK renameWin.buttons.whoseTitle.is('OK').first.elementClick() // Wait for window to cloce renameWin.elementWaitFor({ waitType: "Disappear" }) } } function main() { // Acivate Pro Tools sf.ui.proTools.appActivateMainWindow() // Do For Each sf.ui.proTools.clipDoForEachSelectedClip({ action: renameClip, onError: "Continue" }) } main()
- MIn reply toMaggy_Ayala⬆:Maggy Ayala @Maggy_Ayala
Hey Samuel, thanks a lot for your help
Looks like a bit faster and it allows me to use it with clips I have already cut
but the names what it start to put are ramdom
ie
clip 1 have a marker with 101 but the script ended naming like 123 (what is another marker in another place)samuel henriques @samuel_henriques
umm...
could you share a screen recording of it running?
samuel henriques @samuel_henriques
Could it be two clips that are actually the the same whole clip? It renames the first, and it changes when the script renames the second clip.
If you can have this situation, we could consolidate the clips before renaming them
- MIn reply toMaggy_Ayala⬆:Maggy Ayala @Maggy_Ayala
Sure
Have a look here https://filebin.net/6scqrnqeeugvtp1h
I did try to consolidate each clip before run the script and the result is exactly the sameOh man, I feel this is super close but .. haha
samuel henriques @samuel_henriques
Got it, the script is looking for a marker within the clip selection, the first memory location after the start of the clip, but before its end. But, if there is no marker it shouldn't change the name.
Could you try to make the markers on the clips, just to see if it works better?
samuel henriques @samuel_henriques
could you confirm the version of PT you are using?
and to work the way you want, where the markers are outside the clips, I need to think of another way.
Could be making a selection including the markers, and if the number of markers is the same as the number of selected clips, it would name each clip on the same order of markers. Does this make sense?samuel henriques @samuel_henriques
I made a new version based on your workflow. It will name the clips based on the memory locations in the selection and in the same order.
for example, the selection you made wouldn't,
In this case, the clip 1 would be named L09, clip 2 L11, clip 3 L13 and clip 4 wouldn't be named.
You must make a selection including the markers and the clips you want to rename.
First marker name will go to the first selected clip, second marker to the second clip and so on.
You can't have any other markers in the way otherwise it will use those to name.Give this a try,
function getMemLoc() { // Functions to grab start and end time on any counter //( because its running on clipDoForEachSelectedClip it should be Samples, but will work on any) const getSelectionStart = () => sf.ui.proTools.selectionGet().selectionStart.replace(/[:.+| ]/g, ''); const getSelectionEnd = () => sf.ui.proTools.selectionGet().selectionEnd.replace(/[:.+| ]/g, ''); // filter mem locs within selection const memLocFromSelection = sf.proTools.memoryLocationsFetch().collection['list'].filter(m => m.mainCounterValue.replace(/[:.+| ]/g, '') >= getSelectionStart() && m.mainCounterValue.replace(/[:.+| ]/g, '') <= getSelectionEnd() ); // return first memory location within selection return memLocFromSelection } let index = 0 /** * @param {array} memLocs */ function renameClip(memLocs) { if (memLocs[index]) { //Open Rename window sf.ui.proTools.menuClick({ menuPath: ['Clip', 'Rename...'] }); //Reference for Rename Window const renameWin = sf.ui.proTools.windows.whoseTitle.is('Name').first.elementWaitFor({ waitType: "Appear" }).element const nameClipOnlyButton = renameWin.groups.first.radioButtons.first /// Set Clip Name Only if (nameClipOnlyButton.exists) renameWin.groups.first.radioButtons.first.checkboxSet({ targetValue: "Enable" }); // Set the clip name to Track name renameWin.groups.first.textFields.first.elementSetTextFieldWithAreaValue({ value: memLocs[index].name }); // Click OK renameWin.buttons.whoseTitle.is('OK').first.elementClick() // Wait for window to cloce renameWin.elementWaitFor({ waitType: "Disappear" }) index++ } } function main() { // Acivate Pro Tools sf.ui.proTools.appActivateMainWindow(); sf.ui.proTools.invalidate(); sf.ui.proTools.memoryLocationsEnsureWindow({ restoreWindowOpenState: true, action: () => { // Get Locations from selection const memLocFromSelection = getMemLoc() // Do For Each sf.ui.proTools.clipDoForEachSelectedClip({ action: () => renameClip(memLocFromSelection), onError: "Continue" }); } }); }; main();
- VVasiko Tsabadze @Vasiko_Tsabadze
Hey Samuel !
Following a recent update of Pro Tools, it seems that the script is no longer functioning as intended. As someone who heavily relies on this functionality for my workflow, I was wondering if you have time to updating the script to make it compatible with the latest version of Pro Tools 2023.6.
Thanks !
samuel henriques @samuel_henriques
Hello Vasiko,
Just tested and it's working on my 2023.6. Are you getting any error?
You can make a screen capture video of the script failing so I can try to figure what is working differentlysamuel henriques @samuel_henriques
The new marker window is different but the way the script is reading the marker list is still the same.
Can you double check the sort by option is Time?- VVasiko Tsabadze @Vasiko_Tsabadze
Yes, markers are sorted by Time.
Here is the video: https://youtu.be/aSeUCH9LyGQsamuel henriques @samuel_henriques
Can't reproduce the issue.
I made a slight change and updated above, could you try the new version please?- Ssgiacometti @sgiacometti
Hey Samuel, should this script still work with PT 2023.9?
It's not working for me at the moment (it goes through all clips, but doesn't change the name).
I'm pretty new at this, but after trying to figure out what's going on, it looks like memLocFromSelection is filtering memory locations by Main Counter Value, so it's expecting a value in samples. With the current version of PT, I get this as memoryLocationsFetch result:
"Number": 3,
"Name": "3",
"MarkerTrack": "Selected. Marker Ruler",
"MainCounterValue": "Marker Ruler'
This of course means that no markers are found after filtering, so the name stays unchanged.
Am I doing something wrong, or is memoryLocationsFetch currently not working as it should?samuel henriques @samuel_henriques
hello sgiacometti,
pro tools has changed the memory location window.
replace lines 1 to 19 with,/** * Retrieves a list of memory locations. * * @function * @returns {Array<Object>} An array of objects representing memory locations. * @property {boolean} isSelected - Indicates whether the memory location is selected. * @property {string} Sharing Merging * @property {string} Active Location * @property {string} Number * @property {string} Name * @property {string} Track Name * @property {string} Marker View filter * @property {string} Selection Memory Location View filter * @property {string} Zoom Settings View filter * @property {string} Pre/Post-Roll View filter * @property {string} Show/Hide View filter * @property {string} Track Heights View filter * @property {string} Active Groups View filter * @property {string} Window Configuration filter * @property {string} Venue Snapshot filter * @property {string} MainCounterValue * @property {string} Sub Counter * @property {string} Comments */ function getMemoryLocationsList() { let memLocList = [] sf.ui.proTools.memoryLocationsEnsureWindow({ action: () => { const memLocWin = sf.ui.proTools.memoryLocationsWindow.tables.whoseTitle.is("Memory Locations") const memLocColumns = memLocWin.first.children.whoseRole.is("AXColumn").first.children.whoseRole.is("AXRow").first.children.whoseRole.is("AXCell").map(mem => mem.children.whoseRole.is("AXStaticText").first.title.value .replace("Numeration", "number") .replace("Marker Name", "name") .replace("Main Counter", "mainCounterValue") ); memLocWin.allItems[1].children.whoseRole.is("AXRow").map(r => { let obj = {}; r.children.whoseRole.is("AXCell").map((cell, i) => { obj["isSelected"] = false const cellValue = cell.children.whoseRole.is("AXStaticText").first.value.value if (cellValue.startsWith("Selected. ")) { obj["isSelected"] = true } obj[memLocColumns[i]] = cellValue.replace("Selected. ", "") }) memLocList.push(obj) }) }, restoreWindowOpenState: true }) return memLocList }; function getMemLoc() { // Functions to grab start and end time on any counter //( because its runnign on clipDoForEachSelectedClip it should be Samples, but will work on any) const getSelectionStart = () => +sf.ui.proTools.selectionGet().selectionStart.replace(/[:.+| ]/g, ''); const getSelectionEnd = () => +sf.ui.proTools.selectionGet().selectionEnd.replace(/[:.+| ]/g, ''); // filter mem locs within selection const memLocFromSelection = getMemoryLocationsList().filter(m => +m.mainCounterValue.replace(/[:.+| ]/g, '') >= getSelectionStart() && +m.mainCounterValue.replace(/[:.+| ]/g, '') <= getSelectionEnd() ); // return first memory location within selection return memLocFromSelection }
- In reply tosamuel_henriques⬆:KKurt Kellenberger @Kurt_Kellenberger
Hi, I want to do something very similar, except that instead of replacing the clip name, I want to add each marker name to the beginning of each clip's current name, I would imagine using Batch Rename instead of Rename. And then ideally, I'd like to do that for all selected clips on all tracks
samuel henriques @samuel_henriques
Hello Kurt,
This script will go to each selected clip and read the marker within the clip selection. Bach rename clips, wouldn't know what marker is within each clip. So we would have to go clip by clip and rename it one at a time.
Unless you have one marker for all the selected clips, so one name you want to add on all selected clips, that would be, append to clip name in the batch rename.Let me know witch one you need.
- KKurt Kellenberger @Kurt_Kellenberger
Hi Samuel, and TIA!
Basically, all I want is exactly the same behavior as the current script, but to add each marker name as a prefix to the current clip name instead of replacing the current clip name, so the resulting clip name would be something like "(MarkerName)_(ClipCurrentName)". I only mentioned Batch Rename because it has an "Add: Prefix" field I thought might be useful for this.- KKurt Kellenberger @Kurt_Kellenberger
So in this example, the resulting name of the first few clips would be "Location 1_Audio 1_02", "Location 2_Audio 1_01-05", etc.
samuel henriques @samuel_henriques
Sure, replace the renameClip function from lines 22 to 51 with:
/** * @param {array} memLocs */ function renameClip(memLocs) { if (memLocs[index]) { //Open Rename window sf.ui.proTools.menuClick({ menuPath: ['Clip', 'Rename...'] }); //Reference for Rename Window const renameWin = sf.ui.proTools.windows.whoseTitle.is('Name').first.elementWaitFor({ waitType: "Appear" }).element const nameClipOnlyButton = renameWin.groups.first.radioButtons.first /// Set Clip Name Only if (nameClipOnlyButton.exists) renameWin.groups.first.radioButtons.first.checkboxSet({ targetValue: "Enable" }); const currentClipName = renameWin.groups.first.textFields.first.value.invalidate().value const newClipName = memLocs[index].name + "_" + currentClipName // Set the clip name to Track name renameWin.groups.first.textFields.first.elementSetTextFieldWithAreaValue({ value: newClipName }); // Click OK renameWin.buttons.whoseTitle.is('OK').first.elementClick() // Wait for window to cloce renameWin.elementWaitFor({ waitType: "Disappear" }) index++ } }
- KKurt Kellenberger @Kurt_Kellenberger
Excellent! Thanks!! One last thing, would there be a way to skip renaming clips that have no marker within their boundaries? Or put another way: only rename clips that have markers within their start and end points?
samuel henriques @samuel_henriques
ok, now the old script would grab the collection of markers in the initial selection and add info on them to the clips in the same selection, the markers did't have to be within the clip boundary, so the first maker info would go to the first clip in the selection the second marker to second clip and so on. This has a problem where selected clips in the selection could be in a different order than the same clips on the clip list and pro tools uses the clip list order to rena clips, using the old script method.
this new one will select the first clip in the selection, then check what markers exist within the selected clip boundary and add it's name to the clip name the way you asked. If more than one marker exist, it will use the first, if no marker exists it will skip the clip.
I hope I was clear, just so you use them accordingly depending on the case.
Here yo go:
function getMemLoc() { // Functions to grab start and end time on any counter //( because its running on clipDoForEachSelectedClip it should be Samples, but will work on any) const getSelectionStart = () => sf.ui.proTools.selectionGet().selectionStart.replace(/[:.+| ]/g, ''); const getSelectionEnd = () => sf.ui.proTools.selectionGet().selectionEnd.replace(/[:.+| ]/g, ''); // filter mem locs within selection const memLocFromSelection = sf.proTools.memoryLocationsFetch().collection['list'].filter(m => m.mainCounterValue.replace(/[:.+| ]/g, '') >= getSelectionStart() && m.mainCounterValue.replace(/[:.+| ]/g, '') <= getSelectionEnd() ); // memory locations within selection return memLocFromSelection } function renameClip() { const memLocFromSelection = getMemLoc(); // If mem loc exists if (memLocFromSelection.length) { //Open Rename window sf.ui.proTools.menuClick({ menuPath: ['Clip', 'Rename...'] }); //Reference for Rename Window const renameWin = sf.ui.proTools.windows.whoseTitle.is('Name').first.elementWaitFor({ waitType: "Appear" }).element /// Set Clip Name Only const nameClipOnlyButton = renameWin.groups.first.radioButtons.first if (nameClipOnlyButton.exists) renameWin.groups.first.radioButtons.first.checkboxSet({ targetValue: "Enable" }); //Get current clip name const currentClipName = renameWin.groups.first.textFields.first.value.invalidate().value; //Build new name const newClipName = memLocFromSelection[0].name + "_" + currentClipName; // Set the clip name to Track name renameWin.groups.first.textFields.first.elementSetTextFieldWithAreaValue({ value: newClipName }); // Click OK renameWin.buttons.whoseTitle.is('OK').first.elementClick() // Wait for window to cloce renameWin.elementWaitFor({ waitType: "Disappear" }) }; }; function main() { // Acivate Pro Tools sf.ui.proTools.appActivateMainWindow(); sf.ui.proTools.invalidate(); sf.ui.proTools.memoryLocationsEnsureWindow({ restoreWindowOpenState: true, action: () => { // Do For Each sf.ui.proTools.clipDoForEachSelectedClip({ action: () => renameClip(), onError: "Continue" }); } }); }; main();
- KKurt Kellenberger @Kurt_Kellenberger
Very nice, I think this does it! For some reason, in my test session it is skipping marker-to-clip name "Location 1", but that might be something to do with the clip creation. But yes, this looks like it gets at least 99% of the way there. Thank you!!
- MIn reply toMaggy_Ayala⬆:Maggy Ayala @Maggy_Ayala
Hey Samuel, this one definetly works a lot better, pretty happy about it :) again, thanks so much for you help
Still, I can see even I made sure each clip is near to his marker, at some point just stop to rename (but still does the process like copying the name from the marker, and still at some point takes from the marker 2 clips away
I also notice that It doesnt name correctly if I do a huge selectionI am still trying to figure all the little glitches
I will so another little video soon - MIn reply toMaggy_Ayala⬆:Maggy Ayala @Maggy_Ayala
Have a look
https://filebin.net/vxw9vrnb5e448q8e
there are bit even I am inside the rules I was following for the others clips, (as you said for the new script, select markers and clips to rename) still, it will not rename correctly, even if I consolidate again
I am on PT 2020.12.0 and OSX 10.15.6samuel henriques @samuel_henriques
something else is wrong, it should choose "name clip only" and its not doing it, on the other video as well. The recording might be missing if because it's too fast, but you should be able to see it.
can't say if it has to do with versions of pt, but I'm on 2021.7, and might be some things different versions do to soundFlow.
on this video, it didn't rename anything, or you made the video after renaming?
do you see the memory locations window open and close?
samuel henriques @samuel_henriques
you have the memory locations sorted by number, could you try to sort by time?
it certainly makes a difference for this workflow.
- WIn reply toMaggy_Ayala⬆:William Kleinsasser @William_Kleinsasser
Hello, I have a need to use this exact functionality in Protools sessions with multiple clips. I'm using Protools version 2022.9.0 for reasons of plugin compatibility. The script below is not working for me. I'm selecting all the clips in the session, including the markers bar and then running the script but in Protools the only thing that happens is Protools becomes the active top application. If anyone can help, I'd really appreciate it.
Thanks,
WKfunction getMemLoc() { // Functions to grab start and end time on any counter //( because its runnign on clipDoForEachSelectedClip it should be Samples, but will work on any) const getSelectionStart = () => sf.ui.proTools.selectionGet().selectionStart.replace(/[:.+| ]/g, ''); const getSelectionEnd = () => sf.ui.proTools.selectionGet().selectionEnd.replace(/[:.+| ]/g, ''); // filter mem locs within selection const memLocFromSelection = sf.proTools.memoryLocationsFetch().collection['list'].filter(m => m.mainCounterValue.replace(/[:.+| ]/g, '') >= getSelectionStart() && m.mainCounterValue.replace(/[:.+| ]/g, '') <= getSelectionEnd() ); // return first memory location within selection return memLocFromSelection[0] }; function renameClip() { // Get First Memory Location Name from selection const memLocFromSelection = getMemLoc() if (memLocFromSelection) { //Open Rename window sf.ui.proTools.menuClick({ menuPath: ['Clip', 'Rename...'] }); //Reference for Rename Window const renameWin = sf.ui.proTools.windows.whoseTitle.is('Name').first.elementWaitFor({ waitType: "Appear" }).element const nameClipOnlyButton = renameWin.groups.first.radioButtons.first /// Set Clip Name Only if (nameClipOnlyButton.exists) renameWin.groups.first.radioButtons.first.checkboxSet({ targetValue: "Enable" }); // Set the clip name to Track name renameWin.groups.first.textFields.first.elementSetTextFieldWithAreaValue({ value: memLocFromSelection.name }); // Click OK renameWin.buttons.whoseTitle.is('OK').first.elementClick() // Wait for window to cloce renameWin.elementWaitFor({ waitType: "Disappear" }) } } function main() { // Acivate Pro Tools sf.ui.proTools.appActivateMainWindow() // Do For Each sf.ui.proTools.clipDoForEachSelectedClip({ action: renameClip, onError: "Continue" }) } main()
- WWilliam Kleinsasser @William_Kleinsasser
I figured it out. In the Protools session only one track can be selected. Before running the script, open Protools file and select a single track name in the left column of the tracks window, then select the region and include the marker strip in the selection. Be sure that markers and clips are sorted by time not name. With these settings and selection, run the SoundFlow script to rename clips with marker names. This is such a useful script! Thank you.
- DIn reply toMaggy_Ayala⬆:Dylan Furrow @Dylan_Furrow
Hey guys, I've been trying to use this script and it doesn't seem to be renaming the clips. Everything else seems fine though