VideoHelp Forum
+ Reply to Thread
Results 1 to 14 of 14
Thread
  1. I'm about to start digitizing a large collection of my home videos including VHS, Hi8, VHS-C.

    Over the last few weeks, I've been doing a LOT of reading, researching, and testing learning how to use AviSynth and the various settings available within QTGMC, in particular, that control smoothing and noise/grain. It's all new to me.

    I know there is no such thing as a one-size-fits-all script for anything, but I wanted to make one as a "jumping off point" for myself to have at least the most common things available in a script that I can use and re-use for each of my videos.

    After testing some sample captures, I came up with the following script which covered most of the issues or needs I had so far, that I know of.

    Before I begin, I'd like to know:

    1. Is there anything that I'm doing that is WRONG (or should be done a different way), or anything that is going to otherwise mess up my videos in one way or another that is undesirable?
    2. Am I missing any major "things" that I should look into in addition to what's already here? i.e. Any "cannot live without" plugins for SD material not here?

    I was planning on creating two output files: One to ProRes for archiving/future editing (other computer is a mac). One to h264/mp4 for USB/TV/computer/smartphone playback. I've seen many people import AviSynth to VirtualDub for further processing, but I don't think I need to do anything else other than what's here for my needs. So, skipping that step if I can.

    Learning this in the past few weeks has been a little bit like drinking from a fire hose, so I appreciate any feedback from more experienced users. Thanks.

    Code:
    SetFilterMTMode("QTGMC", 2)  #set QTGMC in multithread mode
    Avisource("clip.avi")  #load clip
    Trim(100,50000)  #NOTE: temporarily disable QTGMC to get actual frame #s for trimming
    
    ConvertToYV12(interlaced=true)  #colorspace needed for certain filters
    AssumeTFF()  #top field first (most sources probably TFF except DV, probably BFF)
    
    #LoadCPlugin("C:\Program Files (x86)\AviSynth+\non auto load plugins\yadif.dll")  #For quick deint when testing
    #Yadif(mode=0)  #mode 1 = double frame rate, mode 0 = single frame rate
    
    QTGMC(Preset="slower", Edithreads=2)  #59.94 FPS Slower Preset *PREFERRED after testing, try TR2=0 if too clay-like for less output smoothing, or faster preset
    
    #Other options for QTGMC 
    #QTGMC(Preset="faster", Edithreads=2)  #59.94 FPS  *KEEPS MORE NOISE AND GRAIN
    #QTGMC(Preset="slower", EZDenoise=1.0, Grainrestore=1.0, Edithreads=2, showsettings=true)  #59.94 FPS noise and grain tweaking
    #QTGMC(Preset="slower", FPSDivisor=2, ShutterBlur=1, ShutterAngleSrc=180, ShutterAngleOut=180, Edithreads=2) #29.97 FPS extra blur settings smooth motion with fpsdivisor
    
    #Color correct and fix levels, temporarily enable histogram for checking
    #Tweak(bright=-12, cont=1.2, sat=1.2, coring=false)  #bright=blacks, cont=whites
    #Levels(18,1.0,235,0,255,coring=false)  #stretch black and white points out 
    ColorYUV(cont_y=39, off_y=2, cont_u=12, cont_v=12, gain_y=32, gamma_y=0) #analyze=true to display values
    
    #crop(mask) and resize
    Crop(8,0,-16,-8).AddBorders(12,4,12,4)
    video=Spline36Resize(640,height)   #16 less sharpen, 36 medium sharpen, 64 more sharpen
    #video=BilinearResize(640,480)  #won't sharpen as much as spline
    #video=LanczosResize(640,480)   #another option
    
    #generate intro 
    intro = BlankClip(video, length=300) # create black clip (300 frames) with same properties as existing clip
    intro = intro.Subtitle("Line 1\n" + \ 
                                    "Line 2\n" + \
                                    "Line 3\n" + \
                                    "Line 4\n" + \
                                    "Line 5", \
                                    lsp=30, font="Courier New", size=40, text_color=$FFFFFF, x=-1, y=175) # add font, size, x and y positions as desired
                                    
    intro.fadeio(20)+video.fadeio(20)  #fade in / out 20 frames
    
    #check levels/waveforms
    #Histogram("levels") #check levels
    #Histogram("audiolevels") #check audio levels  - should be around -15 to -12db with occasional peaks to -8db OK
    #Histogram()    #histogram/waveform on right
    #Turnright.Histogram.Turnleft()    #histogram/waveform on top
    
    PreFetch(4)
    Quote Quote  
  2. I didn't see any errors in the script. It ran fine when I used a test video. One thing you may not know: when you don't specify a stream by name the name "last" is used. So a sequence like:

    Code:
    Avisource("clip.avi")
    Trim(100,50000)
    is the same as:

    Code:
    last = Avisource("clip.avi")
    last = Trim(last,100,50000)
    Halfway through your script you start naming a stream "video". There's nothing wrong with that but you could just as well have relied on the implied last, as you do elsewhere in the script.

    In ColorYUV() you used both cont_y and gain_y. Those two features do the same thing, multiply Y values, except gain_y is based around zero, and cont_y is based around 128. In other words gain_y increases contrast by keeping 0 at 0 but making everything brighter than 0 brighter. Cont_y increases contrast by making everything darker than medium grey darker, everything lighter than medium grey brighter.

    Code:
    gain_y:  Y' = Y * gain
    cont_y:  Y'= ((Y - 128) * gain) + 128
    Generally, it's less confusing if you use only one of those -- you don't have to remember the order of precedence (the functions are performed in a specific order internally, not the order you list them in the call). I usually use just gain_y followed by off_y. Gain is performed before offset, just as multiplication is performed before addition in algebra:

    Code:
    Y' = Y * gain + offset
    means:
    Code:
    Y' = (Y * gain) + offset
    not:
    Code:
    Y' = Y * (gain + offset)
    You may know this but the FadeIn() and FadeOut() filters add one frame to the specified clip. FadeIO() adds two. So your 300 frame intro becomes 302 frames after FadeIO(20). And your main "video" clip is getting two extra frames too. Use the "zero" versions of those functions to avoid the extra frames: FadeIn0(), FadeOut0(), FadeIO0().
    Quote Quote  
  3. Thanks for taking the time to respond Jagabo.


    Originally Posted by jagabo View Post
    One thing you may not know: when you don't specify a stream by name the name "last" is used.
    Halfway through your script you start naming a stream "video". There's nothing wrong with that but you could just as well have relied on the implied last, as you do elsewhere in the script.
    I kind of knew that, but somewhere along the way I added "video" before I really understood what I was doing, or that I could actually use the word "last". So I removed "video=" on the resize line above and changed all instances of "video" to "last":

    Code:
    intro = BlankClip(last, length=300) # create black clip (300 frames) with same properties as existing clip
    intro = intro.Subtitle("Line 1\n" + \ 
                                    "Line 2\n" + \
                                    "Line 3\n" + \
                                    "Line 4\n" + \
                                    "Line 5", \
                                    lsp=30, font="Courier New", size=40, text_color=$FFFFFF, x=-1, y=175) # add font, size, x and y positions as desired
                                    
    intro.fadeio0(20)+last.fadeio0(20)  #fade in / out 20 frames

    You may know this but the FadeIn() and FadeOut() filters add one frame to the specified clip. FadeIO() adds two. So your 300 frame intro becomes 302 frames after FadeIO(20). And your main "video" clip is getting two extra frames too. Use the "zero" versions of those functions to avoid the extra frames: FadeIn0(), FadeOut0(), FadeIO0().
    Did not know this one. I changed it to the 0 versions, but I don't really understand why it matters if those extra frames are added without the 0 version. What problems does that cause?


    In ColorYUV() you used both cont_y and gain_y. Those two features do the same thing, multiply Y values, except gain_y is based around zero, and cont_y is based around 128. In other words gain_y increases contrast by keeping 0 at 0 but making everything brighter than 0 brighter. Cont_y increases contrast by making everything darker than medium grey darker, everything lighter than medium grey brighter.

    Code:
    gain_y:  Y' = Y * gain
    cont_y:  Y'= ((Y - 128) * gain) + 128
    Generally, it's less confusing if you use only one of those -- you don't have to remember the order of precedence (the functions are performed in a specific order internally, not the order you list them in the call). I usually use just gain_y followed by off_y. Gain is performed before offset, just as multiplication is performed before addition in algebra:
    This is by far the thing I've had the most trouble wrapping my head around, along with when to use ColorYUV vs Levels vs Tweak when trying to correct black levels, brightness/contrast, and saturation.

    I sort of get what you're saying about cont_y (and even read on the wiki page that "Although it is possible, it doesn't make sense to apply this setting to the luma of the signal.") but by adjusting that one value, it seemed to correct the issue I had with my video. I had the proc amp settings a little off during capture so my blacks were too high, and I also felt things could have been a little brighter overall. So increasing this value helped both things at once.. made blacks (and darks) blacker and whites (and brights) brighter (truly what you would think increasing "contrast" would do logically). And saturation needed to be increased as well, so I increased both cont_u and cont_v.

    I am trying to make the same adjustment with gain_y, off_y, and gamma_y and not really getting how to do that because all 3 values seem to shift the entire luma range left or right (looking at the waveform), difference being that gain shifts as a multiplier...?

    So, I guess I don't really understand the difference between gain_y and off_y for this reason..or how to use these 2 values in conjunction to do what I want.

    Or am I using the wrong filter to do what I want? I also experimented with Levels(18,1.0,220,0,255,coring=false) to stretch blacks down and whites up. Would that be more appropriate for what I'm trying to do?

    I am not sure why this isn't clicking for me. I'm much more familiar with Photography and Photoshop terms and trying to correlate the settings to things I know and understand (like, you can accomplish sort of the same thing by adjusting the brightness/contrast controls as adjusting levels, but levels gives you better control) but... I don't know, I just feel like I'm just moving sliders (i.e. in AvsPmod) not really understanding what I'm doing til it looks decent, when I'd rather approach it with a better grasp on what I'm doing.
    Quote Quote  
  4. Video Restorer lordsmurf's Avatar
    Join Date
    Jun 2003
    Location
    dFAQ.us/lordsmurf
    Search Comp PM
    I don't see anything in there for chroma shifting, something usually needed for VHS source.
    Want my help? Ask here! (not via PM!)
    FAQs: Best Blank DiscsBest TBCsBest VCRs for captureRestore VHS
    Quote Quote  
  5. Originally Posted by lordsmurf View Post
    I don't see anything in there for chroma shifting, something usually needed for VHS source.
    Thanks. I haven't come across that yet - been experimenting mostly on 8mm tapes so far.

    Is that most-easily corrected by using the ChromaShift plugin? Or is that too obvious?
    Quote Quote  
  6. Originally Posted by Christina View Post
    Is that most-easily corrected by using the ChromaShift plugin?
    Yes, ChromaShift() or ChromaShiftSP().

    Regarding ColorYUV(), put this in an AVS file and view the results:

    Code:
    function GreyRamp()
    {
       black = BlankClip(color=$000000, width=1, height=256, pixel_type="RGB32", length=512)
       white = BlankClip(color=$010101, width=1, height=256, pixel_type="RGB32", length=512)
       StackHorizontal(black,white)
       StackHorizontal(last, last.RGBAdjust(rb=2, gb=2, bb=2))
       StackHorizontal(last, last.RGBAdjust(rb=4, gb=4, bb=4))
       StackHorizontal(last, last.RGBAdjust(rb=8, gb=8, bb=8))
       StackHorizontal(last, last.RGBAdjust(rb=16, gb=16, bb=16))
       StackHorizontal(last, last.RGBAdjust(rb=32, gb=32, bb=32))
       StackHorizontal(last, last.RGBAdjust(rb=64, gb=64, bb=64))
       StackHorizontal(last, last.RGBAdjust(rb=128, gb=128, bb=128))
    }
    
    
    function AnimateGain(clip vid, int gain)
    {
    	ColorYUV(vid, gain_y = gain)
    	Subtitle("gain="+String(gain))
    }
    
    
    function AnimateOff(clip vid, int off)
    {
    	ColorYUV(vid, off_y = off)
    	Subtitle("off="+String(off))
    }
    
    function AnimateCont(clip vid, int cont)
    {
    	ColorYUV(vid, cont_y = cont)
    	Subtitle("cont="+String(cont))
    }
    
    
    function AnimateGamma(clip vid, int gamma)
    {
            gamma = gamma < -255 ? -255 : gamma
    
    	ColorYUV(vid, gamma_y = gamma)
    	Subtitle("gamma="+String(gamma))
    }
    
    #ImageSource("grayramp.png", start=0, end=512, fps=23.976) 
    GreyRamp()
    ConvertToYUY2(matrix="PC.601")
    
    v1=Animate(0,512, "AnimateGain", -256, 256)
    v2=Animate(0,512, "AnimateOff", -256, 256)
    v3=Animate(0,512, "AnimateCont", -256, 256)
    v4=Animate(0,512, "AnimateGamma", -256, 256)
    
    StackHorizontal(v1,v2,v3,v4)
    
    TurnRight().Histogram().TurnLeft()
    
    ConvertToRGB(matrix="pc.601")
    Image
    [Attachment 54919 - Click to enlarge]


    Things to note:

    1) With gain_y 0 always remains at 0. The rest of the values are multiplied by the same amount.

    2) With off_y the same values is added or subtracted from all Y values. The slope of the line doesn't change.

    3) With cont_y 128 remains at 128. All other values are multiplied by the same amount. Note the slope of the line is the same as with gain_y, just the mid point changes. Any cont_y value can be achieved with a combination of gain_y and off_y. For example, ColorYUV(cont_y=256) gives the same result as ColorYUV(gain_y=256, off_y=-128).

    4) With gamma_y 0 and 255 stay where they are. Between those the line is bent to increase or decrease shadow detail.

    5) In all cases the final output values are clamped between 0 and 255.
    Quote Quote  
  7. Thanks. I will dive into this later. Appreciate the help!

    Can you also explain the effect of the additional frames on fadeio without the 0?
    (Edit: i.e. Why is it bad?)
    Quote Quote  
  8. Originally Posted by Christina View Post
    Can you also explain the effect of the additional frames on fadeio without the 0?
    For one, if there's audio it'll throw the audio synch off. And if you do filtering on a specific ranger of frames, unless you're careful you might wind up doing that filtering on different frames than intended.
    Quote Quote  
  9. Originally Posted by jagabo View Post
    Regarding ColorYUV(), put this in an AVS file and view the results:
    I got an error when I loaded that script:

    "Script error: Invalid arguments to function 'animate'.
    line 48

    I was able to fix it by adding "last" to each animate function. It appears to now be doing what you intended.

    Code:
    v1=Animate(last, 0,512, "AnimateGain", -256, 256)
    v2=Animate(last, 0,512, "AnimateOff", -256, 256)
    v3=Animate(last, 0,512, "AnimateCont", -256, 256)
    v4=Animate(last, 0,512, "AnimateGamma", -256, 256)
    I'm not sure why it didn't work for me if it worked for you but I have you to thank for even knowing to try to put "last" in there With that, one thing I don't understand is why I can use "last" every time, and in each case it's still referring back to the original GreyRamp rather than the line above (i.e. why doesn't v2 line refer to v1 as "last")

    Anyway, this is extremely helpful. You should be a teacher. Thank you!
    Quote Quote  
  10. Originally Posted by Christina View Post
    I was able to fix it by adding "last" to each animate function. It appears to now be doing what you intended.

    Code:
    v1=Animate(last, 0,512, "AnimateGain", -256, 256)
    v2=Animate(last, 0,512, "AnimateOff", -256, 256)
    v3=Animate(last, 0,512, "AnimateCont", -256, 256)
    v4=Animate(last, 0,512, "AnimateGamma", -256, 256)
    I'm not sure why it didn't work for me if it worked for you
    It must be an Avisynth version difference?

    Originally Posted by Christina View Post
    With that, one thing I don't understand is why I can use "last" every time, and in each case it's still referring back to the original GreyRamp rather than the line above (i.e. why doesn't v2 line refer to v1 as "last")
    The script specifies a name for the output of each call to Animate(): v1, v2, v3, v4. So the output of each Animate() is a new stream. Last remains unchanged.

    Just to be sure... are you seeing animations like in the attached video?
    Image Attached Files
    Quote Quote  
  11. Yup! That's exactly what I see when I run it. I'm using AviSynth+ 3.6.1. Syntax for Animate shows it needs a clip as the first argument... maybe your version assumes last for clip if it's not there, and mine doesn't.

    I get what you're saying about "last" remaining unchanged if you assign a new name for outputs that come after it. Originally I just thought it referred to the last thing in the line above what you were doing even if you had given it its own name. Thanks once again.
    Quote Quote  
  12. REVISED SCRIPT!

    So, based on the feedback above, here is my revised baseline AviSynth script for my analog home movie collection. I am sure this will grow as I go along, but this gives a good starting point for the most common needs with analog home videos in decent shape.

    I am posting here again in case this may be helpful to someone else in the future, and I added more comments to explain a little more what's going on. It's getting a little busy-looking but I think the comments help if you're new!

    My script trims a portion out of a longer video and adds a black intro with a multi-line title that fades in and out. It deinterlaces with QTGMC, adjusts brightness/contrast/saturation etc, masks edges and centers video with crop / addborders, and resizes to 640x480 square pixels, assuming 720x480 NTSC interlaced source (captured with lossless codec). I hope this helps someone else at some point!

    The ONLY thing left that I don't understand if I should be doing or not in this script is coring=false. I know what it does, I just don't know if/when I need that or not.

    Code:
    SetFilterMTMode("QTGMC", 2)             #set QTGMC in multithread mode
    Avisource("clip.avi")                   #load clip
    Trim(0,3000)                            #NOTE: temporarily disable QTGMC to get actual frame #s for trimming
    
    ConvertToYV12(interlaced=true)          #colorspace needed for certain filters
    AssumeTFF()                             #top field first (most sources probably TFF except DV, probably BFF)
    
    /* For quick deinterlacing when testing */ 
    #LoadCPlugin("C:\Program Files (x86)\AviSynth+\non auto load plugins\yadif.dll") 
    #Yadif(mode=1)                          #mode 1 = double frame rate, mode 0 = single frame rate
    
    QTGMC(Preset="slower", Edithreads=2)    #59.94 FPS Slower Preset *PREFERRED after testing, try TR2=0 if too clay-like for less output smoothing, or faster preset
    
    /* Other options for QTGMC */
    #QTGMC(Preset="faster", Edithreads=2)   #59.94 FPS  *KEEPS MORE NOISE AND GRAIN
    #QTGMC(Preset="slower", EZDenoise=1.0, Grainrestore=1.0, Edithreads=2, showsettings=true)    #59.94 FPS noise and grain tweaking
    #QTGMC(Preset="slower", FPSDivisor=2, ShutterBlur=1, ShutterAngleSrc=180, ShutterAngleOut=180, Edithreads=2)   #29.97 FPS extra blur settings smooth motion with fpsdivisor
    
    /* Color correct and fix levels, temporarily enable histogram for checking */
    Tweak(bright=0.0, hue=0.0, cont=1.0, sat=1.0, coring=false)   #bright=blacks, cont=whites
    #Levels(16,1.0,235,0,255,coring=false)                        #stretch black and white points out from input to output   ex. 16 down to 0, 235 up to 255
    ColorYUV(gain_y=0, off_y=0, cont_u=0, cont_v=0, gamma_y=0)    #analyze=true to display values
    
    /* Chroma Shift for problematic VHS */
    #ChromaShift(C=0, U=0, V=0, L=0)        #C = U and V together. C, U, V left and right. L is up and down. Even numbers only.
    #ChromaShiftSP(x=0, y=0)                #same as above + sub pixel accuracy, progressive sources only.
    
    /* crop(mask) and resize  - assuming source of 720x480, resize to 640x480 with square pixels to correct display aspect ratio */
    Crop(8,0,-16,-8).AddBorders(12,4,12,4)  #mask edges without changing size
    Spline36Resize(640,height)              #16 less sharpen, 36 medium sharpen, 64 more sharpen
    #BilinearResize(640,height)             #won't sharpen as much as spline
    #LanczosResize(640,height)              #another option
    
    /* generate intro */
    intro = BlankClip(last, length=300)     #create black clip (300 frames ~5 seconds) with same properties as existing clip - reduce to 150 if using 29.97 FPS
    intro = intro.Subtitle("Line 1\n" + \ 
                                    "Line 2\n" + \
                                    "Line 3\n" + \
                                    "Line 4\n" + \
                                    "Line 5", \
                                    lsp=30, font="Courier New", size=40, text_color=$FFFFFF, x=-1, y=175) # add font, size, x and y positions as desired
                                    
    intro.fadeio0(30)++last.fadeio0(30)      #fade in / out 30 frames, zero version = no extra frames added, needed to keep audio sync
    
    /* check levels/waveforms, use when adjusting levels above */
    #Histogram("levels")                    #check levels
    #Histogram("audiolevels")               #check audio levels  - should be around -15 to -12db with occasional peaks to -8db OK
    #Histogram()                            #histogram/waveform on right
    #Turnright.Histogram.Turnleft()         #histogram/waveform on top
    
    PreFetch(4)                             #depends on your cpu cores, adjust up or down for performance/stability
    Last edited by Christina; 17th Sep 2020 at 22:43. Reason: Added ++ on append per jagabo
    Quote Quote  
  13. Some very old players had troubles with superblacks and superwhites -- rendering them with grossly incorrect colors (a superblack might show as white, and vice versa). I haven't seen any modern player do that. I would leave coring=false, especially if you are going to follow up with more levels adjustments.

    Oh, when appending clips with audio you should use ++ instead of +, to assure A/V sync.

    Code:
    intro.fadeio0(30)++last.fadeio0(30)
    Quote Quote  
  14. Good to know! I revised my script above to include the ++. THANK YOUUUUUU!
    Quote Quote  



Similar Threads

Visit our sponsor! Try DVDFab and backup Blu-rays!