Page 1 of 1

Video Calculator

Posted: 24 Apr 2009 05:58
by Muroph
A bit of background info:
I do a lot of video conversions, and often i need to calculate the parameters (bitrate, resolution, etc) for these conversions.
However, even after hours of hard work, I couldn't find an all-in-one tool to do it for me.
So I decided to write my own using a familiar language, xy script.
This was intended to be a simple script for my personal use only, but it's been so useful to me that i decided to share it.

Video Calculator v6

This script used to be a simple bitrate calculator, but it got a lot more features over time.

What it can do:
-Calculate video duration, bitrate or size.
-Calculate new resolution based on current or specified aspect ratio (current AR calculated from original resolution).
-Calculate image aspect ratio (you can even give a name to them).
Since v2:
-Remember last input.
Since v3:
-Round resolution to closest multiple of "x". If "x" is not specified, use (configurable) default value.

Changes in v6:
-Small changes to the input syntax.
-Rewriten to make use of "if" and "while" blocks.

Simply run the script, fill the parameters for the desired operation and hit enter.
And make sure you don't use any ridiculous values.
If you need help, just post your problem here.

It's kinda big, but I won't post it as a file attachment.

Code: Select all

// Video Calculator v6
//
//     Settings
//   $sep
// set the separator between parameters.
// never use comma(s), slash(es), or a single dot.
// changing the separator *might* break the script.
// the only way to know is testing.
// default = "-"
//
//   $delta
// this is used to compare the calculated aspect ratio with those in the $ratios list.
// a match will happen if the difference betwen the calculated ratio and the named ratio is smaller than $delta.
// lower values give more precision, but if it's too low the script will probably never match anything.
// higher values will match more often, but they are more likely to match the wrong name.
// i'm still testing to see what is the best value for this setting.
// for now i'll leave the default at "0.03" (it's enough to separate 3:2 from 14:9).
// 
//   $ratios
//   $names
// comma-separated list of aspect ratios and their names.
// put the ratio in the $ratio list and the name you want for it in the $names list.
// the ratio and it's name must be in the same position in the list.
// if there are 2 or more succesful matches, the one closest to the end of the list will overwrite the others.
// the default lists match some common aspect ratios.
//
//   $temppath
// path used to store variables.
//
//   $defresdiv
// set the default divisor for output resolution.
// any calculated resolution will be rounded to the closest multiple of this value.
// unless, of course, you specify otherwise in the input dialog.
// the default value is "1" (calculated resolution is not changed).
//
"Video Calculator"
  global $input,$sep,$delta,$ratios,$names,$defresdiv;
  //the settings
  $sep = "-";
  $delta = "0.03";
  $ratios = "1.33,1.50,1.56,1.66,1.78";
  $names = "4:3,3:2,14:9,5:3,16:9";
  $temppath = "%temp%";
  $defresdiv = 16;
  //script start
  getkey $lastinput, lastinput, general, "$temppath\videocalc.tmp";
  $tips=<<<TIPS
Use * to select the output (only one!)

Duration, Bitrate or Size:
<hh,nn,ss>$sep<kbps>$sep<MB>
Note: "hh," or "hh,nn," are optional

Resize using current aspect ratio:
<orig_width>,<orig_height>$sep<new_width>,<new_height>[,<divisor>]
Use * only on <new_width> or <new_height>

Change/calculate aspect ratio:
<width>,<height>[,<divisor>]$sep<ratio>
Enter <ratio> as a decimal or a proportion (e.g. 1.33 == 4/3)
TIPS;
  $input = input("Video Calculator", "$tips", $lastinput, s);
  setkey $input, lastinput, general, "$temppath\videocalc.tmp";
  replace $input, $input, " ", ""; //remove spaces
  $test = gettoken($input, 3, "$sep"); //find type of operation
  sub ($test)?(_dbs):(_res);

"_dbs" //get duration, bitrate and size from input, then see which one we have to calculate
  global $input,$dur,$bit,$size,$sep;
  $dur = gettoken($input, 1, "$sep");
  $bit = gettoken($input, 2, "$sep");
  $size = gettoken($input, 3, "$sep");
  if("$dur"=="*"){sub _duration;}
  elseif("$bit"=="*"){sub _bitrate;}
  elseif("$size"=="*"){sub _size;}
  else{sub _invalid;}

