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',
});
});
});
- AAndrew Sherman @Andrew_Sherman
Does anyone have any pointers on how to approach this?
- 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 usefilenameWithoutExtension
instead ofnewFileName
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//
- AAndrew Sherman @Andrew_Sherman
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', }); }); });
- AAndrew Sherman @Andrew_Sherman
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
etcI 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;
Chris Shaw @Chris_Shaw2021-05-01 22:29:57.349Z
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 }); }); });
- AAndrew Sherman @Andrew_Sherman
This is excellent, thank you Chris. This technique will be useful for me for other things as well. Much appreciated.
Chris Shaw @Chris_Shaw2021-05-02 13:46:01.690Z
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()