DOpus-Scripting-Extensions project

Thanks.
I know this works since it's quite the same as the one I posted stating it's how I made it work :slight_smile:
Thanks also for clarifying the use of double quotes.

There was two points for my post;

  • My first instinct led me to something lile var paramsArray = [ "-background #ff5722", "-fill #000000", ... which is not working. Using switches like -swwitch <value> you need to pass 2 parameters in the array, one for -switch and another one for <value>. I wanted to suggest the examples on the github would be updated for that.
  • The second one was about quotes: you just clarified that. If an entire parameter would require being encapsulated between double quotes on a command line (such as a path), here, it's not required and to go even further, any double quotes added will end being interpreted as part of the parameter (which seems not to be an issue with the path for ImageMagick, but could be for other command line tools).

Once again thanks for that and the effort to work on performance (even though I had no chance to work with commands outputing things in the likes of 1MB or more, but it couold be a thing in some edge cases, especially with db requests).

If I were to do that, I would implement the logic inside a JScript Opus script, and rely on ProcessRunner to just make the calls to ffmpeg. I'm not sure you would gain much in implementing the logic somewhere else.
Note also that for most of ffmpeg calls, you won't need to retrieve the console output, the return code should be enough, which makes relying on a simple WScript.Shell.Run an option to consider.

1 Like

Yes, that's what I've done in my scripts so far.

Nor am I - that's why I'm bringing this up. :wink: My hope would be that looping in the ProcessRunner is faster than the same logic in JScript. Plus the passing back and forth of data will add a bit of overhead as well.
But the answer may well be "No". :man_shrugging:

Well, that depends entirely on what you're using ffmpeg for. Example: I have a command to select all mp3 files that have the same set of tags as the selected one. Several tags are my own custom ones, so the built-in DOpus metadata aren't an option. That requires retrieving the tags of all files in a directory.

(Yes, I'm aware there are other tools possibly more suited to that but I'm trying to reduce the number of dependencies of my DOpus installation.)

Anyway, I wasn't asking just about this specific use case but rather about the general possibility and value of such an addition.

Absolutely. That's why I said "for most calls". But if you're using the functions of ffmpeg that are retrieving information, which seems to be one of your use cases, in that case, you'd benefit from using ProcessRunner.

There is probably a slight gain in performance from looping in C++ compiled code rather than doing it in a scripting language, and yes, passing data is adding a bit of overhead (if you can manage to give the same information in a more consice way for the loop, which is not assured in all situations), but I think it is negligible compared to the operations done by ffmpeg that require disk i/o (at least to read file headers/metadata parts). So in the end, it won't matter much.
Where you'll probably gain is by using ProcessRunner instead of having the console output written to a file then read from that file to process it.

If you take the example I mentioned above, my script was making sqlite requests about 400 times in a loop: each call took about 800ms with console output write/read to/from file and is now taking around 300ms for the same requests.
Overall, that part of the script is now taking about 2 minutes where it took more than 5 before.
In that situation, looping elsewhere might help gain a few seconds not much more than that I think.
Of course, all of this remains very contextual and could be different in your situation.

Hi @PolarGoose. Trying to switch my existing scripts that at some point run an external app, I stumbled upon a situation where I did use WScript.Shell.CurrentDirectory because the external app I use is working on the directory from where it is launched.

Would it be doable to add such a method on the ProcessRunner object (that would have to be called, optionally, before the Run method) ?
If not, I'll try and work launching a cmd that first changes directory then launched the app, but it will be less straightforward.

@PassThePeas,

Could you provide a code sample of how you use WScript.Shell.CurrentDirectory ?

Sure.
Basically, once you have the ActiveXObject("WScript.Shell") in a variable (for instance shell), you just assign a string path to shell.CurrentDirectory.

	var fsu 		= DOpus.FSUtil;
	var vResult = { "result" : null, "nbLines" : 0, "lines" : DOpus.Create.Vector, "errors" : DOpus.Create.Vector() };
	var rootFolder 	= fsu.Resolve(rootPath);

	var fso 	= new ActiveXObject("Scripting.FilesystemObject");
	var shell   = new ActiveXObject("WScript.Shell");

	var tmpFileBase = "DO.Temp.";
	var tmpFileExt = ".txt";
	var tmpFileStdout = ExtSystem.GetTmpFileName(tmpFileBase, tmpFileExt, fso).fullname;
	var tmpFileStderr = tmpFileStdout+".err"+tmpFileExt;
	
	var cmdLine = '%comspec% /c "python3.12 "' + nimbankPath + '" --list csvSAL -r . ';
	shell.CurrentDirectory = rootFolder;
	cmdLine += ' >"'+tmpFileStdout+'" 2>"'+tmpFileStderr+'""';

	var result = {};
	result.cmd = cmdLine;
	result.returncode = shell.Run(cmdLine, 0, true);
	result.stdout = ExtSystem.ReadFile(tmpFileStdout, fso); //fso.DeleteFile(tmpFileStdout);
	result.stderr = ExtSystem.ReadFile(tmpFileStderr, fso); //fso.DeleteFile(tmpFileStderr);

@PassThePeas,

it is a very good point. I need to allow specification of the WorkingDirectory like this:

var workingDirectory = "C:\some directory"
processRunner.Run(exe, params, workingDirectory)

I will add it soon.

1 Like

I have released a new version:

  • You can specify a working directory like this:
res = processRunner.Run("C:/Program Files/Git/usr/bin/file.exe", ["twain_32.dll"], "C:/Windows")
  • You can use environment variables in the path
res = processRunner.Run("%comspec%", ["/c", "echo test"])
2 Likes

I have released a new version:

  • ProcessRunner should be a bit faster now.
  • No need to specify [] to run an executable without parameters. You can just call it like this:
    processRunner.Run("C:/Program Files/Git/usr/bin/echo.exe")
  • Added StringFormatter class to format strings in Python-like style:
    fmt.Format("Some {} with {}. Number: {:10}", "message", "arguments", 123)
2 Likes

Nice addition! Thanks.

Is it still on the roadmap to include wrappers to some useful utility libraries? Like your idea of libmagic or MediaInfoLib?

I have added libmagic too. I forgot to mention it :slight_smile: It is described in the Readme on the Github repo. I already use it in my plugin File MIME type column.

MediaInfoLib

I'm looking into it. I have checked the existing plugin MediaInfo-based extended columns, it is gigantic :slight_smile:
I need to see if there will be any benefit of having the functionality inside a COM dll.

There is another idea I got. Apart from libmagic, there is also TrID, which provides more comprehensive information about file type. It relies on a big database. COM DLL can allow the database to be loaded once, and then every request for a file type in DOpus will be very fast.

Ah, sorry I missed that one.

TrID as a lib is also a good idea!

As for MediaInfoLib, I think it has faster responsiveness than its executable counterpart, and it lets you get very specific info that's not possible via the command line.

And what about Exiftool as a lib? I think it also takes longer the first time you call it. Does it make sense to include it as a library—to gain some speed on subsequent calls? I read that the Perl version even has faster responsiveness, but I'm guessing that including that version would be nearly impossible or at least a huge time consumer. Or am I wrong?

(If you have the site rights, maybe it would be a good idea to move or create this post in the Tools area).

Could you draft a sample code in JScript on how you would like to use MediaInfoLib if it were provided as a COM object?

If you have the site rights

I'm just an ordinary peasant :slight_smile:

it would be a good idea to move or create this post in the Tools area

Yes, probably, as this project got traction, I guess it might be a suitable place for this topic.
@Leo, hey :slight_smile: Could you please move this topic to Tools if you think it is okay?

Sure. I was thinking of something very similar to the current official MediaInfo examples available in other languages.
E.g. to get some info for Chapters:

var MI_lib = new ActiveXObject('DOpusScriptingExtensions.MediaInfo');
if (!MI_lib) return;
var file = 'c:\\path\\to\\video.mp4';
if (MI_lib.Open(file)) {
	var ini_chapters = parseInt(MI_lib.Get(3, 0, "Chapters_Pos_Begin"), 10) || 0; // 3 is StreamKind=Menu
	var end_chapters = parseInt(MI_lib.Get(3, 0, "Chapters_Pos_End"), 10) || 0;
	while (ini_chapters <= end_chapters) {
		DOpus.Output(MI_lib.Get(3, 0, ini_chapters, 'Info_Name')); 
		DOpus.Output(MI_lib.Get(3, 0, ini_chapters, 'Info_Text'));
		ini_chapters++;
	};
	MI_lib.Close();
}

More interestly it would probably be to use MediaInfoList, since it lets you manage a list of files.

I understand this is very niche, so it shouldn't be taken as a request or anything like that. I'm totally fine with ProcessRunner, and I thank you again for that.

Regards.

I have added MediaInfoRetriever class. Look at the Readme file in the repository on how to use it.
Could you please check if it provides the required functionality?

3 Likes

:open_mouth:
I'm going to test it this weekend and report back ASAP.
Thanks!

After some tests, I can confirm that MediaInfoRetriever is working very nicely. It does seem faster than using their CLI counterpart.

As a side note, thanks to your clear code, I managed to add and build a new dll with some additional methods from MediaInfoLib. It's very addictive! :grinning_face_with_smiling_eyes:
But I'm by no means a dev, and I don't want to do a pull request, so maybe it's better if I show you what I did via DM, if that's OK with you.

Many thanks for the addition, and congrats on the initiative—may it continue to grow with new projects over time.

Regards.

2 Likes

@errante,

Amazing, glad that you liked it.

But I'm by no means a dev, and I don't want to do a pull request, so maybe it's better if I show you what I did via DM, if that's OK with you.

Yes. Send me the code via DM. I will incorporate it.

1 Like

I have released a new version:

  • Added extra methods to MediaInfoRetriever. The implementation was done by @errante.