"_res" //get resolutions, divisor and aspect ratio, then decide what to calculate
  global $input,$origw,$origh,$neww,$newh,$ar,$sep,$resdiv,$defresdiv;
  $original = gettoken($input, 1, "$sep");
  $new = gettoken($input, 2, "$sep");
  $origw = gettoken($original,1,",");
  $origh = gettoken($original,2,",");
  $resdiv = gettoken($original,3,",");
  $neww = gettoken($new,1,",");
  $newh = gettoken($new,2,",");
  $resdiv = ($resdiv)?($resdiv):(gettoken($new,3,","));
  $resdiv=($resdiv)?($resdiv):($defresdiv);
  $ar = eval($new);
  if("$new"=="*"){sub _ar;}
  elseif("$newh"=="*"){sub _newheight;}
  elseif("$origw"=="*"){sub _arwidth;}
  elseif("$origh"=="*"){sub _arheight;}
  elseif("$neww"=="*"){sub _newwidth;}
  else{sub _invalid;}
  //sub ("$new"=="*")?(_ar):(("$newh"=="*")?(_newheight):(("$origw"=="*")?(_arwidth):(("$origh"=="*")?(_arheight):(("$neww"=="*")?(_newwidth):(_invalid)))));

"_duration" //calculate clip duration for given bitrate and file size
  global $bit,$size,$round;
  $sec = ($size*8192/$bit);//calculate total seconds
  $min = ($sec/60);//minutes
  $hrs = ($min/60);//and hours
  $round = "$sec,3"; sub _round; $sec=$round;
  $min = gettoken("$min.", 1, ","); //discard redundant time
  $hrs = gettoken("$hrs.", 1, ",");
  $sec2 = ($sec-$min*60);
  $round = "$sec2,3"; sub _round; $sec2 = $round;
  $min = ($min-$hrs*60);
  strlen $test, $sec2; //fix leading zeros
  $sec2 = ($test==1)?(0.$sec2):($sec2);
  strlen $test, $min;
  $min = ($test==1)?(0.$min):($min);
  input("Clip duration in hrs:min:sec (Click OK to see total seconds)", ,"$hrs:$min:$sec2");
  input("Clip duration in seconds", ,"$sec"); //done!

"_getduration" //calculate total of seconds based on duration input
  global $dur,$total;
  $thrs = gettoken($dur, 1, ",");
  $tmin = gettoken($dur, 2, ",");
  $tsec = gettoken($dur, 3, ",");
  if($tmin==""){ //fix if "hh.nn" wasn't entered
	$tsec = $thrs;
	$tmin = 0;
	$thrs = 0;}
  elseif($tsec==""){ //fix if "hh" wasn't entered
	$tsec = $tmin;
	$tmin = $thrs;
	$thrs = 0;}
  $total = ($tsec+60*$tmin+3600*$thrs); //total seconds

"_bitrate" //calculate bitrate based on duration and file size
  global $size,$total,$round;
  sub _getduration;
  $bitrate = ($size*8192/$total); //this will also round down the result
  $round = "$bitrate,0"; sub _round; $bitrate = $round; //this will also round the result
  input("Clip bitrate in Kbps", ,"$bitrate"); //done!

"_size" //calculate file size based on duration and bitrate
  global $bit,$total,$round;
  sub _getduration;
  $size = ($bit*$total/8192);
  $round = "$size,2"; sub _round; $size = $round; //leave only two decimals
  input("File size in MB", ,"$size"); //done!
  
"_newwidth" //calculate new width for desired height, using current aspect ratio
  global $origw,$origh,$neww,$newh,$ar,$round,$resdiv,$newheight,$newwidth;
  $newwidth = ($origw/$origh*$newh);
  $newheight = $newh;
  if($resdiv>1){sub _resdiv;}
  //sub ($resdiv>1)?(_resdiv):(_nothing);
  $round = "$newwidth,0"; sub _round; $newwidth = $round;
  input("New clip resolution  (width,height)", ,"$newwidth,$newheight"); //done!

"_newheight" //vice-versa, again using the current aspect ratio
  global $origw,$origh,$neww,$newh,$round,$resdiv,$newheight,$newwidth;
  $newheight = ($origh/$origw*$neww);
  $newwidth = $neww;
  if($resdiv>1){sub _resdiv;}
  //sub ($resdiv>1)?(_resdiv):(_nothing);
  $round = "$newheight,0"; sub _round; $newheight = $round;
  input("New clip resolution (width,height)", ,"$newwidth,$newheight"); //done!

"_arwidth" //calculate width using specified aspect ratio
  global $origh,$ar,$round,$resdiv,$newheight,$newwidth;
  $newwidth = ($ar*$origh);
  $newheight = $origh;
  if($resdiv>1){sub _resdiv;}
  //sub ($resdiv>1)?(_resdiv):(_nothing);
  $round = "$newwidth,0"; sub _round; $newwidth = $round;
  input("New clip resolution (width,height)", ,"$newwidth,$newheight"); //done! 

