No internet connection
  1. Home
  2. Script Sharing

Ultimate Vocal Remover in Pro Tools

By Brandon Jiaconia @Brandon_Jiaconia
    2024-09-11 22:23:44.068Z

    This script uses a python package called audio-separator (https://pypi.org/project/audio-separator/) that can use UVR via the command line. Thanks to @Kitch and @Chris_Shaw for helping me figure out the interleaved section!

    sf.ui.proTools.appActivateMainWindow();
    
    // Set Pro Tools session to interleaved
    sf.app.proTools.setSessionInterleavedState({interleavedState:true});
    
    // Consolidate the selected clip in Pro Tools
    sf.ui.proTools.menuClick({ menuPath: ['Edit', 'Consolidate Clip'], });
    
    // Wait for Modals
    sf.ui.proTools.waitForNoModals();
    
    // Invalidate PT API
    sf.app.proTools.invalidate();
    
    // Get the path of the selected file in Pro Tools
    var fullPath = sf.app.proTools.getFileLocation({
        fileFilters: ['SelectedClipsTimeline'],
    }).fileLocations[0].path;
    
    // Set Pro Tools session to interleaved state to false
    sf.app.proTools.setSessionInterleavedState({interleavedState:false});
    
    // Get the directory of the selected file
    var directoryPath = fullPath.substring(0, fullPath.lastIndexOf('/'));
    
    // Compile File Name
    var fileName = fullPath.substring(fullPath.lastIndexOf('/') + 1, fullPath.length - 4); // Assumes the file has a 3-character extension
    
    //Path To Processed file
    var pathToAudioFiles = `${directoryPath}/${fileName}_(Vocals)_UVR-MDX-NET-Inst_HQ_4.wav`;
    
    // Command line
    sf.system.exec({
        commandLine: `PATH=/opt/homebrew/bin:$PATH /opt/homebrew/bin/audio-separator "${fullPath}" --model_filename "UVR-MDX-NET-Inst_HQ_4.onnx" --output_dir "${directoryPath}" --output_format=WAV`
    });
    //Copy the file to the clipboard
    sf.file.copyToClipboard({ path: pathToAudioFiles });
    sf.ui.proTools.spotFileFromClipboard();
    

    My next step is to make this into a template and add all of the models.

    • 9 replies
    1. Kitch Membery @Kitch2024-09-11 22:41:16.648Z

      Awesome @Brandon_Jiaconia!

      It would be great to see this transformed into a package and shared on the SoundFlow Store after you have converted it into a Command Template.

      Great hangin' with you and the crew in the Zoom session this morning!

      1. D
        AK @DJAK
          2025-11-05 04:13:28.789Z

          Hey @Brandon_Jiaconia Can you let me know if this script still works and how exactly does it work? I use UVR daily so this would be a huge help. I tried your script but all it seems to do is consolidate the selected clip. Is there something I need to install or edit in the script? Also, how does it know if you want to make it an acapella or instrumental? Thanks!

          1. BBrandon Jiaconia @Brandon_Jiaconia
              2025-11-05 15:38:15.618Z

              Hey - Yes this still works. I use it often to extract a voice over or music from a clip in Pro Tools. The current script is set up to make an instrumental and vocal of the selected file in Pro Tools. It is a workaround of a workaround, so the setup is a little complicated.
              To start you need to install audio-separator on your computer. There are instructions on their site
              https://pypi.org/project/audio-separator/.
              For me this is done with a terminal command like 'pip install audio-separator'. Once it finishes, confirm in terminal with 'which audio-separator'. It will return a path like "/opt/homebrew/Caskroom/miniforge/base/bin/audio-separator" You will need this path in your script - Here is the updated script I use, you'll need to change a few things specific to where audio-separator gets installed on your computer:

              sf.ui.proTools.appActivateMainWindow();
              
              //Selection
              const selection = sf.ui.proTools.selectionGet();
              const timecodeIn = `${selection.selectionStart}`;
              
              // Set Pro Tools session to interleaved
              sf.app.proTools.setSessionInterleavedState({ interleavedState: true });
              
              // Consolidate the selected clip in Pro Tools
              sf.ui.proTools.menuClick({ menuPath: ['Edit', 'Consolidate Clip'] });
              sf.ui.proTools.waitForNoModals();
              
              sf.app.proTools.invalidate();
              
              // Get the path of the selected file in Pro Tools
              var fullPath = sf.app.proTools.getFileLocation({
              	fileFilters: ['SelectedClipsTimeline'],
              }).fileLocations[0].path;
              
              
              // Build paths
              var directoryPath = fullPath.substring(0, fullPath.lastIndexOf('/'));
              var fileName = fullPath.substring(fullPath.lastIndexOf('/') + 1, fullPath.length - 4);
              fileName = fileName.replace(/\.L|\.R$/, '');
              
              // Disable interleaved again
              sf.app.proTools.setSessionInterleavedState({ interleavedState: false });
              
              
              // Output files expected by UVR naming
              var vocalFile = `${directoryPath}/${fileName}_(Vocals)_UVR-MDX-NET-Inst_HQ_4.wav`;
              var instrumentalFile = `${directoryPath}/${fileName}_(Instrumental)_UVR-MDX-NET-Inst_HQ_4.wav`;
              
              // command line
              sf.system.exec({
                  commandLine: `PATH="/opt/homebrew/bin:/opt/homebrew/sbin:$PATH"; \
              /opt/homebrew/Caskroom/miniforge/base/bin/audio-separator \
              "${fullPath}" \
              --model_filename UVR-MDX-NET-Inst_HQ_4.onnx \
              --output_dir "${directoryPath}" \
              --output_format WAV`
              });
              
              //Destination Tracks
               sf.app.proTools.selectTracksByName({
                      trackNames: ["Dial 7"],
                  });
              
              // Copy the file to the clipboard
              sf.file.copyToClipboard({ path: vocalFile });
              sf.ui.proTools.spotFileFromClipboard();
              sf.ui.proTools.waitForNoModals();
              
               sf.app.proTools.selectTracksByName({
                      trackNames: ["Music_10"],
                  });
              
              // Copy the file to the clipboard
              sf.file.copyToClipboard({ path: instrumentalFile });
              sf.ui.proTools.spotFileFromClipboard();
              sf.ui.proTools.waitForNoModals();    
              

              Now in this section you need to change the script to work with your install location:

              // command line
              sf.system.exec({
                  commandLine: `PATH="/opt/homebrew/bin:/opt/homebrew/sbin:$PATH"; \
              /opt/homebrew/Caskroom/miniforge/base/bin/audio-separator \
              "${fullPath}" \
              --model_filename UVR-MDX-NET-Inst_HQ_4.onnx \
              --output_dir "${directoryPath}" \
              --output_format WAV`
              });
              

              You need to swap my install path "/opt/homebrew/Caskroom/miniforge/base/bin/audio-separator " with the install location that was returned when you entered 'which audio-separator' in terminal.

              I have this setup up to work with my template, so you will need to change the names of these destination tracks to something that works in your session, in my case here the tracks are named Dial 7 and Music_10, these both need to be stereo tracks!

              //Destination Tracks
               sf.app.proTools.selectTracksByName({
                      trackNames: ["Dial 7"],
                  });
              
              // Copy the file to the clipboard
              sf.file.copyToClipboard({ path: vocalFile });
              sf.ui.proTools.spotFileFromClipboard();
              sf.ui.proTools.waitForNoModals();
              
               sf.app.proTools.selectTracksByName({
                      trackNames: ["Music_10"],
                  });
              
            • D
              AK @DJAK
                2025-11-05 16:37:55.575Z

                Thanks for the break down. I'm not able to download audio separator for some reason. maybe it's my Mac OSX version or M1 processor or something. This is what i'm getting when trying to install:

                djak@DJ-AKs-MacBook-Pro ~ % pip install audio-separator
                DEPRECATION: Python 2.7 reached the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 is no longer maintained. pip 21.0 will drop support for Python 2.7 in January 2021. More details about Python 2 support in pip can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support pip 21.0 will remove support for this functionality.
                ERROR: Could not find a version that satisfies the requirement audio-separator (from versions: none)
                ERROR: No matching distribution found for audio-separator
                djak@DJ-AKs-MacBook-Pro ~ % pip install "audio-separator[cpu]"
                DEPRECATION: Python 2.7 reached the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 is no longer maintained. pip 21.0 will drop support for Python 2.7 in January 2021. More details about Python 2 support in pip can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support pip 21.0 will remove support for this functionality.
                ERROR: Could not find a version that satisfies the requirement audio-separator[cpu] (from versions: none)
                ERROR: No matching distribution found for audio-separator[cpu]
                djak@DJ-AKs-MacBook-Pro ~ % pip install audio-separator
                DEPRECATION: Python 2.7 reached the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 is no longer maintained. pip 21.0 will drop support for Python 2.7 in January 2021. More details about Python 2 support in pip can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support pip 21.0 will remove support for this functionality.
                ERROR: Could not find a version that satisfies the requirement audio-separator (from versions: none)
                ERROR: No matching distribution found for audio-separator
                djak@DJ-AKs-MacBook-Pro ~ %

                tried both: pip install "audio-separator[cpu]" and pip install audio-separator

                I have the latest python installed as well 3.14

                Did I need to install anything else? I'm using Terminal.

                1. BBrandon Jiaconia @Brandon_Jiaconia
                    2025-11-05 16:53:18.422Z

                    Try directly using the updated python version in your terminal command
                    python3 -m pip install "audio-separator[cpu]"
                    or
                    pip3 install "audio-separator[cpu]"

                    When I first set this up I was using an M1, so should be all good

                  • D
                    AK @DJAK
                      2025-11-05 17:34:16.285Z

                      Was able to get Terminal to use python3 instead of the built in version but now stuck at this error:

                      Additionally, some packages in these conflicts have no matching distributions available for your environment:
                      onnxruntime
                      onnxruntime-silicon

                      To fix this you could try to:

                      1. loosen the range of package versions you've specified
                      2. remove package versions to allow pip to attempt to solve the dependency conflict

                      ERROR: ResolutionImpossible: for help visit https://pip.pypa.io/en/latest/topics/dependency-resolution/#dealing-with-dependency-conflicts

                      I'm guessing this is preventing audio separator from installing, because when I enter "'which audio-separator'" I get this: zsh: command not found: which audio-separator

                      Would you be able to do a youtube or post on the forum (if its allowed) where you create a guide or show how to get everything setup? If you have the time of course.

                      But using UVR with pro-tools will be a huge game-changer for alot of us. Currently, I use a soundflow script to create a copy of the clip to my desktop. Then I open UVR, drag the file in, select vocals or instrumental and process it. Then I drag the processed file back into pro-tools and continue working.

                      1. BBrandon Jiaconia @Brandon_Jiaconia
                          2025-11-05 18:31:04.760Z

                          The problem is I'm not a python or terminal expert at all ! So I dont know if a video would actually be very helpful or accurate for everybody. I have set this up on a few computers, and it's always a little specific to that computer and python setup. On some I've had to create a virtual environment and install python/audio-sep fresh in that location. On others it was much easier by following the terminal steps I outlined above. I can look at expanding the script to include all the models and making this more user friendly
                          That said I think whats going on in your case is a mismatch between a newer version of python and an older version of onnxruntime, but again I'm not a python expert !

                          1. DAK @DJAK
                              2025-11-05 18:45:08.361Z

                              Yes, looking further, It seems the onnxruntime doesn't work past python V3.9 and I'm on the latest 3.14.

                              I installed 3.9 and attempted the reinstall via Terminal and this version threw tons of red errors lol. I will stop now before I mess something up in my system and not be able to work 😂

                              1. BBrandon Jiaconia @Brandon_Jiaconia
                                  2025-11-05 22:16:58.555Z

                                  Here is a reformatted script that incorporates all the MDX models.

                                  // Path To Audio Separator
                                  const separatorPath = "/Users/bj018/audio-sep-env/bin/audio-separator";
                                  
                                  // MDX model list
                                  var modelFiles = [
                                      "UVR-MDX-NET-Inst_HQ_1.onnx",
                                      "UVR-MDX-NET-Inst_HQ_2.onnx",
                                      "UVR-MDX-NET-Inst_HQ_3.onnx",
                                      "UVR-MDX-NET-Inst_HQ_4.onnx",
                                      "UVR-MDX-NET-Inst_HQ_5.onnx",
                                      "UVR_MDXNET_Main.onnx",
                                      "UVR-MDX-NET-Inst_Main.onnx",
                                      "UVR_MDXNET_1_9703.onnx",
                                      "UVR_MDXNET_2_9682.onnx",
                                      "UVR_MDXNET_3_9662.onnx",
                                      "UVR-MDX-NET-Inst_1.onnx",
                                      "UVR-MDX-NET-Inst_2.onnx",
                                      "UVR-MDX-NET-Inst_3.onnx",
                                      "UVR_MDXNET_KARA.onnx",
                                      "UVR_MDXNET_KARA_2.onnx",
                                      "UVR_MDXNET_9482.onnx",
                                      "UVR-MDX-NET-Voc_FT.onnx",
                                      "Kim_Vocal_1.onnx",
                                      "Kim_Vocal_2.onnx",
                                      "Kim_Inst.onnx",
                                      "Reverb_HQ_By_FoxJoy.onnx",
                                      "UVR-MDX-NET_Crowd_HQ_1.onnx",
                                      "kuielab_a_vocals.onnx",
                                      "kuielab_a_other.onnx",
                                      "kuielab_a_bass.onnx",
                                      "kuielab_a_drums.onnx",
                                      "kuielab_b_vocals.onnx",
                                      "kuielab_b_other.onnx",
                                      "kuielab_b_bass.onnx",
                                      "kuielab_b_drums.onnx",
                                      "UVR-MDX-NET_Main_340.onnx",
                                      "UVR-MDX-NET_Main_390.onnx",
                                      "UVR-MDX-NET_Main_406.onnx",
                                      "UVR-MDX-NET_Main_427.onnx",
                                      "UVR-MDX-NET_Main_438.onnx",
                                      "UVR-MDX-NET_Inst_82_beta.onnx",
                                      "UVR-MDX-NET_Inst_90_beta.onnx",
                                      "UVR-MDX-NET_Inst_187_beta.onnx",
                                      "UVR-MDX-NET-Inst_full_292.onnx"
                                  ];
                                  // Custom stem names for certain models
                                  const stemOverrides = {
                                      "Reverb_HQ_By_FoxJoy": ["(No Reverb)", "(Reverb)"],
                                      "UVR-MDX-NET_Crowd_HQ_1": ["(No Crowd)", "(Crowd)"],
                                      "kuielab_a_other": ["(No Other)", "(Other)"],
                                      "kuielab_a_bass": ["(No Bass)", "(Bass)"],
                                      "kuielab_a_drums": ["(No Drums)", "(Drums)"],
                                      "kuielab_b_other": ["(No Other)", "(Other)"],
                                      "kuielab_b_bass": ["(No Bass)", "(Bass)"],
                                      "kuielab_b_drums": ["(No Drums)", "(Drums)"]
                                  };
                                  
                                  
                                  // pop up[ search
                                  var modelChoice = sf.interaction.popupSearch({
                                      title: "Choose MDX Model",
                                      items: modelFiles.map(filename => ({
                                          name: filename.replace(/\.onnx$/, ''),
                                          value: filename      
                                      }))
                                  }).item;
                                  
                                  // Model Variables
                                  var selectedModelWithExt = modelChoice.value; 
                                  var modelNameNoExt = modelChoice.name;
                                  
                                  //Get the selections in & out points.
                                  const selection = sf.ui.proTools.selectionGet();
                                  
                                  // Set Pro Tools session to interleaved
                                  sf.app.proTools.setSessionInterleavedState({ interleavedState: true });
                                  
                                  // Consolidate the target clip in Pro Tools
                                  sf.ui.proTools.menuClick({ menuPath: ['Edit', 'Consolidate Clip'] });
                                  sf.ui.proTools.waitForNoModals();
                                  
                                  // Invalidate PT API
                                  sf.app.proTools.invalidate();
                                  
                                  // Get the path of the target file in Pro Tools
                                  var fullPath = sf.app.proTools.getFileLocation({
                                      fileFilters: ['SelectedClipsTimeline'],
                                  }).fileLocations[0].path;
                                  
                                  // Set Pro Tools session to interleaved state to false
                                  sf.app.proTools.setSessionInterleavedState({ interleavedState: false });
                                  
                                  // Get the directory of the target file
                                  var directoryPath = fullPath.substring(0, fullPath.lastIndexOf('/'));
                                  
                                  // Compile File Name without .L or .R suffix
                                  var fileName = fullPath.substring(fullPath.lastIndexOf('/') + 1, fullPath.length - 4); // Assumes the file has a 3-character extension
                                  fileName = fileName.replace(/\.L|\.R$/, ''); // Remove .L or .R from the filename
                                  
                                  // Processed files
                                  const [stem1, stem2] = stemOverrides[modelNameNoExt] || ["(Vocals)", "(Instrumental)"];
                                  var vocalFile = `${directoryPath}/${fileName}_${stem1}_${modelNameNoExt}.wav`;
                                  var instrumentalFile = `${directoryPath}/${fileName}_${stem2}_${modelNameNoExt}.wav`;
                                  
                                  //command line
                                  sf.system.exec({
                                      commandLine: `${separatorPath} "${fullPath}" --model_filename "${selectedModelWithExt}" --output_dir "${directoryPath}" --output_format=WAV`
                                  });
                                     
                                  sf.app.proTools.importAudio({
                                      sourcePaths: [vocalFile, instrumentalFile],
                                      audioFileHandling: "ConvertAudio",
                                      location: "Selection",
                                      destination: "NewTrack"
                                  });
                                  

                                  Once you get audio-separator installed you only need to swap out the path to it at the top of the script

                                  // Path To Audio Separator
                                  const separatorPath = "/Users/bj018/audio-sep-env/bin/audio-separator";
                                  

                                  Looking on my work computer today, it looks like I had to also make new virtual environment when I set this one up awhile back.