My goal is to create an "Encode to MP4" button, in JScript if possible. My goal is to handle width/height/duration and frame rate variables in if/else, before deciding the FFMPEG formula to use in order to convert the file to MP4.
I think I'd benefit from just being pointed at how to find/get file properties. I'd also like to know which Type of function I should do this script in as I'm very new. I'm not sure what the difference is between: Standard Function (Opus or external), MS-DOS Batch Function, Script Function (JScript, VBScript), WSL Script Function.
Ok well, given the information I was able to find. I asked ChatGPT to make one and got what I wanted:
function OnClick(clickData) {
var cmd = clickData.func.command;
var selectedItems = clickData.func.sourcetab.selected;
if (selectedItems.count == 0) {
DOpus.Output("No video files selected.");
return;
}
var ffprobePath = "ffprobe"; // Assumes ffprobe is in your system's PATH
var ffmpegPath = "ffmpeg"; // Assumes ffmpeg is in your system's PATH
for (var e = new Enumerator(selectedItems); !e.atEnd(); e.moveNext()) {
var item = e.item();
if (!item.is_dir) {
var inputFilePath = item.realpath;
var outputFilePath = item.path + "\\" + item.name_stem + "_LQ.mp4";
// Get video information using ffprobe
var shell = new ActiveXObject("WScript.Shell");
var exec = shell.Exec(ffprobePath + ' -v error -select_streams v:0 -show_entries stream=width,height,r_frame_rate,duration,bit_rate -of default=noprint_wrappers=1 "' + inputFilePath + '"');
var stdout = exec.StdOut.ReadAll();
var stderr = exec.StdErr.ReadAll();
if (stderr) {
DOpus.Output("Error: " + stderr);
continue;
}
// Parse the ffprobe output
var width = stdout.match(/width=([0-9]+)/) ? parseInt(stdout.match(/width=([0-9]+)/)[1], 10) : null;
var height = stdout.match(/height=([0-9]+)/) ? parseInt(stdout.match(/height=([0-9]+)/)[1], 10) : null;
var frameRate = stdout.match(/r_frame_rate=([0-9]+\/[0-9]+)/) ? stdout.match(/r_frame_rate=([0-9]+\/[0-9]+)/)[1] : "30000/1001";
var duration = stdout.match(/duration=([0-9.]+)/) ? parseFloat(stdout.match(/duration=([0-9.]+)/)[1]) : null;
var bitRate = stdout.match(/bit_rate=([0-9]+)/) ? parseInt(stdout.match(/bit_rate=([0-9]+)/)[1], 10) : null;
if (!width || !height) {
DOpus.Output("Could not extract necessary video information for file: " + inputFilePath);
continue;
}
// Calculate new dimensions (halving resolution)
var newWidth = Math.floor(width / 2);
var newHeight = Math.floor(height / 2);
// Determine encoding parameters based on resolution
var crf, maxRate, bufSize;
if (newWidth >= 1920 || newHeight >= 1080) {
crf = 23;
maxRate = "8M";
bufSize = "10M";
} else if (newWidth >= 1280 || newHeight >= 720) {
crf = 25;
maxRate = "5M";
bufSize = "6M";
} else {
crf = 28;
maxRate = "3M";
bufSize = "4M";
}
var ffmpegCommand = ffmpegPath +
' -i "' + inputFilePath + '"' +
' -vf "scale=' + newWidth + ':' + newHeight + ',format=yuv420p"' +
' -c:v libx264' +
' -preset slow' +
' -crf ' + crf +
' -maxrate ' + maxRate +
' -bufsize ' + bufSize +
' -profile:v baseline' + // Change profile to baseline
' -level 3.1' + // Lower level to 3.1
' -c:a aac' +
' -b:a 128k' +
' -movflags +faststart' +
' "' + outputFilePath + '"';
DOpus.Output("Running encoding command: " + ffmpegCommand);
// Run the FFMPEG command
cmd.RunCommand('cmd /c ' + ffmpegCommand);
DOpus.Output("Encoding completed. Output file: " + outputFilePath);
}
}
}
That being said, can I actually save the code in the buttons as editable text? i'd like to put the scripts I've been accumulating into a Git repo so that I have version control for when I update/change them.
At the moment, I'm just making copies of the flies and registering them in Git.
Oh, it just occurred to me that I can drag the entire DO folder from the C:\ into VS code and put that in a repo instead. I'll try to figure out how to keep stuff I want to track registered, or at least this way, I have a better starting point than just guessing where to look for something.