"_arheight" //calculate height using specified aspect ratio
  global $origw,$ar,$round,$resdiv,$newheight,$newwidth;
  $newheight = (1/$ar*$origw);
  $newwidth = $origw;
  if($resdiv>1){sub _resdiv;}
  //sub ($resdiv>1)?(_resdiv):(_nothing);
  $round = "$newheight,0"; sub _round; $newheight = $round;
  input("New clip resolution (width,height)", ,"$newwidth,$newheight"); //done! 

"_ar" //calculate aspect ratio of given resolution
  global $origw,$origh,$ar,$modar,$delta,$names,$maxcount,$round;
  $ar = ($origw/$origh); //calculate ratio
  regexreplace $test, $names, "[^,]", ""; //start comparison loop
  strlen $maxcount, $test;
  $count = 0;
  while($count<=$maxcount){
	$workar = gettoken("$ratios", ($count+1),","); //get current name and ratio from the list
	$workname = gettoken("$names", ($count+1),",");
	$modar = (((-$delta<($ar-$workar))==(($ar-$workar)<$delta))==1)?($workname):($modar);  //compare with calculated aspect ratio using $delta
	$count++;}
  $round = "$ar,2"; sub _round; $ar = $round; //leave only two decimals
  input(($modar)?("Aspect ratio matched $modar"):("Aspect ratio is:"), ,"$ar:1"); //done!

"_resdiv"
  global $resdiv,$newwidth,$newheight,$round;
  $round=($newwidth/$resdiv).",0"; sub _round;
  $newwidth=($round*$resdiv);
  $round=($newheight/$resdiv).",0"; sub _round;
  $newheight=($round*$resdiv);

"_round" //global $round; $round="<value_or_variable_to_round>,<output_decimal_places>"; sub _round; <output_variable>=$round;
  global $round;
  $roundval = gettoken($round,1,","); //get parameters
  $roundto = gettoken($round,2,",");
  $roundint = gettoken($roundval,1,"."); //separate decimal part
  $rounddec = gettoken($roundval,2,".");
  if($roundto>0){
	substr $outdec, $rounddec,,$roundto; //separate removed decimals
	substr $remdec, $rounddec, $roundto;
	if("0.$remdec">"0.5"){ //test to round down the decimals
		incr $outdec;}
	elseif("0.$remdec"=="0.5"){
		$outdec = (gettoken(($outdec/2),2, "."))?($outdec+1):($outdec);}
	strlen $countdec, $outdec; //fix trailing zeroes
	$outdec = "$outdec".strrepeat("0",($roundto-$countdec));}
  elseif($roundto==0){
	if("0.$rounddec">"0.5"){ //test to round down the decimals
		incr $roundint;}
	elseif("0.$$rounddec"=="0.5"){
		$roundint = (gettoken(($roundint/2),2, "."))?($roundint+1):($roundint);}}
  $round = "$roundint".($roundto>0)?(".$outdec"):(""); //output to $round

"_invalid"
  msg "Invalid input parameters";

//"_nothing"

Re: Video Calculator

Posted: 24 Apr 2009 23:18
by Muroph
Updated to v2:

-Fixed a bug.
-Remember last input used.
-New sub-script to round numbers. Follows math conventions (at least those i could remember).

Re: Video Calculator

Posted: 25 Apr 2009 10:57
by admin
Wow, again and again I'm surprised what you folks do with xy scripting. Some of you are really into it. I'd like to know: Is there any particular thing you miss in scripting, something that would make your scripting life much easier?

Re: Video Calculator

Posted: 25 Apr 2009 20:36
by Muroph
Another update.
This time to v3.

-Round resolution to closest multiple of "x". If "x" is not specified, use (configurable) default value.
Sometimes I have to round the resolution to a certain divisor in order to use an image filter.
Now i don't have to do it by hand.

I don't have any other (useful) ideas for a v4. Yet. :)

admin wrote:Wow, again and again I'm surprised what you folks do with xy scripting. Some of you are really into it. I'd like to know: Is there any particular thing you miss in scripting, something that would make your scripting life much easier?
hmm...
maybe having a few more commands converted to functions.
this way we could put them directly inside other commands/functions/comparisons and discard lots of temp variables.
however, this would mean having to review and rewrite many scripts :| .

Re: Video Calculator

Posted: 25 Apr 2009 23:11
by TheQwerty
admin wrote:Wow, again and again I'm surprised what you folks do with xy scripting. Some of you are really into it. I'd like to know: Is there any particular thing you miss in scripting, something that would make your scripting life much easier?
1) Loops. Recursion is sloppy and prone to stack overflows.
2) Real logic blocks. Having to sub out everything can be painful, and often requires a lot of unnecessary use of globals.
3) Ability to retrieve current state of XY's config. (For instance I want to detect if the catalog or tree is visible, the only way to do so is Save the configuration and then read it).
4) User functions. With globals you can get by but it would be nice to have actual user functions.
5) A lot more commands / functions to control XY (open/rename/lock/home/iconify tabs,
6) Ability to easily create submenus, so that they actually show as submenus, open in the appropriate place, don't chase the cursor around (I prefer they open at my cursor to the left corner), and can be easily closed to return to the main menu.

