No internet connection
  1. Home
  2. Packages
  3. Improved Strip Silence

Can Improved Strip Silence be Improved a bit more??? Custom value to enter?

By Jonathan Johnson @Jonathan_Johnson
    2025-02-17 18:13:02.761Z

    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=

    • 6 replies
    1. Chad Wahlbrink @Chad2025-02-17 23:49:52.534Z

      Hi @Jonathan_Johnson,

      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}` });
          }
      }
      
      1. FForrester Savell @Forrester_Savell
          2025-02-18 00:44:01.768Z

          Thanks @Chad, I will have a look into this when I have a spare moment.

          1. In reply toChad:
            JJonathan Johnson @Jonathan_Johnson
              2025-02-18 17:23:30.240Z

              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)

              1. 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.

            • F
              Forrester Savell @Forrester_Savell
                2025-03-20 20:28:41.518Z

                @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?

                1. Chad Wahlbrink @Chad2025-03-25 15:44:26.788Z

                  Excellent! This is great, @Forrester_Savell.