Need a little help with a non-working AVISynth resize script...

Nazo

2[H]4U
Joined
Apr 2, 2002
Messages
3,672
Ok, I'm trying to create a somewhat universal script for taking a source video, changing the framerate, and resizing it for a portable player (namely my iAudio U3.) Basically how it works is that it should take the video, convert the framerate (via the switch mode since the framerate decrease is too extreme to just blend -- I wonder if anyone might know if there might be a more optimal value than the zone=80 that the documentation suggests?) then resize the video.

The tricky part here is that I want it to either add borders or crop the video (depending on my personal preference for the particular video) and I really want it to be able to figure it out on its own (otherwise it wouldn't be very universal after all.) To this end, I tried to create one function for each method and determine within each function first the size to resize to (maintaining the original source aspect ratio but fitting the correct target dimension depending on which method is being used) and then the amount to add or subtract to get the correct output.

The problem is, AVISynth seems to be ignoring something and resizing into a square image every time. With the border adding resize (where it resizes to the same width as the target but should resize to a lower height) it resizes to TargetWidth*TargetWidth and with the cropping resize (where it resizes to the same height as the target but should resize to a larger height) it resizes to TargetHeight*TargetHeight. In other words, if I take a 352x240 video (eg the colorbars I'm using for testing atm) with the borders enabled, I should be getting an output of 160x128 with black bars such that the actual video itself is 160x109 within those bars and instead I get an output of 160x160 with no borders. If I use cropping on that same resolution video, I should see video actually being about 188x128 cropped down to 160x128 (eg 14 pixels cut off of the left and the right for a removal of 28 total width) and instead I get a 128x128 video with no cropping.

To determine resize width or height, I first find out the aspect ratio of the source video by dividing width and height (eg 4/3 = 1.3333) and then I multiply that ratio by the target height to get the resize width (eg 1.3333 * 128 = 170.6624) for cropping or divide that ratio from the target width to get the resize height (eg 160 / 1.3333 = 120.0030) for borders. I was hoping to get away without needing rounding, but I think I will have to (it was my hope that it was smart enough to blend and such as needed -- like it can do with the crop function, but I think the resize won't allow that. As it turns out, I'm going to have to figure out how to make sure that the height and width in the resize are always integrally divisible by 2 and then correct the border adding or cropping as needed. I can do this, but right now I'm just too tired to deal with it, and more importantly, I can't get far enough along into the process to need to figure it out just yet since it craps out before it gets to the border or crop functions. Once I figure out those, I'll deal with the headache of the integral divide by 2 resolutions.)

Anyway, if someone can figure out what I am (or AVISynth is) doing wrong, I'd be terribly grateful. Perhaps I'm just getting too tired to see it, but I'd swear that no matter how hard I look, I wrote the actual function correctly (minus the integral divide by 2 resolution problem that I still haven't even run into.) When I try to follow the formula I put in with a calculator, I get the correct results, but it is apparently getting incorrect results. Here's my full code complete with as much white space and commentation as I could manage for hopefully maximum readability:

Code:
#Set user variable values
useBorders = 1  #Resize and maintain ratio via a crop (0) or border (1)
useBilinear = 1  #Resize using Point filter (0) or Bilinear filter (1)

targetWidth = 160  #Target width
targetHeight = 128  #Target height
targetFPS = 13.000  #Target framerate - Note:  Simple @ L3 suggests <= 15 FPS

#End of user variables
#Please modify nothing below this line unless you know what you are doing.

#------------------------------------------------------------------------------

#Start of script
videoIn = ColorBars(352,240)  #REMOVE ME LATER!!!
#videoIn = DirectShowSource("%VideoPathFile%")  #ADD ME LATER!!!

#YUY2 is required for some filters (like ConvertFPS) so we need to convert if
#the source is not YUY2.  The output will be YV12 for MPEG standards, so even
#if the source is RGB or YV12, this is probably a harmless conversion.
videoOut = (IsYUY2(videoIn) == true) ? videoIn : videoIn.ConvertToYUY2

#Convert to the target framerate with switch for the low framerate to output
videoOut = (Framerate(videoOut) == targetFPS) ?
\          videoOut : videoOut.ConvertFPS(targetFPS, zone=80)

#Resize with borders or cropping, depending on useBorders variable
videoOut = (useBorders == 1) ?
\          ResizeBorder(videoOut, targetWidth, targetHeight, useBilinear) :
\          ResizeNoBorder(videoOut, targetWidth, targetHeight, useBilinear)

#MPEG uses YV12.  I'm not sure if AVISynth has a better filter, but I suspect
#it would not be worse, so I'll just go ahead and convert to YV12.  It probably
#depends on what encoder you will be using.  Perhaps AVISynth is better?
videoOut = videoOut.ConvertToYV12

videoOut = (AudioRate(videoOut) == 44100) ? videoOut : videoOut.SSRC(44100)
videoOut = (AudioBits(videoOut) == 16) ? videoOut : videoOut.ConvertAudioTo16Bit

return(videoOut)
#End of script

#------------------------------------------------------------------------------

#Start of functions

#Resize the clip to target adding borders where needed
Function ResizeBorder(videoInput, outWidth, outHeight, useBilinear) {

  videoWidth = Width(videoInput)
  videoHeight = Height(videoInput)
  videoRatio = videoWidth / videoHeight
  targetRatio = outWidth / outHeight
  
  #What height do I resize to with the source aspect ratio but target width?
  resizeHeight = outWidth / videoRatio

  #Find out how much to add on each side
  eachSide = (videoRatio == targetRatio) ? 0 : (outHeight - resizeHeight) / 2

  videoOutput = (useBilinear == 1) ?
\               videoInput.BilinearResize(outWidth, resizeHeight) : 
\               videoInput.PointResize(outWidth, resizeHeight)

  videoOutput = videoOutput.AddBorders(0, eachSide, 0, eachSide)

  return videoOutput
}

#Resize the clip to target using clipping where needed
Function ResizeNoBorder(videoInput, outWidth, outHeight, useBilinear) {

  videoWidth = Width(videoInput)
  videoHeight = Height(videoInput)
  videoRatio = videoWidth / videoHeight
  targetRatio = outWidth / outHeight

  #What width do I resize to with the source aspect ratio but target height?
  resizeWidth = videoRatio * outHeight

  #Find out how much to subtract on each side
  eachSide = (videoRatio == targetRatio) ? 0 : (resizeWidth - outWidth) / 2

  videoOutput = (useBilinear == 1) ?
\               videoInput.BilinearResize(resizeWidth, outHeight) :
\               videoInput.PointResize(outWidth, resizeHeight)

  Crop(videoOutput, eachSide, 0, (eachSide * -1), -0)

  return videoOutput
}
#End of functions
 
Why do people love that Super program so much? I already knew about it. It's not actually the greatest thing since sliced bread believe it or not. In fact, I'll take nice standard stuff like VirtualDub with authors who will talk to you directly in project forums and listen to what users say as well as show their code for the world to see rather than trying to hide stuff from their users over something that needs ten pages of colored varying sized text explaining about how wonderful the authors think it is and saying the word "free" a little too much for my comfort (seriously, if they have to say "free" more than just once, you KNOW there's a catch however well it may be hidden.) However, that's neither here nor there. AVISynth is not an encoder, and Super cannot replace AVISynth as it does a COMPLETELY different thing (eg encoding vs video processing.) In fact, other encoders like VirtualDub are just as capable, but the point here is to create a somewhat universal script to be used for all videos. You see, most DAP devices -- mine included unfortunately -- require special settings to accept a video. These special settings require a modified version of VirtualDub or mencoder to work outside of the program that came with the player (which isn't a very good program, so I'll take VDub or mencoder any day of the year.) A closed source program like Super will never work because people are unable to modify it to work correctly and it's not actually as advanced as mencoder is (don't get me wrong, that's not necessarily a bad thing -- IMO mencoder goes too far. Luckily I'm using a nice simple frontend that requires only that I drag and drop the video file into the u3video.exe file to begin the encode process with all the appropriate settings in place for me.) Actually, funny thing about your post. Super even proves that it is no AVISynth replacement by making a big deal about the fact that it now supports using AVISynth scripts at the bottom of that page...

The frontend currently does not resize in quite the way I want, and I had a problem once or twice that was easily solved by proxying the video through AVISynth first. Plus I want a little more control over the process anyway. So it was my intention to create a nice standard script that should require nothing more than the replacement of the video's filename within it to work. In fact, it was my hope to convince the author to add support for an automatic building of such a file based on such universal code, but obviously that won't happen if the code doesn't work.
 
Back
Top