No internet connection
  1. Home
  2. How to

Process multiple selected files using the same command

By Andrew Sherman @Andrew_Sherman
    2021-04-10 14:31:01.677Z

    I'm trying to process multiple files using ffmpeg. Where I'm getting stuck is how to get the names and paths for each of the selected files, and how to pass that onto the shell script each time the process loops. I want to select multiple files in Finder, and then trigger the command once so that it runs on each file until they're all done. I'm running them as background processes so that it can allow other commands to still happen and to take advantage of multi-threading.

    // Convert multiple selected Quicktime videos to mono WAV using ffmpeg
    
    var selectedPaths = sf.ui.finder.selectedPaths;
    var selectedFile1 = '/path/File1.mov'; // Path/name for first item - not sure how to get this
    var selectedFile2 = '/path/File2.mov';
    // etc
    const ffmpegLocation = '/opt/homebrew/bin/ffmpeg';
    var destinationFile1 = 'path/File1.wav'; // Path/name for first output file - not sure how to get this
    var destinationFile2 = 'path/File2.wav';
    // etc
    
    selectedPaths.forEach(path => {
        sf.engine.runInBackground(() => {
    
            sf.system.exec({
                commandLine: `"${ffmpegLocation}" -i "${selectedFile1}" -ac 1 -f wav "${destinationFile1}"`,
                executionMode: 'Background',
            });
    
        });
    
    });
    
    Solved in post #5, click to view
    • 7 replies
    1. A
      Andrew Sherman @Andrew_Sherman
        2021-05-01 12:03:27.035Z

        Does anyone have any pointers on how to approach this?

        1. In reply toAndrew_Sherman:
          Chris Shaw @Chris_Shaw2021-05-01 16:14:50.404Z2021-05-01 16:23:40.695Z

          I'm not familiar with ffmpeg processing and I'm not at my rig at the moment but this might get you where you want to be:

          // Convert multiple selected Quicktime videos to mono WAV using ffmpeg
          
          //Get paths of selected Files
          var selectedPaths = sf.ui.finder.selectedPaths;
          
          const ffmpegLocation = '/opt/homebrew/bin/ffmpeg';
          
          selectedPaths.forEach(path => {
              sf.engine.runInBackground(() => {
                  var filename = path.split('/').slice(-1)[0];
                  var filenameWithoutExtension = filename.split('.').slice(0, -1).join('.');
                  var newFileName = filenameWithoutExtension + ".wav" 
          
                  sf.system.exec({
                      commandLine: `"${ffmpegLocation}" -i "${path}" -ac 1 -f wav "${newFileName}"`,
                      executionMode: 'Background',
                  });
          
              });
          
          });
          

          newFileName not be necessary if ffmpeg automatically appends ".wav" to the output file.
          If that is the case use filenameWithoutExtension instead of newFileName in the command line.
          Like I said, I'm not familiar with the ffmpeg command line but the above code should cycle through the paths and generate a new file name for each path.

          //CS//

          1. AAndrew Sherman @Andrew_Sherman
              2021-05-01 19:29:58.360Z

              This is great, thank you very much Chris! I see I was putting the variables in the wrong place, it makes sense to have them in the loop.

              I added a line to put the destination files in the same directory.

              Thanks for your help!

              
              // Convert multiple selected Quicktime videos to mono WAV using ffmpeg
              
              //Get paths of selected Files
              var selectedPaths = sf.ui.finder.selectedPaths;
              
              const ffmpegLocation = '/opt/homebrew/bin/ffmpeg';
              
              selectedPaths.forEach(path => {
                  sf.engine.runInBackground(() => {
                      var filename = path.split('/').slice(-1)[0];
                      var directory = path.split('/').slice(0, -1).join('/');
                      var filenameWithoutExtension = filename.split('.').slice(0, -1).join('.');
                      var newFileName = directory + "/" + filenameWithoutExtension + ".wav" 
              
                      sf.system.exec({
                          commandLine: `"${ffmpegLocation}" -i "${path}" -ac 1 -f wav "${newFileName}"`,
                          executionMode: 'Background',
                      });
              
                  });
              
              });
              
              ReplySolution
              1. AAndrew Sherman @Andrew_Sherman
                  2021-05-01 20:46:10.137Z

                  Chris, this works perfectly for keeping the filenames the same (which is what I was initially looking for). I made a version that deletes the original Quicktime videos as I don't want to keep them for my specific use case.

                  But is there a way of renaming the files and incrementing them as well?

                  For example
                  Copy name to clipboard ("NewFileName")
                  NewFileName-01.wav
                  NewFileName-02.wav
                  etc

                  I tried to include your excellent code that increments the file number, but I was only getting it to do one file and then it would stop.

                  // Convert multiple selected Quicktime videos to mono WAV using ffmpeg
                  
                  //Get paths of selected Files
                  var selectedPaths = sf.ui.finder.selectedPaths;
                  
                  const ffmpegLocation = '/opt/homebrew/bin/ffmpeg';
                  
                  selectedPaths.forEach(path => {
                      sf.engine.runInBackground(() => {
                          var filename = path.split('/').slice(-1)[0];
                          var directory = path.split('/').slice(0, -1).join('/');
                          var filenameWithoutExtension = filename.split('.').slice(0, -1).join('.');
                          var newFileName = directory + "/" + filenameWithoutExtension + ".wav"
                  
                          // Convert files from MOV to WAV
                          sf.system.exec({
                              commandLine: `"${ffmpegLocation}" -i "${path}" -ac 1 -f wav "${newFileName}"`,
                              executionMode: 'Background',
                          });
                  
                          // Delete original files
                          sf.file.move({
                              sourcePath: directory + '/' + filename,
                              destinationPath: '~/.Trash/' + filename
                          });
                  
                      });
                  
                  });
                  
                  // var projectName = sf.clipboard.getText().text + '-01';
                  // var grps = filenameWithoutExtension.match(/^(.+?)(\d+)$/);
                  // var newNumber = !grps || grps.length === 0 || isNaN(Number(grps[2])) ? '-01' : ((Number(grps[2]) + 1) + '').padStart(2, '0');
                  // var newFile = (grps ? grps[1] : (filenameWithoutExtension)) + newNumber + '.' + 'wav';
                  // var newFilePath = directory + '/' + newFile;
                  
                  
                  1. this should do it. It will add a leading zero to single digit file numbers. This should be good up to 100 files.

                    // Convert multiple selected Quicktime videos to mono WAV using ffmpeg
                    
                    //Get paths of selected Files
                    var selectedPaths = sf.ui.finder.selectedPaths;
                    
                    const ffmpegLocation = '/opt/homebrew/bin/ffmpeg';
                    
                    // set counter for incrementing files to 0
                    var i = 0;
                    
                    // Loop through array and convert files
                    selectedPaths.forEach(path => {
                    
                        //increment file number by 1
                        i = i + 1;
                    
                       // if file number is less than 10, add leading zero
                        if (i < 10) {
                            var fileNumber = ("0" + i.toString());
                        } else { fileNumber = i.toString() }
                    
                        //Convert selected files
                        sf.engine.runInBackground(() => {
                    
                            // get paths and file names
                            var filename = path.split('/').slice(-1)[0];
                            var directory = path.split('/').slice(0, -1).join('/');
                            var filenameWithoutExtension = filename.split('.').slice(0, -1).join('.');
                            var newFileName = directory + "/" + filenameWithoutExtension + "-" + fileNumber + ".wav"
                    
                            // Convert files from MOV to WAV
                            sf.system.exec({
                                commandLine: `"${ffmpegLocation}" -i "${path}" -ac 1 -f wav "${newFileName}"`,
                                executionMode: 'Background',
                            });
                    
                            // Delete original files
                            sf.file.move({
                                sourcePath: directory + '/' + filename,
                                destinationPath: '~/.Trash/' + filename
                            });
                    
                        });
                    
                    });
                    
                    1. AAndrew Sherman @Andrew_Sherman
                        2021-05-02 05:16:22.782Z

                        This is excellent, thank you Chris. This technique will be useful for me for other things as well. Much appreciated.

                        1. FYI:
                          For cleaner code, this part of the script:

                          if (i < 10) {
                                  var fileNumber = ("0" + i.toString());
                              } else { fileNumber = i.toString() }
                          

                          Can be written as:

                          var fileNumber = (i<10) ? ("0" + i.toString()) : i.toString()