Script to grab name data from a marker and rename clip
Hi all,
I do a lot of jazz sessions where we usually just put every take in the same session, so that the band can cycle from song to song on a whim rather than saying "Um, we're going to do such and such now" and then they have to wait while I have to close this session and open another, make sure that all the aux sends for monitoring are the same, etc. So my workflow is that I always print through our console on a seperate track that I just call "Print". When the band starts going I hit record and I make a marker where I put in take number ("T1", "T2", etc.) and song title (so it hypothetically becomes "T2 Someday My Prince Will Come"). When the session is over I manually rename all the clips on my print track and export them as files. This is tedious when the band does 80 takes over the course of a couple of days.
I found this script that works pretty well by @samuel_henriques, but if I make a larger selection it starts to mess up and suddenly T4 has the name of T5 etc. It would be so beautiful if I could just mark every region on my print track and hit a button on my streamdeck and it renames them all, and it works correctly. Would make me VERY happy. :)
Here's the script (copied from Rename clips by markers in Pro Tools, for whatever reason it doesn't want to format correctly in the forum post, but it is a direct copy/paste from that thread):
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
}
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()
// Get Locations from selection
const memLocFromSelection = getMemLoc()
// Do For Each
sf.ui.proTools.clipDoForEachSelectedClip({
action: () => renameClip(memLocFromSelection),
onError: "Continue"
})
}
main()
Here's a video of what happens.
Would appreciate any help. :)
- samuel henriques @samuel_henriques
Hello Kyrre,
I'm sorry, I can see now how this script is not great. Hopefully it's better now.
Let me know if its working well for you/** * @param {string} name */ function renameClip(name) { if (name) { //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.whoseTitle.is("name clip only").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: name }); // Click OK renameWin.buttons.whoseTitle.is('OK').first.elementClick() // Wait for window to cloce renameWin.elementWaitFor({ waitType: "Disappear" }) }; }; function getMemLocNameFromSelection() { // Grab start and end time on any counter - (.replace(/[:.+| ]/g, '') - works on any couter const selection = sf.ui.proTools.selectionGet(); const selectionStart = +selection.selectionStart.replace(/[:.+| ]/g, '') const selectionEnd = +selection.selectionEnd.replace(/[:.+| ]/g, '') // Filter mem locs within selection //(.replace(/[:.+| ]/g, '') - to work on any couter const memLocFromSelection = sf.proTools.memoryLocationsFetchFromGui().collection['list'].filter(m => +m.mainCounterValue.replace(/[:.+| ]/g, '') >= selectionStart && +m.mainCounterValue.replace(/[:.+| ]/g, '') <= selectionEnd ); // return first memory location name within selection return memLocFromSelection[0].name } function main() { // Acivate Pro Tools sf.ui.proTools.appActivateMainWindow(); sf.ui.proTools.invalidate(); const isMemLocWinOpen = sf.ui.proTools.getMenuItem("Window", "Memory Locations").isMenuChecked sf.ui.proTools.menuClick({ menuPath: ["Window", "Memory Locations"], targetValue: "Enable" }) // Do For Each sf.ui.proTools.clipDoForEachSelectedClip({ action: () => renameClip(getMemLocNameFromSelection()), onError: "Continue" }) if (!isMemLocWinOpen) { sf.ui.proTools.menuClick({ menuPath: ["Window", "Memory Locations"], targetValue: "Disable" }) } } main()
- KKyrre Laastad @Kyrre_Laastad
Hi Samuel,
Thank you so much! This appears to be working perfectly. What a joy! Will try to get time to test it more thoroughly with more sessions tomorrow, but it appears that it does work as intended. Thanks again!
Best
Kyrre- SStudioA StudioA @StudioA_StudioA
This is super useful. Is there a way to alter it to rename the clips based on the markers comments? This would be amazing!
samuel henriques @samuel_henriques
Here you go StudioA,
It's much slower because reading the comments is more complicated. Until I figure a better way...Hope this helps:
function getMemLocNumberFromSelection() { const selection = sf.ui.proTools.selectionGet() // Grab start and end time on any counter - (.replace(/[:.+| ]/g, '') - works on any counter const selectionStart = +selection.selectionStart.replace(/[:.+| ]/g, '') const selectionEnd = +selection.selectionEnd.replace(/[:.+| ]/g, '') // Filter mem locs within selection //(.replace(/[:.+| ]/g, '') - to work on any counter const memLocFromSelection = sf.proTools.memoryLocationsFetchFromGui().collection['list'].filter(m => +m.mainCounterValue.replace(/[:.+| ]/g, '') >= selectionStart && +m.mainCounterValue.replace(/[:.+| ]/g, '') <= selectionEnd ); // return first memory location number within selection return memLocFromSelection[0].number }; /** * @param {string | number} memLocNumber */ function getCommentsFromMemLocByNumber(memLocNumber) { sf.ui.proTools.memoryLocationsGoto({ memoryLocationNumber: +memLocNumber }); sf.ui.proTools.memoryLocationsWindow.popupButtons.first.popupMenuSelect({ menuSelector: items => items.filter(el => el.names[0].startsWith("Edit "))[0] }); const memLocWin = sf.ui.proTools.newMemoryLocationDialog.elementWaitFor({}, "Memory Location Win Didn\'t Open.").element; const comments = memLocWin.textFields.first.value.invalidate().value; memLocWin.buttons.whoseTitle.is("Cancel").first.elementClick(); memLocWin.elementWaitFor({ waitType: "Disappear" }, "Memory Location Win Didn\'t Close."); return comments }; /** * @param {string} name */ function renameClip(name) { // If no new name, return (leave function) if (!name) return //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.whoseTitle.is("name clip only").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: 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(); sf.ui.proTools.invalidate(); const isMemLocWinOpen = sf.ui.proTools.getMenuItem("Window", "Memory Locations").isMenuChecked sf.ui.proTools.menuClick({ menuPath: ["Window", "Memory Locations"], targetValue: "Enable" }) // Do For Each sf.ui.proTools.clipDoForEachSelectedClip({ action: () => { const comments = getCommentsFromMemLocByNumber(getMemLocNumberFromSelection()); sf.ui.proTools.menuClick({ menuPath: ["Edit", "Restore Last Selection"] }); renameClip(comments); }, onError: "Continue" }); if (!isMemLocWinOpen) { sf.ui.proTools.menuClick({ menuPath: ["Window", "Memory Locations"], targetValue: "Disable" }) } } main();
samuel henriques @samuel_henriques
Updated above, found a faster way...
- In reply tosamuel_henriques⬆:SStudioA StudioA @StudioA_StudioA
THANK YOU THIS IS WICKED! It's great for ADR workflows.
samuel henriques @samuel_henriques
Cool! Just be aware of forbidden symbols you can write on comments but you can't write on clip names. @#"* for example, will fail to be accepted by pro tools and stop the script. If you start getting this problem, I have a script I can easily add to this that will clean forbidden symbols and it should help.
- SStudioA StudioA @StudioA_StudioA
Thanks again I will bare that in mind. It works a treat so far.