Strip Silence Script
Hi All!
Andrew Scheps helped me script out some automation for Strip Silence (by helped, I mean he took my cave man script and brought it to life!)
It has a few things that could be improved upon, but thought we would share. You'll want to enter your strip silence settings before running the script, but this will strip silence from selected tracks, both adjacent and non. I love this one!
// NOTE: Setup Strip Silence with your preferred settings before running this script
function stripTheSilence(trackHeader) {
//Select track
trackHeader.trackSelect();
//Scroll track into View
trackHeader.trackScrollToView();
// Select All Clips In Track
sf.keyboard.press({
keys: 'cmd+a'
});
// Click Strip Button
sf.ui.proTools.windows.whoseTitle.is("Strip Silence").first.buttons.whoseTitle.is("Strip").first.mouseClickElement();
// Create Fades On Clips
sf.keyboard.press({
keys: 'f'
});
}
function main() {
// Set Pro Tools frontmost
sf.ui.proTools.appActivateMainWindow();
//Get selected tracks
const selectedTrackHeaders = sf.ui.proTools.selectedTracks.trackHeaders;
// Declare stripSilenceWin Variable as Strip Silence Window
var stripSilenceWin = sf.ui.proTools.windows.whoseTitle.is("Strip Silence").first;
if (stripSilenceWin && stripSilenceWin.exists) {
//Strip Silence IS open, do nothing
} else {
//Strip Silence is NOT open
// Open Strip Silence
sf.ui.proTools.menuClick({
menuPath: ['Edit', 'Strip Silence']
});
// stripSilenceWin.getElement("AXTitleUIElement").elementWaitFor();
}
selectedTrackHeaders.forEach( trackHeader => {
stripTheSilence(trackHeader)
});
// Close Strip Silence
sf.ui.proTools.viewCloseFocusedFloatingWindow();
}
main();
Linked from:
- MMark Abrams @Mark_Abrams
Sorry, looks like I copied it in wrong. It's my first day :)
Kitch Membery @Kitch2021-06-05 19:41:19.679Z
Hi @Mark_Abrams,
Thanks for sharing :-). I fixed the formatting for you.
Please check this tutorial for how to quote code in the SoundFlow forum, so that it displays in a readable format:
Rock on
Kitch- MMark Abrams @Mark_Abrams
Thanks Kitch! Will do!
- PIn reply toMark_Abrams⬆:Philip weinrobe @Philip_weinrobe
is anybody smart enough to modify this script so that when it ends it re-selects the originally selected tracks?
Ryan DeRemer @Ryan_DeRemer
@Philip_weinrobe Try this:
// NOTE: Setup Strip Silence with your preferred settings before running this script function stripTheSilence(trackHeader) { //Select track trackHeader.trackSelect(); //Scroll track into View trackHeader.trackScrollToView(); // Select All Clips In Track sf.keyboard.press({ keys: 'cmd+a' }); // Click Strip Button sf.ui.proTools.windows.whoseTitle.is("Strip Silence").first.buttons.whoseTitle.is("Strip").first.mouseClickElement(); } function main() { // Set Pro Tools frontmost sf.ui.proTools.appActivateMainWindow(); //Get selected tracks const selectedTrackHeaders = sf.ui.proTools.selectedTracks.trackHeaders; const origSelectedTracks = sf.ui.proTools.selectedTrackNames // Declare stripSilenceWin Variable as Strip Silence Window var stripSilenceWin = sf.ui.proTools.windows.whoseTitle.is("Strip Silence").first; if (stripSilenceWin && stripSilenceWin.exists) { //Strip Silence IS open, do nothing } else { //Strip Silence is NOT open // Open Strip Silence sf.ui.proTools.menuClick({ menuPath: ['Edit', 'Strip Silence'] }); // stripSilenceWin.getElement("AXTitleUIElement").elementWaitFor(); } selectedTrackHeaders.forEach( trackHeader => { stripTheSilence(trackHeader) }); // Close Strip Silence sf.ui.proTools.viewCloseFocusedFloatingWindow(); // Re-select original tracks sf.ui.proTools.trackSelectByName({ names: origSelectedTracks }); } main();
- AIn reply toMark_Abrams⬆:alex alcanjim @alex_alcanjim
Hi all,
I found this script really useful! Perhaps, I've detected and issue when there are some Aux Tracks (or different tracks than Audio Tracks) within the selected tracks. It seems like Strip Silence doesn't work on Aux Tracks.
My question is: Is there any way to skip the Aux Tracks or only apply the script on Audio Tracks when selected tracks contains different track types?
Besides, I've detected that if selected tracks are not all visible (I mean, all of selected tracks exceed the size of the screen) the script also crash. Y don't know if there is a way to make the script auto scroll down to be able to continue doing its stuff along all selected tracks.
Thanks so much in advance for your help guys!
- MMark Abrams @Mark_Abrams
Hi Alex!
Glad it has been useful! I can confirm that I have those issues too and will look into it. May be a minute, but asap!
Cheers,
Mark
- MMatt Cahill @Matt_Cahill
Hi Mark, was there any follow up on this? cheers
- MMark Abrams @Mark_Abrams
Hey @Matt_Cahill !
Apologies, I haven't had time to revisit it, but will try and work it into the schedule. I need to fix it for me as well!
- MMatt Cahill @Matt_Cahill
No worries, just thought it was worth the ask!
- FIn reply toMark_Abrams⬆:Forrester Savell @Forrester_Savell
Hey All (@alex_alcanjim , @Matt_Cahill )
I've had a go at modifying this script so that it deals with Aux tracks, folders or automation view on Audio Tracks. It should reselect only visible Audio Tracks and change their view to Waveform. So you can essentially blanket select any tracks (or your entire session from Clip List) and hopefully it will Strip Silence without errors. Thanks to @Chris_Shaw for the final puzzle piece. If you encounter any issues, reply here and I can have a go at helping fix them, although I'm far from expert.
Forrester
const { thresholdX, minimumDurationX, clipStartPadX, clipEndPadX, target, createFades } = event.props function setStripSilenceParameters(stripSilenceDlg) { let sliders = stripSilenceDlg.sliders const thresholdSlider = sliders[0]; const minDurationSlider = sliders[1]; const startPadSlider = sliders[2]; const endPadSlider = sliders[3]; thresholdSlider.mouseClickElement({ relativePosition: { "x": 0, "y": 2 }, }); thresholdSlider.mouseClickElement({ relativePosition: { "x": 220, "y": 2 }, }); thresholdSlider.mouseClickElement({ relativePosition: { "x": Number(thresholdX), "y": 2 }, }); minDurationSlider.mouseClickElement({ relativePosition: { "x": 0, "y": 2 }, }); minDurationSlider.mouseClickElement({ relativePosition: { "x": 220, "y": 2 }, }); minDurationSlider.mouseClickElement({ relativePosition: { "x": Number(minimumDurationX), "y": 2 }, }); startPadSlider.mouseClickElement({ relativePosition: { "x": 0, "y": 2 }, }); startPadSlider.mouseClickElement({ relativePosition: { "x": 220, "y": 2 }, }); startPadSlider.mouseClickElement({ relativePosition: { "x": Number(clipStartPadX), "y": 2 }, }); endPadSlider.mouseClickElement({ relativePosition: { "x": 0, "y": 2 }, }); endPadSlider.mouseClickElement({ relativePosition: { "x": 220, "y": 2 }, }); endPadSlider.mouseClickElement({ relativePosition: { "x": Number(clipEndPadX), "y": 2 }, }); } function clickStrip() { sf.ui.proTools.windows.whoseTitle.is("Strip Silence").first.buttons.whoseTitle.is("Strip").first.mouseClickElement(); } function stripTheSilence(trackHeader) { //Select track trackHeader.trackSelect(); //Scroll track into View trackHeader.trackScrollToView(); // Select All Clips In Track sf.keyboard.press({ keys: 'cmd+a' }); // Click Strip Button clickStrip() if (createFades === true) { // Create Fades On Clips sf.ui.proTools.menuClick({ menuPath: ["Edit", "Fades", "Create..."], }); sf.ui.proTools.windows.whoseTitle.is("Batch Fades").first.buttons.whoseTitle.is("OK").first.elementClick(); } } function scrollToTrackNamed(trackName, selectedTracks) { sf.ui.proTools.menuClick({ menuPath: ['Track', 'Scroll to Track...'] }); var confirmationDialogWin = sf.ui.proTools.confirmationDialog; confirmationDialogWin.elementWaitFor(); confirmationDialogWin.textFields.first.elementSetTextFieldWithAreaValue({ value: trackName }); confirmationDialogWin.buttons.whoseTitle.is('OK').first.elementClick(); confirmationDialogWin.elementWaitFor({ waitType: 'Disappear' }); //Re-select originally selected tracks sf.ui.proTools.trackSelectByName({ names: selectedTracks }) }; function main() { // Set Pro Tools frontmost sf.ui.proTools.appActivateMainWindow(); // if visible, hide floating windows const areFloatingWindowsVisible = sf.ui.proTools.getMenuItem('Window', 'Hide All Floating Windows').isEnabled if (areFloatingWindowsVisible) { sf.ui.proTools.menuClick({ menuPath: ['Window', 'Hide All Floating Windows'] }) }; // Reselect only visible Audio Tracks + change to Waveform // Get all selected track headers let allSelectedTrackHeaders = sf.ui.proTools.invalidate().trackGetSelectedTracks().trackHeaders; //Filter to get only visible audio tracks let allVisibleSelectedAudioTrackNames = allSelectedTrackHeaders.filter(t => t != null && t.title.value.includes("Audio Track")).map(t => t.normalizedTrackName); //Select only previously selected visible audio tracks sf.ui.proTools.trackSelectByName({ names: allVisibleSelectedAudioTrackNames, deselectOthers: true }); // Scroll to first selected Audio Track, so it can be changed to Waveform view scrollToTrackNamed(allVisibleSelectedAudioTrackNames[0], allVisibleSelectedAudioTrackNames); // Change all selected (Audio)tracks to Waveform sf.ui.proTools.selectedTrack.trackDisplaySelect({ displayPath: ["waveform"], selectForAllSelectedTracks: true }); //Refresh selected tracks sf.ui.proTools.mainWindow.invalidate(); const selectedTrackHeaders = sf.ui.proTools.selectedTracks.trackHeaders; // Declare stripSilenceWin Variable as Strip Silence Window let stripSilenceDlg = sf.ui.proTools.windows.whoseTitle.is("Strip Silence").first; let stripSilenceDlgOpen = false; if (stripSilenceDlg && stripSilenceDlg.exists) { //Strip Silence IS open stripSilenceDlgOpen = true; } else { //Strip Silence is NOT open // Open Strip Silence sf.ui.proTools.menuClick({ menuPath: ['Edit', 'Strip Silence'] }); } //Refresh the variable now that window is open stripSilenceDlg = sf.ui.proTools.windows.whoseTitle.is("Strip Silence").first; setStripSilenceParameters(stripSilenceDlg); if (target === "allAudio") { selectedTrackHeaders.forEach(trackHeader => { stripTheSilence(trackHeader) }); } else { clickStrip() if (createFades === true) { // Create Fades On Clips sf.ui.proTools.menuClick({ menuPath: ["Edit", "Fades", "Create..."], }); sf.ui.proTools.windows.whoseTitle.is("Batch Fades").first.buttons.whoseTitle.is("OK").first.elementClick(); } } // Wait for no modals sf.ui.proTools.waitForNoModals(); // Close Strip Silence if (!stripSilenceDlgOpen) sf.ui.proTools.viewCloseFocusedFloatingWindow(); // Reselect Audio Track Selection (shows which tracks were stripped) sf.ui.proTools.trackSelectByName({ names: allVisibleSelectedAudioTrackNames }); } main();
- PPhilip weinrobe @Philip_weinrobe
can't seem to get this to work.
keep getting this error.
any ideas?
14.06.2023 13:12:58.03 [Backend]: >> Command: Better Strip Silence Copy [user:cktj8p6a80003y610qt32zw39:clivyvy2v00006y10vcb4wk0i]
JavaScript error with InnerException: null
!! Command Error: Better Strip Silence Copy [user:cktj8p6a80003y610qt32zw39:clivyvy2v00006y10vcb4wk0i]:
TypeError: Cannot convert undefined or null to object
(Better Strip Silence Copy line 1)- PPhilip weinrobe @Philip_weinrobe
oh, it also seems to set all the values of my strip silence window to the farthest right! is this something i should be modifying in the script (put in my values?)
philip
- FForrester Savell @Forrester_Savell
Hey @Philip_weinrobe
Sorry I forgot to make it clear, but this code is to replace the code in Mark Abrams Strip Silence package (downloadable from the Store). I recommend making an 'Editable Copy' and replacing his code with the code below. You need the Command Templates for the script to run, which he has provided in his package.
Using those Command Templates, you can set the sliders for Strip Silence to whatever you like. I have a few presets for different "noise" levels I'm dealing with.
I can't guarantee the weird closing of the Strip Silence window won't happen, but I find I can avoid it if I simply move the window slightly from its original position first.
Here's my latest code that seems to be pretty solid
const { thresholdX, minimumDurationX, clipStartPadX, clipEndPadX, target, createFades } = event.props function setStripSilenceParameters(stripSilenceDlg) { let sliders = stripSilenceDlg.sliders const thresholdSlider = sliders[0]; const minDurationSlider = sliders[1]; const startPadSlider = sliders[2]; const endPadSlider = sliders[3]; thresholdSlider.mouseClickElement({ relativePosition: { "x": 0, "y": 2 }, }); thresholdSlider.mouseClickElement({ relativePosition: { "x": 220, "y": 2 }, }); thresholdSlider.mouseClickElement({ relativePosition: { "x": Number(thresholdX), "y": 2 }, }); minDurationSlider.mouseClickElement({ relativePosition: { "x": 0, "y": 2 }, }); minDurationSlider.mouseClickElement({ relativePosition: { "x": 220, "y": 2 }, }); minDurationSlider.mouseClickElement({ relativePosition: { "x": Number(minimumDurationX), "y": 2 }, }); startPadSlider.mouseClickElement({ relativePosition: { "x": 0, "y": 2 }, }); startPadSlider.mouseClickElement({ relativePosition: { "x": 220, "y": 2 }, }); startPadSlider.mouseClickElement({ relativePosition: { "x": Number(clipStartPadX), "y": 2 }, }); endPadSlider.mouseClickElement({ relativePosition: { "x": 0, "y": 2 }, }); endPadSlider.mouseClickElement({ relativePosition: { "x": 220, "y": 2 }, }); endPadSlider.mouseClickElement({ relativePosition: { "x": Number(clipEndPadX), "y": 2 }, }); } function clickStrip() { sf.ui.proTools.windows.whoseTitle.is("Strip Silence").first.buttons.whoseTitle.is("Strip").first.mouseClickElement(); } function stripTheSilence(trackHeader) { //Select track trackHeader.trackSelect(); //Scroll track into View trackHeader.trackScrollToView(); // Select All Clips In Track sf.keyboard.press({ keys: 'cmd+a' }); // Click Strip Button clickStrip() if (createFades === true) { // Create Fades On Clips sf.ui.proTools.menuClick({ menuPath: ["Edit", "Fades", "Create..."], }); sf.ui.proTools.windows.whoseTitle.is("Batch Fades").first.buttons.whoseTitle.is("OK").first.elementClick(); } } function scrollToTrackNamed(trackName, selectedTracks) { sf.ui.proTools.menuClick({ menuPath: ['Track', 'Scroll to Track...'] }); var confirmationDialogWin = sf.ui.proTools.confirmationDialog; confirmationDialogWin.elementWaitFor(); confirmationDialogWin.textFields.first.elementSetTextFieldWithAreaValue({ value: trackName }); confirmationDialogWin.buttons.whoseTitle.is('OK').first.elementClick(); confirmationDialogWin.elementWaitFor({ waitType: 'Disappear' }); //Re-select originally selected tracks sf.ui.proTools.trackSelectByName({ names: selectedTracks }) }; function main() { // Set Pro Tools frontmost sf.ui.proTools.appActivateMainWindow(); //Make sure Link Track and Edit Selection is enabled sf.ui.proTools.menuClick({ menuPath: ["Options", "Link Track and Edit Selection"], targetValue: "Enable" }); // if visible, hide floating windows const areFloatingWindowsVisible = sf.ui.proTools.getMenuItem('Window', 'Hide All Floating Windows').isEnabled if (areFloatingWindowsVisible) { sf.ui.proTools.menuClick({ menuPath: ['Window', 'Hide All Floating Windows'] }) }; // Reselect only visible Audio Tracks + change to Waveform // Get all selected track headers let allSelectedTrackHeaders = sf.ui.proTools.invalidate().trackGetSelectedTracks().trackHeaders; //Filter to get only visible audio tracks let allVisibleSelectedAudioTrackNames = allSelectedTrackHeaders.filter(t => t != null && t.title.value.includes("Audio Track")).map(t => t.normalizedTrackName); //Select only previously selected visible audio tracks sf.ui.proTools.trackSelectByName({ names: allVisibleSelectedAudioTrackNames, deselectOthers: true }); // Scroll to first selected Audio Track, so it can be changed to Waveform view scrollToTrackNamed(allVisibleSelectedAudioTrackNames[0], allVisibleSelectedAudioTrackNames); // Change all selected (Audio)tracks to Waveform sf.ui.proTools.selectedTrack.trackDisplaySelect({ displayPath: ["waveform"], selectForAllSelectedTracks: true }); //Refresh selected tracks sf.ui.proTools.mainWindow.invalidate(); const selectedTrackHeaders = sf.ui.proTools.selectedTracks.trackHeaders; // Declare stripSilenceWin Variable as Strip Silence Window let stripSilenceDlg = sf.ui.proTools.windows.whoseTitle.is("Strip Silence").first; let stripSilenceDlgOpen = false; if (stripSilenceDlg && stripSilenceDlg.exists) { //Strip Silence IS open stripSilenceDlgOpen = true; } else { //Strip Silence is NOT open // Open Strip Silence sf.ui.proTools.menuClick({ menuPath: ['Edit', 'Strip Silence'] }); } //Refresh the variable now that window is open stripSilenceDlg = sf.ui.proTools.windows.whoseTitle.is("Strip Silence").first; setStripSilenceParameters(stripSilenceDlg); if (target === "allAudio") { selectedTrackHeaders.forEach(trackHeader => { stripTheSilence(trackHeader) }); } else { clickStrip() if (createFades === true) { // Create Fades On Clips sf.ui.proTools.menuClick({ menuPath: ["Edit", "Fades", "Create..."], }); sf.ui.proTools.windows.whoseTitle.is("Batch Fades").first.buttons.whoseTitle.is("Fade Preset Toggle 2").first.elementClick; sf.ui.proTools.windows.whoseTitle.is("Batch Fades").first.buttons.whoseTitle.is("OK").first.elementClick(); } } // Wait for no modals sf.ui.proTools.waitForNoModals(); // Close Strip Silence if (!stripSilenceDlgOpen) sf.ui.proTools.viewCloseFocusedFloatingWindow(); // Reselect Audio Track Selection (shows which tracks were stripped) sf.ui.proTools.trackSelectByName({ names: allVisibleSelectedAudioTrackNames }); } main();
- VVanessa Garde @Vanessa_Garde
Is there any way to have it do it on selection, one track at a time, analysing each track individually (inside the selection)? Now it applies the same settings inside the selection, to all tracks (and I don't select "All Audio On Selected Tracks" since I don't want other regions/cues to apply the strip silence settings yet...)
Thanks!! :-)
- FForrester Savell @Forrester_Savell
It does appear that the 'Current Selection' target template doesn't behave as expected and could be more robust. TBH I have only used 'All Audio On Selected Tracks' which seems to work without any issues. I'll try to see if I can improve the 'Current Selection' option, but in the meantime, a quick solution would be to duplicate your playlists, apply the 'All Audio On Selected Tracks' process and then just copy the required stripped audio back to your preferred playlist.
Forrester
- RIn reply toMark_Abrams⬆:Rakel Pascual @Rakel_Pascual
Hey Mark!
Thank you very much for the Strip Silence Automation, is great!
Now, I wonder how I could adjust the Threshold, clip start pad and end pad to an specific number.
Lets say:
Threshold -41
Start Pad 70 ms
End Pad 123 msThank you very much!
- FForrester Savell @Forrester_Savell
@Rakel_Pascual see my reply to Philip above, you can use the Command Templates as presets and modify the sliders using those.
- PPhilip weinrobe @Philip_weinrobe
ah. this makes perfect sense.
so you experienced that weird minimizing issue as well?
and you solved it (mostly) by shifting the windows location?
that makes sense, it felt like a UI click issue somewhere...
- FIn reply toMark_Abrams⬆:Forrester Savell @Forrester_Savell
Hey all
I've spent a bit of time reworking this script to deal with most of the gremlins we've been experiencing. Due to the changes and addition of another Command Template, I've repackaged and uploaded to the Store as 'Improved Strip Silence'. Thanks again to @Mark_Abrams for the initial script that I've built upon.
If you run into any issues, please let me know over at the forum thread for the new package.Thanks
Forrester- BBrian Armstrong @Brian_Armstrong
Thank you @Forrester_Savell for this. In the package I've installed "Improved Strip Silence" I am still restricted to the preset values rather than being able to enter my own. Is that something that was supposed to be resolved? Having 256 msec as the smallest value is limiting for me when I'm trying to separate callouts from a loop group session. No matter how "sparse" I request them, they rapid fire yell one right after another. haha.
Thank you again for your help.
- FForrester Savell @Forrester_Savell
As the Strip Silence sliders in the PT window can't be entered as a numerical value, they can only be changed by clicking and dragging the sliders, SF is just clicking a relative position on the slider. So unfortunately, for the moment, they're just going to be preset values, rather than a number entry.
However, you can add whatever values you like to create your own presets, you just need to 'Make Editable Copy' of the Improved Strip Silence script. Once you do this you can edit the script to suit your needs.
In the Editor window there is a tab called Template, to the right of the Source tab. Inside that tab you can find the Property: Minimum Duration property. Below that you can see all the Minimum Duration values, and there is a button below the highest value that says '+Add'. To add values lower than 256ms, try adding another Enum Member by clicking +Add and using a Name/Value lower than 15. I don't know what the millisecond timings of these 1 -15 values will be but once you learn what the Name/Value corresponds to, you can add the time in the description.
You can add alternative values to any of the sliders you need using this method.
Hope that helps.
- MIn reply toMark_Abrams⬆:Mitch Lee @Mitch_Lee
Im getting this error alot of times...what am I doing wrong?
08.07.2024 10:41:49.49 [Backend]: !! Command Error: STRIP SILENCE [user:default:clybqnp920000bm10qrryrboo]:
Selected track header and track list item does not match. List Name: ''. Header Name: 'pickup 2 01' (STRIP SILENCE: Line 10)<< Command: STRIP SILENCE [user:default:clybqnp920000bm10qrryrboo]
Filip Killander @FilipKillander
That's happening to me as well! Have you found a solution for it yet? Works fine for me as long as I do 1 track at a time. But as soon as I try to do multiple tracks I get that same error as you.
- In reply toMitch_Lee⬆:
Filip Killander @FilipKillander
I found that I couldn't have the track- or clip list open while activating the script. And if I choose more tracks than fits on the screen it always runs in to issues. But stay clear of that and you're golden! 🥳
Currently looking for some kind of workaround for that last issue, but all and all it still saves me a lot of time!