Can Improved Strip Silence be Improved a bit more??? Custom value to enter?
Title
Can Improved Strip Silence be Improves a bit more??? Custom value to enter?
What do you expect to happen when you run the script/macro?
This is a great script, However, What if I need to change the values?
The Threshold option pre set closest to what I want is here is -40. What if I needed the template to be edited to -39?
Could this be modified to allow custom numbers?
Are you seeing an error?
What happens when you run this script?
it works Great, Bt want to update it for more user joy
How were you running this script?
I used a Stream Deck button
How important is this issue to you?
4
Details
{ "inputExpected": "This is a great script, However, What if I need to change the values?\n\nThe Threshold option pre set closest to what I want is here is -40. What if I needed the template to be edited to -39? \n\nCould this be modified to allow custom numbers?", "inputIsError": false, "inputWhatHappens": "it works Great, Bt want to update it for more user joy", "inputHowRun": { "key": "-MpfwmPg-2Sb-HxHQAff", "title": "I used a Stream Deck button" }, "inputImportance": 4, "inputTitle": "Can Improved Strip Silence be Improves a bit more??? Custom value to enter? " }
Source
const { thresholdX, minimumDurationX, clipStartPadX, clipEndPadX, target, createFades, batchFadePreset } = 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 moveWindow({ window }) {
const screenFrame = window.windowGetScreen().screen.visibleFrame;
const windowFrame = window.frame;
window.windowMove({
position: {
x: screenFrame.x + ((screenFrame.w - windowFrame.w) / 1.5),
y: screenFrame.y + ((screenFrame.h - windowFrame.h) / 2),
}
});
}
function selectVisibleAudioTracks() {
////////// Reselect only visible Audio Tracks + change to Waveform
// Get all selected track headers
let allSelectedTrackHeaders = sf.ui.proTools.invalidate().trackGetSelectedTracks().trackHeaders;
//log(allSelectedTrackHeaders[0]);
//Filter to get only visible audio tracks
const 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
});
return allVisibleSelectedAudioTrackNames
}
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();
if (target === "allAudio") {
// Select All Clips In Track
sf.keyboard.press({
keys: 'cmd+a'
});
}
// Click Strip Button
clickStrip()
}
function batchFade() {
// Create Fades On Clips on all selected stripped tracks
sf.ui.proTools.menuClick({
menuPath: ["Edit", "Fades", "Create..."],
});
if (sf.ui.proTools.windows.whoseTitle.is("Crossfade").first.exists) {
sf.ui.proTools.windows.whoseTitle.is("Crossfade").first.buttons
.whoseTitle.is("Cancel").first.elementClick();
sf.ui.proTools.windows.whoseTitle.is("Crossfade").first.elementWaitFor({
waitType: "Disappear"
});
};
if (sf.ui.proTools.windows.whoseTitle.is("Batch Fades").first.buttons
.whoseTitle.is("OK").first.exists) {
//Select Batch Fade Preset based on Commmand template selection
sf.ui.proTools.windows.whoseTitle.is("Batch Fades").first.buttons
.whoseTitle.contains('Fade Preset Toggle')
.allItems[Number(batchFadePreset)].elementClick();
sf.ui.proTools.windows.whoseTitle.is("Batch Fades").first.buttons
.whoseTitle.is("OK").first.elementClick();
if (sf.ui.proTools.confirmationDialog.invalidate().buttons
.whoseTitle.is('Adjust To Fit').first.exists) {
sf.ui.proTools.confirmationDialog.buttons
.whoseTitle.is('Adjust To Fit').first.elementClick();
sf.ui.proTools.confirmationDialog.elementWaitFor({
waitType: "Disappear", onError: "Continue"
});
}
}
}
function scrollToTrackNamed(trackName, selectedTracks) {
sf.ui.proTools.menuClick({ menuPath: ['Track', 'Scroll to Track...'] });
let 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 prepStripSilence() {
// 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']
});
}
return stripSilenceDlgOpen
}
function main() {
// Set Pro Tools frontmost
sf.ui.proTools.appActivateMainWindow();
//Make sure Link Track and Edit Selection is enabled, save the setting for recall later
let wasLinked = sf.ui.proTools.getMenuItem('Options', 'Link Track and Edit Selection').isMenuChecked;
if (!wasLinked) {
sf.ui.proTools.menuClick({
menuPath: ["Options", "Link Track and Edit Selection"],
});
}
// 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']
})
};
//if target is current selection and no audio is selected, throw error
let lengthNumber = +sf.ui.proTools.selectionGet().selectionLength.replace(/[ :\+\|.]/g, '')
if (target === "currentSelection" && lengthNumber === 0) {
sf.interaction.displayDialog({
prompt: 'This preset requires an audio selection',
giveUpAfterSeconds: 2
});
//log("No Audio Selected");
throw 0;
}
//Select only visible Audio Tracks
const allVisibleSelectedAudioTrackNames = selectVisibleAudioTracks();
//Refresh selected tracks
sf.ui.proTools.mainWindow.invalidate();
const selectedTrackHeaders = sf.ui.proTools.selectedTracks.trackHeaders;
const stripSilenceDlgOpen = prepStripSilence();
//Refresh the variable now that window is open
const stripSilenceDlg = sf.ui.proTools.windows.whoseTitle.is("Strip Silence").first;
//Move Strip Silence window to overcome the window minimizing bug
moveWindow({
window: stripSilenceDlg,
});
//Set the strip silence parameters based on Command template preset
setStripSilenceParameters(stripSilenceDlg);
//Strip Either All Audio or Selected Audio based on Command Template pref
selectedTrackHeaders.forEach(trackHeader => {
stripTheSilence(trackHeader)
});
// 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,
});
if (createFades === true) {
batchFade()
}
if (!wasLinked) {
sf.ui.proTools.menuClick({
menuPath: ["Options", "Link Track and Edit Selection"],
});
}
}
main();
Links
User UID: nd1Ljv8IdvcMPlWQRihpRZT19jG2
Feedback Key: sffeedback:nd1Ljv8IdvcMPlWQRihpRZT19jG2:-OJK6GLYbWr47DbqxVxX
Feedback ZIP: p9DRhowRNFbQejaD0wRbURUSrerjWQyY7pBTLIZo8YWLhIiw/bMFYv3LzFqLf+hvBMuD3eq12cY9mrCOcLGbJCnY203JNGjFK1QQZu96ZGrUyqNI1VSsZnIInkeaebg8Q9WyKDq809j2fgCJZJbLXSzRMY59ZFwg/sT2peP9DnS4thUsCdW3lhalH3MdLBbVfF8xHX8PAKfgVYXwPBXwt6Nuax0lRV1FL21M91D8CApRxQQl/l5bNxQ2/wwhzzpDyICXRmY+4QdtWwpX0p3Jowr+3l/sprthDL5nAH8YLZlhX5lkPDrXJIvjU0u3EUbr5TacT4I6a84pObDmiGPEQ/sHnXMaf1gdHDmlxqPTjdQ=
- Chad Wahlbrink @Chad2025-02-17 23:49:52.534Z
Am I right that you are using @Forrester_Savell's Improved Strip Silence package?
If so, I may move this to the package forum for that package so Forrester can take a look.
Regardless, I took a stab at being able to set custom values and it does seem possible.
This is a bit of a hack, but it works.
Forrester, feel free to incorporate this if it interests you – no pressure.
setThreshold(-39); setMinStripDuration(2025); setClipStartPad(15); setClipEndPad(15); ///////// function setThreshold(amount) { // First Slider let slider = sf.ui.proTools.windows.whoseTitle.is("Strip Silence").first.sliders.whoseTitle.is("Slider").first; // First Text Value let staticText = sf.ui.proTools.windows.whoseTitle.is("Strip Silence").first.children.whoseRole.is("AXStaticText").allItems[1]; // 97 possible values (96 values and 0) let possibleValues = 97 // Positive Value for how far the mouse should travel would be the threshold + 97 let absoluteValueOfStripThreshold = amount + possibleValues; // Get the Range of Pixel Value of 1 Position Increment Along the slider's frame's width let range = possibleValues / slider.frame.w; // Jump to the Closest Value using the position of the slider and adding (possible values / width of the frame - 226 in this case) sf.mouse.click({ position: { x: slider.position.x + (absoluteValueOfStripThreshold / range), y: slider.position.y } }) let currentSetting = Number(staticText.invalidate().value.value.split(" dB")[0]); let incrementDecrement = currentSetting > amount ? "AXDecrement" : "AXIncrement"; // Repeat Increment until we reach the desired threshold while (Number(staticText.invalidate().value.value.split(" dB")[0]) !== amount) { // Drag from current position to incremented position for (let i = 0; i < 5; i++) { slider.elementClick({ actionName: `${incrementDecrement}` }) } } } function setMinStripDuration(amount) { let slider = sf.ui.proTools.windows.whoseTitle.is("Strip Silence").first.sliders.whoseTitle.is("Slider").allItems[1]; let staticText = sf.ui.proTools.windows.whoseTitle.is("Strip Silence").first.children.whoseRole.is("AXStaticText").allItems[3]; // 4001 possible values (4001 values and 0) let possibleValues = 4001; // Get the Range of Pixel Value of 1 Position Increment Along the slider's frame's width let range = possibleValues / slider.frame.w; // Jump to the Closest Value using the position of the slider and adding (possible values / width of the frame - 226 in this case) sf.mouse.click({ position: { x: slider.position.x + (amount / range), y: slider.position.y } }) // Get the Current Setting let currentSetting = Number(staticText.invalidate().value.value.split(" msec")[0]); let incrementDecrement = currentSetting > amount ? "AXDecrement" : "AXIncrement"; while (Number(staticText.invalidate().value.value.split(" msec")[0]) !== amount) { // Drag from current position to incremented position slider.elementClick({ actionName: `${incrementDecrement}` }); } } function setClipStartPad(amount) { let slider = sf.ui.proTools.windows.whoseTitle.is("Strip Silence").first.sliders.whoseTitle.is("Slider").allItems[2]; let staticText = sf.ui.proTools.windows.whoseTitle.is("Strip Silence").first.children.whoseRole.is("AXStaticText").allItems[5]; // 4001 possible values (4001 values and 0) let possibleValues = 4001; // Get the Range of Pixel Value of 1 Position Increment Along the slider's frame's width let range = possibleValues / slider.frame.w; // Jump to the Closest Value using the position of the slider and adding (possible values / width of the frame - 226 in this case) sf.mouse.click({ position: { x: slider.position.x + (amount / range), y: slider.position.y } }) let currentSetting = Number(staticText.invalidate().value.value.split(" msec")[0]); let incrementDecrement = currentSetting > amount ? "AXDecrement" : "AXIncrement"; while (Number(staticText.invalidate().value.value.split(" msec")[0]) !== amount) { // Drag from current position to incremented position slider.elementClick({ actionName: `${incrementDecrement}` }); } } function setClipEndPad(amount) { let slider = sf.ui.proTools.windows.whoseTitle.is("Strip Silence").first.sliders.whoseTitle.is("Slider").allItems[3]; let staticText = sf.ui.proTools.windows.whoseTitle.is("Strip Silence").first.children.whoseRole.is("AXStaticText").allItems[7]; // 4001 possible values (4001 values and 0) let possibleValues = 4001; // Get the Range of Pixel Value of 1 Position Increment Along the slider's frame's width let range = possibleValues / slider.frame.w; // Jump to the Closest Value using the position of the slider and adding (possible values / width of the frame - 226 in this case) sf.mouse.click({ position: { x: slider.position.x + (amount / range), y: slider.position.y } }) let currentSetting = Number(staticText.invalidate().value.value.split(" msec")[0]); let incrementDecrement = currentSetting > amount ? "AXDecrement" : "AXIncrement"; while (Number(staticText.invalidate().value.value.split(" msec")[0]) !== amount) { // Drag from current position to incremented position slider.elementClick({ actionName: `${incrementDecrement}` }); } }
- FForrester Savell @Forrester_Savell
Thanks @Chad, I will have a look into this when I have a spare moment.
- In reply toChad⬆:JJonathan Johnson @Jonathan_Johnson
Yes, That is right it is from @Forrester_Sacell's Improved Strip Silence package, Sorry should have described it better....
Thanks So Much! However when I now go to run this it get this error:
~Strip Silence modified Failed
TypeError: Cannot read property 'w' of null (~Strip Silence modified line 22)Chad Wahlbrink @Chad2025-02-18 17:29:11.934Z
Hi, @Jonathan_Johnson,
The script I provided only contains the code to set custom settings for the Strip Silence window. If the Strip Silence window is closed, and you run my script alone, it will throw errors. If you open the Strip Silence window and run the script I shared, it should set the following settings:
Strip Threshold: -39 dB Min Strip Duration: 2025 msec Clip Start Pad: 15 msec Clip End Pad: 15 msec
I mainly provided that script as a "proof of concept" that Forrester can consider.
For now, I will move this thread to the package forum for Forrester's package so he can take it from here.
- FIn reply toJonathan_Johnson⬆:Forrester Savell @Forrester_Savell
@Jonathan_Johnson @Chad
Its been a busy month, but I've updated the Improved Strip Silence script with your custom code plus a few extra tweaks.
Should be able to enter precise slider values into the presets now.
If you get a chance, check it out and let me know if its working for you?Chad Wahlbrink @Chad2025-03-25 15:44:26.788Z
Excellent! This is great, @Forrester_Savell.