No internet connection
  1. Home
  2. How to

Delete all fades but only where there is a "separation" and not an actual edit

By AMPM101 @AMPM101
    2023-02-27 17:39:48.018Z2023-02-27 18:49:49.643Z

    This one is a real scripting zinger.

    I have a macro that deletes all fades and heals separation. Easy enough. But what I would really like is a macro that determines whether a fade is a separation or an actual edit, and if it is an edit then it leaves the original fade as-is -- if it is a separation, it deletes the fade and heals the separation.

    Note: I know how to batch create fades but I'm trying to keep the original fades where heal separation isn't healing a separation.

    A little context: I am a music editor and I often get AAFs from picture editors with cuts all over the music tracks. However, 80% of these aren't actual music edits -- they are inadvertent and unnecessary cuts made while they were editing the video. Nonetheless, a lot of picture editors will auto-apply fades across their music regions, which means the AAF I'm getting is riddled with "fake" fades/edits. So I end up going through each fade, one-by-one, deleting the fade and healing separation (which unites the clips again if it's not a true edit). When I come upon a clip in which the heal separation does not unite the clips, I know that this was an actual music edit performed by the picture editor, and I know to leave the fade alone for now.

    I'd like to automate this process for an entire selection.

    The psuedocode for the macro I'd like is something like this:

    const fades = selectAllFadesFromSelectionAndMakeArray()
    fades.forEach(fade => { 
       if (batch fade dialog is 'fade in' || 'fade out') {
           break
           } else {
           deletefade()
           healseparation()
           if (a cut still remains i.e. there are still two separate clips where fade once existed) {
              undo deletefade
           }
       }
    }
    

    I realize creating an array of fades and looping through them might be nearly impossible, and that determining whether a deleted fade leaves two clips or one might also be impossible, but I wanted to check in here. There might be other methods for achieving this as well -- like shift+tabbing through each object, determining whether it is a fade or a clip (is "delete fades" menu option available), if it is a fade then delete fade, etc etc

    Solved in post #7, click to view
    • 11 replies

    There are 11 replies. Estimated reading time: 12 minutes

    1. O

      Hey @AMPM101 seemed like a fun thing to give a whirl, here you go.

      /// Menu Click Items
      const deleteFade = () => sf.ui.proTools.menuClick({ menuPath: [`Edit`, `Fades`, `Delete`] })
      const healSeperation = () => sf.ui.proTools.menuClick({ menuPath: [`Edit`, `Heal Separation`] })
      const undoFadeDelete = () => sf.ui.proTools.menuClick({ menuPath: [`Edit`, `Undo Delete`] })
      
      /// Main Function
      function bulkHealFades() {
      
          deleteFade();
      
          if (!sf.ui.proTools.getMenuItem(`Edit`, `Heal Separation`).isEnabled) {
              undoFadeDelete();
          } else {
              healSeperation();
          }
      }
      
      // Do to all Clips
      sf.ui.proTools.clipDoForEachSelectedClip({
          action: bulkHealFades
      });
      

      SO this script is 89% there, there's at least one funky thing I've found that I'm not sure how to fix if there's not a FADE IN on the start of any of the clips the script will fail. Hoping someone can chime in suggesting an easy fix. Here it is in action.

      Ran it on a AAF piece of music, you were not kidding how many times a picture editor does that!

      Bests,
      Owen

      ONCE AGAIN : Script will Fail if there's no FADE IN on any of the clips selected.

      1. AAMPM101 @AMPM101
          2023-02-27 19:58:39.811Z2023-02-27 20:19:09.402Z

          Incredible! Such quick work!

          I'm gonna see if I can tackle the fade-in issue. Obviously the problem is that we're trying to undoFadeDelete when Undo Delete doesn't exist in the undo menu because you haven't deleted a fade (since a fade didn't exist). And it seems rather difficult to simply add a temporary fade-in and immediately delete it.

          The only other thing is I get an error upon completion saying it can't select next full clip inside selection.

          I'll try to work on it from here. Thanks again!

          1. Had an aHa! Pretty sure this fixes it :

            /// Menu Click Items
            const deleteFade = () => sf.ui.proTools.menuClick({ menuPath: [`Edit`, `Fades`, `Delete`] })
            const healSeperation = () => sf.ui.proTools.menuClick({ menuPath: [`Edit`, `Heal Separation`] })
            const undoFadeDelete = () => sf.ui.proTools.menuClick({ menuPath: [`Edit`, `Undo Delete`] })
            
            /// Main Function
            function bulkHealFades() {
            
                deleteFade();
            
                if (!sf.ui.proTools.getMenuItem(`Edit`, `Heal Separation`).isEnabled) {
                    if (sf.ui.proTools.getMenuItem(`Edit`, `Undo Delete`).exists) {
                        undoFadeDelete();
                    }
                } else {
                    healSeperation();
                }
            }
            
            // Do to all Clips
            sf.ui.proTools.clipDoForEachSelectedClip({
                action: bulkHealFades
            });
            
            1. AAMPM101 @AMPM101
                2023-02-27 22:12:40.258Z

                Yep I believe this works - my only hesitation with this is that I think if I had just deleted a separate fade prior to running this script, it will undo that action instead of proceeding as expected.

                1. Ha, yep, I imagine that would happen lol.

                  1. Updated with a hack. Edit Copy first :P

                    /// Menu Click Items
                    const deleteFade = () => sf.ui.proTools.menuClick({ menuPath: [`Edit`, `Fades`, `Delete`] })
                    const healSeperation = () => sf.ui.proTools.menuClick({ menuPath: [`Edit`, `Heal Separation`] })
                    const undoFadeDelete = () => sf.ui.proTools.menuClick({ menuPath: [`Edit`, `Undo Delete`] })
                    const copy = () => sf.ui.proTools.menuClick({ menuPath: [`Edit`, `Copy`] })
                    
                    /// For Each Clip Action
                    function bulkHealFades() {
                    
                        deleteFade();
                    
                        if (!sf.ui.proTools.getMenuItem(`Edit`, `Heal Separation`).isEnabled) {
                            if (sf.ui.proTools.getMenuItem(`Edit`, `Undo Delete`).exists) { undoFadeDelete() }
                        } else {
                            healSeperation();
                        }
                    }
                    
                    function main() {
                        // Hack to Clear the Undo
                        copy();
                        // Do to all Clips
                        sf.ui.proTools.clipDoForEachSelectedClip({
                            action: bulkHealFades
                        });
                    }
                    
                    main();
                    
                    Reply1 LikeSolution
                    1. AAMPM101 @AMPM101
                        2023-02-28 02:30:32.866Z

                        Yesss thank you so much, Owen!

                        1. Hey hey long time, I've been doing some music editing this week and built this quicky to help myself since I see a lot of times the editors are doing these moves to set vol automations. This is just the 'one off' button but I'm sure you could put it into the above package too. It's pretty nifty to not have to deal with the cilp gain auto after.

                          if (sf.ui.proTools.getMenuItem("Edit", "Fades", "Delete").exists) {
                          
                              sf.ui.proTools.menuClick({
                                  menuPath: ["Edit", "Fades", "Delete"],
                              });
                          
                              sf.keyboard.press({
                                  keys: "n",
                                  repetitions: 2,
                                  fast: true,
                              });
                          
                          }
                          
                          sf.ui.proTools.menuClick({
                              menuPath: ["Edit", "Heal Separation"],
                          });
                          
                          sf.ui.proTools.menuClick({
                              menuPath: ["Edit","Cut Special","Clip Gain"],
                          });
                          
                          sf.ui.proTools.clipGainCreateBoundaryBreakpoints();
                          

                          Take it for a spin, should be easy enough to drop it into the above script too.

                          1. OOwen Granich-Young @Owen_Granich_Young
                              2024-06-12 19:06:39.650Z2024-06-12 19:15:07.528Z

                              Of course as soon as I post this I go ... but it could be better.

                              /// Menu Click Items
                              const deleteFade = () => sf.ui.proTools.menuClick({ menuPath: [`Edit`, `Fades`, `Delete`] })
                              const healSeperation = () => sf.ui.proTools.menuClick({ menuPath: [`Edit`, `Heal Separation`] })
                              const undoFadeDelete = () => sf.ui.proTools.menuClick({ menuPath: [`Edit`, `Undo Delete`] })
                              const cutClipGain = () => sf.ui.proTools.menuClick({ menuPath: ["Edit", "Cut Special", "Clip Gain"], });
                              
                              /// Main Function
                              function tryToHeal() {
                              
                                  if (sf.ui.proTools.getMenuItem("Edit", "Fades", "Delete").exists) {
                              
                                      sf.ui.proTools.menuClick({
                                          menuPath: ["Edit", "Fades", "Delete"],
                                      });
                              
                                      sf.keyboard.press({
                                          keys: "n",
                                          repetitions: 2,
                                          fast: true,
                                      });
                              
                                  }
                              
                                  if (!sf.ui.proTools.getMenuItem(`Edit`, `Heal Separation`).isEnabled) {
                                      undoFadeDelete();
                                  } else {
                                      healSeperation();
                                      cutClipGain();
                                      sf.ui.proTools.clipGainCreateBoundaryBreakpoints();
                                  }
                              }
                              
                              tryToHeal()
                              
                              1. Chris Shaw @Chris_Shaw2024-06-12 19:46:19.072Z2024-06-12 20:35:56.117Z

                                This is pretty cool.
                                The only thing I noticed is that you declare but never use the deleteFade() function.

                                Replace lines 12-14 with it.

                                You should also put lines 2-5 inside the tryToHeal() function so that it's all self contained and re-useable (assuming that this wasn't copied from a much larger script).

                                To make it more towards @Kitch 's concept of reading a script like a table of contents I refactored it more:

                                function tryToHeal() {
                                    /// Menu Click Items
                                    const deleteFades = () => sf.ui.proTools.menuClick({ menuPath: [`Edit`, `Fades`, `Delete`] })
                                    const healSeperation = () => sf.ui.proTools.menuClick({ menuPath: [`Edit`, `Heal Separation`] })
                                    const undoFadeDelete = () => sf.ui.proTools.menuClick({ menuPath: [`Edit`, `Undo Delete`] })
                                    const cutClipGain = () => sf.ui.proTools.menuClick({ menuPath: ["Edit", "Cut Special", "Clip Gain"], });
                                
                                    // Get menu states
                                    const fadesExist = sf.ui.proTools.getMenuItem("Edit", "Fades", "Delete").exists;
                                    const cantHealSeparation = () => !sf.ui.proTools.getMenuItem(`Edit`, `Heal Separation`).isEnabled;
                                
                                    function refreshPtMenus() { sf.keyboard.press({ keys: "n", repetitions: 2, fast: true, }) }
                                
                                    // Main 
                                    if (fadesExist) {
                                        deleteFades()
                                        refreshPtMenus()
                                    }
                                
                                    if (cantHealSeparation()) {
                                        undoFadeDelete();
                                    } else {
                                        healSeperation();
                                        cutClipGain();
                                        sf.ui.proTools.clipGainCreateBoundaryBreakpoints();
                                    }
                                }
                                
                                tryToHeal()
                                
                                1. OOwen Granich-Young @Owen_Granich_Young
                                    2024-06-12 20:27:25.731Z2024-06-12 20:35:09.788Z

                                    haha good catch, i was just moving fast and comping the two scripts together lol.

                                    although I'm not sure you can get the menu state on heal separation at the beginning, you might have to get it after delete fades... ohhhhh i see you made it a active one there COOOOOOL Never thought of that.