Should I keep going? :P

Re: Video Calculator

Posted: 26 Apr 2009 03:03
by jacky
Yep, conditions, loops, user functions and arrays are probably on top of my list as well.

Of course, things like onEvent actions or even improvements to existing functions could be great, too -- e.g. report() to support an extra optional param for items list...

Re: Video Calculator

Posted: 26 Apr 2009 07:12
by admin
TheQwerty wrote:
admin wrote:Wow, again and again I'm surprised what you folks do with xy scripting. Some of you are really into it. I'd like to know: Is there any particular thing you miss in scripting, something that would make your scripting life much easier?
1) Loops. Recursion is sloppy and prone to stack overflows.
2) Real logic blocks. Having to sub out everything can be painful, and often requires a lot of unnecessary use of globals.
3) Ability to retrieve current state of XY's config. (For instance I want to detect if the catalog or tree is visible, the only way to do so is Save the configuration and then read it).
4) User functions. With globals you can get by but it would be nice to have actual user functions.
5) A lot more commands / functions to control XY (open/rename/lock/home/iconify tabs,
6) Ability to easily create submenus, so that they actually show as submenus, open in the appropriate place, don't chase the cursor around (I prefer they open at my cursor to the left corner), and can be easily closed to return to the main menu.

Should I keep going? :P
Ah yes, this is was I expected to hear. :) I just was wondering how it's possible that folks write so large and involved scripts without screaming for loops and logic blocks.

Re: Video Calculator

Posted: 26 Apr 2009 09:21
by fishgod
admin wrote:Ah yes, this is was I expected to hear. :) I just was wondering how it's possible that folks write so large and involved scripts without screaming for loops and logic blocks.
I tried to be more constructive in this forum instead of screaming for features while you where absent :D.
Its also possible to convert everly loop and logical block to recursions and xy-syntax :)

But hell yeah, loops and logical block would be another milestone in scripting.

Re: Video Calculator

Posted: 26 Apr 2009 11:46
by serendipity
OK, apart from what TheQwerty mentioned which is a bigger part of scripting I have some smaller requests for current commands/functions:
1) getinfo can show get more infos like extended info of special files like images, audios and videos. (Any reason why extended info in menu File>To clipboard is less detailed than the one in preview mode?)
Also getinfo could give number of items in the current list and position of current intem in the list.
2) replace could support wildcards and inversions.

Will think of more :idea:

Re: Video Calculator

Posted: 26 Apr 2009 13:47
by admin
serendipity wrote:Will think of more :idea:
Thanks, but I'm not out of ideas. My lists are full. I just asked that question because I was surprised about what people can do without logic blocks and loops. I personally would not do scripts > 20 lines without those syntax features... :wink: Especially using recursions as a replacement for loops gives me pains. :mrgreen:

Re: Video Calculator

Posted: 26 Apr 2009 14:04
by jacky
admin wrote:I personally would not do scripts > 20 lines without those syntax features... :wink: Especially using recursions as a replacement for loops gives me pains. :mrgreen:
Yeah, but if such a script filled with bad recursions works fine & saves you 15 minutes a day, I can use those 15 minutes to relax & work on such pains, waiting for the next version of script engine... ;) 8)

Re: Video Calculator

Posted: 27 Apr 2009 12:55
by admin
serendipity wrote:Any reason why extended info in menu File>To clipboard is less detailed than the one in preview mode?
Historical reason, aka "It's always been like that." :)

Re: Video Calculator

Posted: 27 Apr 2009 13:55
by TheQwerty
jacky wrote:Of course, things like onEvent actions
Oh yes, I completely forgot about oEA!
admin wrote:Ah yes, this is was I expected to hear. :) I just was wondering how it's possible that folks write so large and involved scripts without screaming for loops and logic blocks.
You've given us enough tools to get by sufficiently, and really it's not too terribly painful once you adjust. However, each time I script around the lack of loops and logic blocks, I do indeed curse you. :P I know it's on your list though, and will eventually happen, so there's no point pestering.

Re: Video Calculator

Posted: 27 Apr 2009 15:59
by admin
TheQwerty wrote:You've given us enough tools to get by sufficiently, and really it's not too terribly painful once you adjust. However, each time I script around the lack of loops and logic blocks, I do indeed curse you. :P I know it's on your list though, and will eventually happen, so there's no point pestering.
I hope the cursing reduces a bit from v7.90.0145 onwards... :wink: