View Full Version : VHS post processing
Lucky38
16th February 2026, 15:52
Zgraj VirtualDubem bezstratnie (Huffyuv, FFV1, ewentualnie ProRes). W innych wątkach znajdziesz mnóstwo informacji jak to zrobić. Takie pasy występują też przy kiepskim VCR.
dzieki za podpowiedzi.
edit1: czy wedlug tego powinienem robic?
https://www.doom9.org/index.html?/capture/capturing_vdub.html
pytam, bo nigdy tego nie robiłem
Columbo
16th February 2026, 17:01
Forum rule 13: only English is allowed. Thank you.
Lucky38
16th February 2026, 20:24
sorry. I will remember.
Sharc
17th February 2026, 10:29
https://mega.nz/folder/DYUEBAbD#NFXbMl2irutkz91ayZPn9A
Lucky38
18th February 2026, 14:37
https://mega.nz/folder/DYUEBAbD#NFXbMl2irutkz91ayZPn9A
@Sharc,
looks good.
Could you please share script you have used to clean this out?
Lucky38
18th February 2026, 14:41
i have got even worse vhs
https://mega.nz/file/xQglUQSB#cSf_zxfJpZJHw3-mYPT8q6a9VOKpEmTRHyP1-Wu-SQo
Sharc
18th February 2026, 17:08
@Sharc,
looks good.
Could you please share script you have used to clean this out?
Oh, I deleted the script. So from memory the steps were:
- downscale vertically and re-upscale, which blurs the horizontal stripes
- Then apply some denoiser to clean it up a bit
- Also, I think I reduced the color saturation as the clip was oversaturated.
But principally you should think about recapturing the tape properly into lossless interlaced 4:2:2 format to begin with..... and only then postprocess it.
AVIL
19th February 2026, 21:25
Hi:
A quick denoise for your video:
p1=avisource("W:\sample_vhs.avi").converttoyv12()
p2=p1.mergechroma(p1.frfun7(tuv=128.0))
p2.vhsclean()
You can grab vhsclean from https://forum.doom9.org/showthread.php?t=185261
Busty
12th March 2026, 00:18
I'd like to add those diagnostics to my inventar, that shows all those clip info, including the field order which is shown in Emulgators screenshot on page 2 of this thread. I'm talking about the info in the green line at the top of the screenshot. And while i'm at it, the histograms on top and on the side of the frame would be nice to have, too.
can I add them to a script somehow?
https://forum.doom9.org/showthread.php?p=2019566#post2019566
StainlessS
12th March 2026, 02:23
I'd like to add those diagnostics to my inventar,
PortalScope:- https://forum.doom9.org/showthread.php?t=186015
EDIT: Similar-ish,
VideoTek (Avisynth and MPV Waveform Monitor) :- https://forum.doom9.org/showthread.php?t=175249
Tempter57
12th March 2026, 08:59
https://mega.nz/file/JdBRzDJQ#nmJg67FetxfPyjFJMKc9pdxqalIps17HvYPwKXwQa3M
https://mega.nz/fm/YaYG0LTD
The script is based on idea by Dogway
prefix="C:\Program Files (x86)\AviSynth+"
AddAutoloadDir(prefix+"plugins64")
setmemorymax(8000)
FFvideoSource("C:\Users\Asus\Downloads\sample_vhs.mkv", rffmode=0, threads=1).AssumeFPS(25.000)
ConvertToYV16()
SmoothTweak(contrast=1.0, saturation=0.65, hue1=-1, hue2=1, HQ=true,TVrange=false, Limiter=False)
LevelsLumaOnly(input_low=0, gamma=1.0, input_high=244, output_low=16, output_high=235, coring=false, dither=true)
spline36resize(720, 288)
bifrost(interlaced=false).ASTDR(strength=5, tempsoftrad=3, tempsoftth=7, tempsoftsc=6, tht=255, dcn=15, edgem=false, exmc=false)#.MergeLuma(video_org_sep_even, 0.66).MergeChroma(video_org_sep_even, 0.33)
SceneStats("Range+Stats")
Stage=06
PREl1 = ex_autolevels( true ,true, true,Deflicker=true,tv_out=false)
PREl2 = ex_autolevels(PREl1,false,true,false,Deflicker=true,tv_out=false)
PREmo = ex_Median(PREl2,mode="IQMST", UV=3,thres=min(100,(Stage*10)))
PREm = ex_blend(PREl2,PREmo,"blend",opacity=0.3).ex_sbr(1,UV=3)
PREs = SMDegrain(mode="TemporalSoften", tr=6, thSAD=(Stage*70), thSADc=(Stage*60), thSCD1=max(400,(Stage*80)), Str=2.0, contrasharp=false, LFR=false, DCTFlicker=false, refinemotion=false, truemotion=true, blksize=16, search=5, pel=2, subpixel=3, prefilter=PREmo, chroma=true, plane=4, gpuid=-1, interlaced=false)
SMDegrain(mode="MDegrain", tr=6, thSAD=(Stage*60), thSADc=(Stage*50), thSCD1=max(400,(Stage*70)), Str=2.0, contrasharp=true, LFR=true, DCTFlicker=true, refinemotion=true, truemotion=true, blksize=16, search=5, pel=2, subpixel=3, mfilter=PREm, prefilter=PREs, chroma=true, plane=4, gpuid=-1, interlaced=false)
ex_unsharp(Stage/40.).ex_unsharp((Stage/20.),Fc=width()/1.5)
nnedi3_rpow2(rfactor=2,cshift="lanczosresize",fwidth=720,fheight=576)
# ==== Sharpening ====
F3KDB_3(range=20, Y=32, Cb=24, Cr=24, grainY=24, grainC=16, dither_algo=2)
ConverttoYV12()
Prefetch(8, 16)
Script for sample_2.mkv
prefix="C:\Program Files (x86)\AviSynth+\"
AddAutoloadDir(prefix+"plugins64")
setmemorymax(8000)
FFvideoSource("C:\Users\Asus\Downloads\sample_2.mkv", rffmode=0, threads=1).ChangeFPS(25.000)
Jinc144Resize(640, 480, 0,0,-80,-96)
ConvertToYV16()
SmoothTweak(contrast=1.0, saturation=0.89, hue1=-0, hue2=0, HQ=true,TVrange=false, Limiter=False)
LevelsLumaOnly(input_low=14, gamma=1.0, input_high=237, output_low=16, output_high=235, coring=false, dither=true)
SpotLess(BlkSz=12, OLap=4, pel=2, Tm=false, Bblur=0.0, ThSAD=1000, RadT=1)
MCTD (settings="high")
mergechroma(aWarpSharp2(depth=8, blur=3, type=1)).EEDI3()
turnright()
mergechroma(aWarpSharp2(depth=8, blur=3, type=1)).EEDI3()
turnleft()
F3KDB_3(range=20, Y=32, Cb=24, Cr=24, grainY=24, grainC=16, dither_algo=2)
ConverttoYV12()
Prefetch(8, 16)
Busty
12th March 2026, 10:47
yes, thank you Stainless, great! Thanks to Emulgator and hanfrunz, too!
Now I see that my captures all are BFF. This either happens during capture or during conversion to utvideo with ffmpeg.
I do the conversion like this:
(ffmpeg -i video.mov -c:v utvideo -vf format=yuv422p -an video.avi)
When I play them in VLC with deinterlace on and set to yadif (2x), the video playback is jerky (kinda back and forth stuttering)
I can get rid of that with a small script that goes like this:
SeparateFields()
Trim(1,0)
Weave()
They play fine then with yadif (2x), but PortalScope still reports them as BFF.
Wouldn't it be better to convert them to TFF and if so, how can I achieve that?
StainlessS
12th March 2026, 12:21
I think (but am not sure) that BFF is the Avisynth default unless you use eg "AssumeTFF",
Perhaps Portalscope is just reporting the default field order as it has not been changed by you (or script).
SeparateFields()
Trim(1,0)
Weave()
AssumeTFF()
Above is maybe not the best fix (maybe an odd field [EDIT: or more likely duplicate field] left at end of clip).
@Emulgator, care to comment. :)
Emulgator
13th March 2026, 14:36
Yes, Portalscope just reports what AviSynth thinks what it is using GetParity()
So Tempter57's source might not be first generation, and Busty's Source:
AviSynth (and Portalscope) do not know what field order any capture card delivered in reality,
AviSynth just assumes BFF for anything that could have been DV-AVI and passes that down the river,
right or wrong, until someone comes along and checks for real, and corrects if necessary.
As always: Separate Fields() to find out what the real field order is, then AssumeTFF() or BFF().
From then on the flagging can be assumed correct.
johnmeyer
13th March 2026, 17:28
... As always: Separate Fields() to find out what the real field order is, then AssumeTFF() or BFF().
From then on the flagging can be assumed correct.Exactly. While people are doing less with interlaced video these days, that advice should be given to everyone who ever encounters interlaced video for the first time. I have seen WAY too much video that was edited using the wrong field order and you then end up with all those strange artifacts when the camera pans horizontally.
Busty
14th March 2026, 22:10
Thanks Emulgator and johnmeyer. I tried that and PortalScope still reports BFF after SeperateFields(). However, for VLC playing it smoothly with yadif2, I need to add AssumeTFF after the file input. I can add AssumeTFF or AssumeBFF at the end without noticing any change, it plays fine either way.
I mean, I am fine with adding AssumeTFF after file input, I was just wondering if this introduces any problems I don't think/know of right now.
Busty
21st April 2026, 14:51
ok, onto the next issue while on my quest to search for my post processing workflow:
I'd like to use QTGMC for some videos, but run into a problem: The lower half of the frame has annoyimg artefacts, as seen in the screenshot. The upper half is fine. When I convert to YV12 or when I use SourceMatch=0 it looks fine. With YV24 it's even worse, then the upper right quarter is affected too.
Obviously, I would like to use YV16 or YUY2 and SourceMatch=3
This happens with AviSource and LWLibavVideoSource as input.
Does someone know what I can do about it?
https://limewire.com/d/sXh1r#iQSfoltn6P
Sharc
21st April 2026, 17:05
ok, onto the next issue while on my quest to search for my post processing workflow:
I'd like to use QTGMC for some videos, but run into a problem: The lower half of the frame has annoyimg artefacts, as seen in the screenshot. The upper half is fine. When I convert to YV12 or when I use SourceMatch=0 it looks fine. With YV24 it's even worse, then the upper right quarter is affected too.
Obviously, I would like to use YV16 or YUY2 and SourceMatch=3
This happens with AviSource and LWLibavVideoSource as input.
Does someone know what I can do about it?
https://limewire.com/d/sXh1r#iQSfoltn6P
Upload a snippet (few seconds) of the source video to a filehoster so users can check. Pictures don't reveal much.
Emulgator
21st April 2026, 18:08
This was a plane rendering fault, mvtools2 IIRC ?
Update all concerning plugins. Later versions should be free of that.
Busty
22nd April 2026, 21:32
Hey Sharc, I was just about to upload a snippet of the video when I read Emulgator's comment and tried that first. Good call, there were lots of plugins to be updated! Still, the issue remained after updating every dependency for QTGMC. But recently, I had the occasion where it wasn't enough to update a plugin, I additionally had to remove other versions, I think it was masktools or mt_masktools which got in the way of masktools2. Might have been a different plugin.
Long story short, I updated all required plugins, tossed everything else out of the plugins folder and now it seems to work properly.
So, thanks again, Emulgator, your input is appreciated as always!
Busty
27th April 2026, 13:26
QMGMC is working, but now I experience changing colors in every other frame.
Maybe this is even present in the original file already. When I play the unchanged file in VLC with yadif(x2), I see the same color problem. So this might be happening during capture, though I wouldn't know why and how to avoid it.
Does anyone know what causes this and how to get rid of it?
This time with 10 sec snippets :-)
befroeQTMGC: https://limewire.com/d/hCWGH#2eL1viXFBK
afterQTGMC: https://limewire.com/d/7vzfl#JiJncMfU9R
Sharc
27th April 2026, 19:44
The problem is in the source. One field has a tint shift compared to the other field. You can try to tweak the color of one of the fields for a better match.
Does this look any better to you?
https://mega.nz/file/vQEyHSwK#UktTn3HNxGAHcFjNY3Rta8VWvxchUuaLCzbB8tofVSI
Busty
27th April 2026, 21:20
Thanks for looking at and playing with my files, Sharc. And yes, your file does look way better, I wouldn't notice that problem with this one. Could you share what you did exactly? I guess that would help me a lot.
Most likely I have this problem with all my captures then, but only notice it when processing them as 50fps.
I can rule out the VCR and TBC since I used different VCRs and also see this on captures without TBC. I'm suspecting my capture card or conversion from apple quicktime to utvideo.
Sharc
28th April 2026, 08:04
Something like this:
AVISource("beforeQTGMC.avi")
assumeBFF()
separatefields()
e=selecteven()
o=selectodd()
e=mergechroma(e,o,1.0) #copy the chroma of the odd field to the even field
interleave(e,o).weave() #re-interlace
qtgmc()
#optionally add derainbow/denoise filter(s) here ....
Busty
28th April 2026, 09:27
Thank you, Sharc.
While this is definitely an upgrade, it means that I loose some chroma information and I might need to check what happens at scene changes with this merged chroma.
So finding what causes this would still be preferable. I will check if this happens with a different codec during capture too and with a different capture card and report back.
I narrowed it done to the capture card. I checked three units of the card, they all have the same outcome, while a different card (Aurora Fuse) with a different driver looks fine. I also let the DC30 capture with a different driver and the issue is also present with that other driver. Unfortunately, I would have to run the other (Aurora) card on an older system and can't get it to work without getting substantial dropped frames. Also, while colors seem fine, my impression is that with the Aurora card, everything does look a bit worse overall. So it wouldn't be an ideal switch to begin with.
So I guess I live with this flaw. Still, I'd like to adress it, to make the impact as small as I can get it. For this goal, I'd like to tweak the colors of only the, let's say, odd field. I imagine that the tint is always the same on all captures, although I need to check that.
Now my scripting abilities are very limited, I tried to make a script that manipulates the color of odd fields only, but failed. Anything I try affects the even fields, too.
Can someone help me with the right syntax to achieve that?
Edit: after closely reviewing my test captures, I have to correct myself. It's not the capture card(s), it's also present with the Aurora card.
I noticed too, that every other frame is sharper than the other. Would that maybe point to video heads?
.... I tried to make a script that manipulates the color of odd fields only, but failed. Anything I try affects the even fields, too.
Can someone help me with the right syntax to achieve that?
Try this:
<your source filter here>
assumeBFF() #set the field order acc. your source
separatefields()
e=selecteven() #even fields (0,2,4,6 .....)
o=selectodd() #odd fields (1,3,5,7 .....)
o=o.<your tweaking filter for the odd fields here>, for example tweak(hue=4)
interleave(e,o) #restore the fields sequence (0,1,2,3,4,5......)
weave() #reinterlace
Edit: after closely reviewing my test captures, I have to correct myself. It's not the capture card(s), it's also present with the Aurora card.
Capture cards capture the video field by field by field ...(0,1,2,3,4,5 .....). They don't distinguish between even and odd fields or process these differently
Maybe heads/track misalignment of the camera or of the VCR. I don't know.
Thank you Sharc, your input is helpful to me. Got the script working, thanks for that, too:-) I'll play around a bit with settings and see if I can get somewhere with that.
Sharc
10th May 2026, 05:47
Another approach would be to replace the bad fields with a motion interpolated version of adjacent good fields.
I may return to it if you don't succeed in a few days.
Busty
14th May 2026, 13:18
That would be a definitive upgrade to just replacing the field.
In the meantime, I didn't make a lot of progress. When I lower red in one field, it becomes too green before the red level is right. Lowering the saturation affects both planes and is instantly visible. I tried ColorYUV and Tweak.
I think I just need to lower reds a little, maybe increase yellow, too, but without affecting green or blue.
It might work out better in RBG colorspace and my impression is that there are lots of possibilies, but which approach would be the most suitable one? A suggestion which plugin to use would be very welcome. I wouldn't want t o convert the whole clip to RGB, just process chroma on one field and then convert that back, leaving everything else in YUV, if possible.
I noticed another thing, too. I did a different processing of that same clip before and it didn't show that annoying color flickering. The fields had the same problem, e. g. one is more red than the other, but viewing it in 50fps did not result in flickering, at least none that I saw. I didn't use QTGMC but EZDenoise on that one. So it might be enough to get the fields match better (not necessarily perfect) and tweak my denoising settings to avoid this distracting flickering.
Emulgator
14th May 2026, 13:45
Only taking manual care of the field chroma mismatch, not caring about chroma placement restoration (unsmearing, shifting) so far, and just throwing any untuned QTGMC on it:
P.S. Well, couldn't resist:
AssumeBFF()
SeparateFields()
Even=Tweak(SelectEven(),hue=-2.0,sat=1.05)
Odd=Tweak(SelectOdd(),hue=2.0,sat=1.0)
# Plus the Sharc approach of chroma merging maybe ? Up to you. I am interleaving straight here.
Interleave(Even,Odd)
Weave()
ChromaShiftSP(X=3.0, Y=3.0)
smoothdebug=0 #0 no Diagram, 1 = Curve only, 2: Tweak only, 3: Both, 4: portalscope
ShowSmoothCurveDiagram=smoothdebug==1 ? true : smoothdebug==3 ? true : false
ShowSmoothTweakDiagram=smoothdebug==2 ? true : smoothdebug==3 ? true : false
smoothdebugwidth=1920
smoothdebugheight=1080
SmoothCurve16(ConvertTo16bit().ConvertToStacked(), \
Ycurve="0-0;16383-15000;24575-24575;42000-45000;65535-65535", \
Ucurve="0-0;8191-8191;16383-16383;22575-24575;32000-32767;37000-40959;49151-52000;57343-57343;65535-65535", \
Vcurve="0-0;8191-8191;16383-14383;24575-21575;32000-32767;40959-40959;49151-49151;57343-57343;65535-65535", \
limiter=false, HQ=true, interp=100, debug=ShowSmoothCurveDiagram, screenW=smoothdebugwidth, screenH=smoothdebugheight)
ConvertFromStacked()
Smoothdebug==4 ? portalscope() : NOP()
propSet("_FieldBased",1)
QTGMCp()
Sharc
15th May 2026, 10:46
Here a version with chroma interpolation, means substituting the chroma of the "bad" field with motion interpolated chroma of the "good" field. (No other color tweaking applied):
https://mega.nz/file/DdcjFTTa#IFVAPbR3hn7bvtudnjIlyNwWVU6QD4f9n7GP7mcGNFc
ConverttoYV16(interlaced=true)
assumeBFF()
SeparateFields()
ipol = Interpol_RIFE(SelectOdd().AssumeFrameBased()).SelectOdd().Loop(2,0,0)
even = MergeChroma(SelectEven(), ipol)
Interleave(even,SelectOdd())
Weave()
QTGMC(preset="slow")
###########
function Interpol_RIFE(clip source)
{
source.z_ConvertFormat(pixel_type="RGBPS", colorspace_op="601:auto:auto:limited=>rgb:same:same:full")
RIFE(model=5, sc=false)
z_ConvertFormat(pixel_type=source.pixeltype, colorspace_op="rgb:auto:auto:full=>601:same:same:limited")
}
##########
Busty
16th May 2026, 13:14
That's what I love this forum for! You guys take problem somenone else has as a challenge. Quite the professional curiosity.
Thank you Emulgator & Sharc for playing with my files.
@ Emulgator, I couldn't test the whole script because I get an error, that there is no function named "ex_bs"
The tweaking part at the beginning looks like a great improvement for this sample. I tested it on a different capture and it didn't translate, unfortunately.
Is there an easy way to adjust saturation for one plane only?
And you write I could combine it with Sharc's merging, but as far as I understand it, it's one way or the other, right? I mean, I either change colors of a field OR discard the whole field and use a new one, no sense to tweak colors on a newly generated field, or am i missing something here?
@ Sharc, I installed the initial version of rife, as it's the only only for x86. Your script gives me the error "there is no function naned z_ConvertFormat"
Anything I can do about that?
Sharc
16th May 2026, 13:56
@ Sharc, I installed the initial version of rife, as it's the only only for x86. Your script gives me the error "there is no function naned z_ConvertFormat"
Anything I can do about that?
Download the Avisynth plugin Avsresize
http://avisynth.nl/index.php/Avsresize
Actually you can use any other framerate doubler (motion interpolator, like FrameRateConverter etc.) instead of RIFE.
Busty
16th May 2026, 15:55
Thanks, yeah, I did that, and now I'm stuck at how to change the script so it works with FrameRateConverter instead of RIFE.
I did get it to load, but now the colors are all over the place. I guess the syntax has to be changed to match FramerateConverter, but I don't know how to do that (yes i looked at the syntax and yes, I'm obviously that bad in scripting still...)
I tried it just like this:
ConverttoYV16(interlaced=true)
assumeBFF()
SeparateFields()
ipol = FrameRateConverter(SelectOdd().AssumeFrameBased()).SelectOdd().Loop(2,0,0)
even = MergeChroma(SelectEven(), ipol)
Interleave(even,SelectOdd())
Weave()
QTGMC(preset="slow")
###########
function FrameRateConverter(clip source)
{
source.z_ConvertFormat(pixel_type="RGBPS", colorspace_op="601:auto:auto:limited=>rgb:same:same:full")
z_ConvertFormat(pixel_type=source.pixeltype, colorspace_op="rgb:auto:auto:full=>601:same:same:limited")
}
##########
Sharc
16th May 2026, 16:41
Thanks, yeah, I did that, and now I'm stuck at how to change the script so it works with FrameRateConverter instead of RIFE.
I did get it to load, but now the colors are all over the place. I guess the syntax has to be changed to match FramerateConverter, but I don't know how to do that (yes i looked at the syntax and yes, I'm obviously that bad in scripting still...)
I tried it just like this: .............
Sorry, your script doesn't make sense at all.
FrameRateConverter is found here:
http://avisynth.nl/index.php/FrameRateConverter
Study its documentation to use it properly.
If RIFE works just stay with it. No reason to change to anything else.
Busty
17th May 2026, 08:12
No, RIFE does not work. I get a system exemption error on the lines calling RIFE. That's why I wanted to use FrameRateDoubler instead. But I really am sorry (and a bit embarrassed), I am lost when trying to make it work. I just don't know how to phrase the interpolation for FrameRateDoubler, even after looking at the info pages of FrameRateDoubler and RIFE. Can I ask for help on how to replace RIFE with FrameRateDoubler?
https://github.com/Asd-g/AviSynthPlus-RIFE/tree/main
Busty
17th May 2026, 09:52
Thanks rgr, I've seen that site before, but RIFE still does not work on my system. It's a bit special. I got this all running on a Mac and installed it via PlayOnMac, so some things I just can't get to work under the circumstances.
Sharc
17th May 2026, 10:58
Try this using FrameRateConverter:
AssumeBFF()
SeparateFields()
ipol = FrameRateConverter(SelectOdd()).SelectOdd().Loop(2,0,0)
even = MergeChroma(SelectEven(), ipol)
Interleave(even,SelectOdd())
Weave()
QTGMC()
ChromaShiftSP(x=4,y=4) #align the chroma with the luma
Emulgator
17th May 2026, 15:20
Busty, I just threw all my .avsi on notepad++ and searched for ex_bs:
475 hits, most are in Dogway's scripts.
If you follow your assertion it will tell which script path and line it was called from and then go searching from there.
Busty
17th May 2026, 20:31
@ Sharc: This works perfect for me! Thank you so much!
@ Emulgator: While this did the trick and I found it in ExTools, VDub wasn't done complaining about other functions missing. Found them all, but in the end I got a "system Excemption " again. QTGMC+ (or QTGMCp) doesn't work for me, I'm afraid.
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.